ece34934f9c90de80baa4c9918920049d8ea22bb
[socket_wrapper.git] / src / socket_wrapper.c
1 /*
2  * BSD 3-Clause License
3  *
4  * Copyright (c) 2005-2008, Jelmer Vernooij <jelmer@samba.org>
5  * Copyright (c) 2006-2018, Stefan Metzmacher <metze@samba.org>
6  * Copyright (c) 2013-2018, Andreas Schneider <asn@samba.org>
7  * Copyright (c) 2014-2017, Michael Adam <obnox@samba.org>
8  * Copyright (c) 2016-2018, Anoop C S <anoopcs@redhat.com>
9  * All rights reserved.
10  *
11  * Redistribution and use in source and binary forms, with or without
12  * modification, are permitted provided that the following conditions
13  * are met:
14  *
15  * 1. Redistributions of source code must retain the above copyright
16  *    notice, this list of conditions and the following disclaimer.
17  *
18  * 2. Redistributions in binary form must reproduce the above copyright
19  *    notice, this list of conditions and the following disclaimer in the
20  *    documentation and/or other materials provided with the distribution.
21  *
22  * 3. Neither the name of the author nor the names of its contributors
23  *    may be used to endorse or promote products derived from this software
24  *    without specific prior written permission.
25  *
26  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
27  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
28  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
29  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
30  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
31  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
32  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
33  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
34  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
35  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
36  * SUCH DAMAGE.
37  */
38
39 /*
40    Socket wrapper library. Passes all socket communication over
41    unix domain sockets if the environment variable SOCKET_WRAPPER_DIR
42    is set.
43 */
44
45 #include "config.h"
46
47 #include <sys/types.h>
48 #include <sys/time.h>
49 #include <sys/stat.h>
50 #include <sys/socket.h>
51 #include <sys/ioctl.h>
52 #ifdef HAVE_SYS_FILIO_H
53 #include <sys/filio.h>
54 #endif
55 #ifdef HAVE_SYS_SIGNALFD_H
56 #include <sys/signalfd.h>
57 #endif
58 #ifdef HAVE_SYS_EVENTFD_H
59 #include <sys/eventfd.h>
60 #endif
61 #ifdef HAVE_SYS_TIMERFD_H
62 #include <sys/timerfd.h>
63 #endif
64 #include <sys/uio.h>
65 #include <errno.h>
66 #include <sys/un.h>
67 #include <netinet/in.h>
68 #include <netinet/tcp.h>
69 #ifdef HAVE_NETINET_TCP_FSM_H
70 #include <netinet/tcp_fsm.h>
71 #endif
72 #include <arpa/inet.h>
73 #include <fcntl.h>
74 #include <stdlib.h>
75 #include <string.h>
76 #include <stdio.h>
77 #include <stdint.h>
78 #include <stdarg.h>
79 #include <stdbool.h>
80 #include <unistd.h>
81 #ifdef HAVE_GNU_LIB_NAMES_H
82 #include <gnu/lib-names.h>
83 #endif
84 #ifdef HAVE_RPC_RPC_H
85 #include <rpc/rpc.h>
86 #endif
87 #include <pthread.h>
88
89 enum swrap_dbglvl_e {
90         SWRAP_LOG_ERROR = 0,
91         SWRAP_LOG_WARN,
92         SWRAP_LOG_DEBUG,
93         SWRAP_LOG_TRACE
94 };
95
96 /* GCC have printf type attribute check. */
97 #ifdef HAVE_FUNCTION_ATTRIBUTE_FORMAT
98 #define PRINTF_ATTRIBUTE(a,b) __attribute__ ((__format__ (__printf__, a, b)))
99 #else
100 #define PRINTF_ATTRIBUTE(a,b)
101 #endif /* HAVE_FUNCTION_ATTRIBUTE_FORMAT */
102
103 #ifdef HAVE_CONSTRUCTOR_ATTRIBUTE
104 #define CONSTRUCTOR_ATTRIBUTE __attribute__ ((constructor))
105 #else
106 #define CONSTRUCTOR_ATTRIBUTE
107 #endif /* HAVE_CONSTRUCTOR_ATTRIBUTE */
108
109 #ifdef HAVE_DESTRUCTOR_ATTRIBUTE
110 #define DESTRUCTOR_ATTRIBUTE __attribute__ ((destructor))
111 #else
112 #define DESTRUCTOR_ATTRIBUTE
113 #endif
114
115 #ifndef FALL_THROUGH
116 # ifdef HAVE_FALLTHROUGH_ATTRIBUTE
117 #  define FALL_THROUGH __attribute__ ((fallthrough))
118 # else /* HAVE_FALLTHROUGH_ATTRIBUTE */
119 #  define FALL_THROUGH ((void)0)
120 # endif /* HAVE_FALLTHROUGH_ATTRIBUTE */
121 #endif /* FALL_THROUGH */
122
123 #ifdef HAVE_ADDRESS_SANITIZER_ATTRIBUTE
124 #define DO_NOT_SANITIZE_ADDRESS_ATTRIBUTE __attribute__((no_sanitize_address))
125 #else
126 #define DO_NOT_SANITIZE_ADDRESS_ATTRIBUTE
127 #endif
128
129 #ifdef HAVE_GCC_THREAD_LOCAL_STORAGE
130 # define SWRAP_THREAD __thread
131 #else
132 # define SWRAP_THREAD
133 #endif
134
135 #ifndef MIN
136 #define MIN(a,b) ((a)<(b)?(a):(b))
137 #endif
138
139 #ifndef ZERO_STRUCT
140 #define ZERO_STRUCT(x) memset((char *)&(x), 0, sizeof(x))
141 #endif
142
143 #ifndef ZERO_STRUCTP
144 #define ZERO_STRUCTP(x) do { \
145                 if ((x) != NULL) \
146                         memset((char *)(x), 0, sizeof(*(x))); \
147         } while(0)
148 #endif
149
150 #ifndef SAFE_FREE
151 #define SAFE_FREE(x) do { if ((x) != NULL) {free(x); (x)=NULL;} } while(0)
152 #endif
153
154 #ifndef discard_const
155 #define discard_const(ptr) ((void *)((uintptr_t)(ptr)))
156 #endif
157
158 #ifndef discard_const_p
159 #define discard_const_p(type, ptr) ((type *)discard_const(ptr))
160 #endif
161
162 #define UNUSED(x) (void)(x)
163
164 #ifdef IPV6_PKTINFO
165 # ifndef IPV6_RECVPKTINFO
166 #  define IPV6_RECVPKTINFO IPV6_PKTINFO
167 # endif /* IPV6_RECVPKTINFO */
168 #endif /* IPV6_PKTINFO */
169
170 /*
171  * On BSD IP_PKTINFO has a different name because during
172  * the time when they implemented it, there was no RFC.
173  * The name for IPv6 is the same as on Linux.
174  */
175 #ifndef IP_PKTINFO
176 # ifdef IP_RECVDSTADDR
177 #  define IP_PKTINFO IP_RECVDSTADDR
178 # endif
179 #endif
180
181 #define socket_wrapper_init_mutex(m) \
182         _socket_wrapper_init_mutex(m, #m)
183
184 /* Add new global locks here please */
185 # define SWRAP_REINIT_ALL do { \
186         int ret; \
187         ret = socket_wrapper_init_mutex(&sockets_mutex); \
188         if (ret != 0) exit(-1); \
189         ret = socket_wrapper_init_mutex(&socket_reset_mutex); \
190         if (ret != 0) exit(-1); \
191         ret = socket_wrapper_init_mutex(&first_free_mutex); \
192         if (ret != 0) exit(-1); \
193         ret = socket_wrapper_init_mutex(&sockets_si_global); \
194         if (ret != 0) exit(-1); \
195         ret = socket_wrapper_init_mutex(&autobind_start_mutex); \
196         if (ret != 0) exit(-1); \
197         ret = socket_wrapper_init_mutex(&pcap_dump_mutex); \
198         if (ret != 0) exit(-1); \
199         ret = socket_wrapper_init_mutex(&mtu_update_mutex); \
200         if (ret != 0) exit(-1); \
201 } while(0)
202
203 # define SWRAP_LOCK_ALL do { \
204         swrap_mutex_lock(&sockets_mutex); \
205         swrap_mutex_lock(&socket_reset_mutex); \
206         swrap_mutex_lock(&first_free_mutex); \
207         swrap_mutex_lock(&sockets_si_global); \
208         swrap_mutex_lock(&autobind_start_mutex); \
209         swrap_mutex_lock(&pcap_dump_mutex); \
210         swrap_mutex_lock(&mtu_update_mutex); \
211 } while(0)
212
213 # define SWRAP_UNLOCK_ALL do { \
214         swrap_mutex_unlock(&mtu_update_mutex); \
215         swrap_mutex_unlock(&pcap_dump_mutex); \
216         swrap_mutex_unlock(&autobind_start_mutex); \
217         swrap_mutex_unlock(&sockets_si_global); \
218         swrap_mutex_unlock(&first_free_mutex); \
219         swrap_mutex_unlock(&socket_reset_mutex); \
220         swrap_mutex_unlock(&sockets_mutex); \
221 } while(0)
222
223 #define SOCKET_INFO_CONTAINER(si) \
224         (struct socket_info_container *)(si)
225
226 #define SWRAP_LOCK_SI(si) do { \
227         struct socket_info_container *sic = SOCKET_INFO_CONTAINER(si); \
228         if (sic != NULL) { \
229                 swrap_mutex_lock(&sockets_si_global); \
230         } else { \
231                 abort(); \
232         } \
233 } while(0)
234
235 #define SWRAP_UNLOCK_SI(si) do { \
236         struct socket_info_container *sic = SOCKET_INFO_CONTAINER(si); \
237         if (sic != NULL) { \
238                 swrap_mutex_unlock(&sockets_si_global); \
239         } else { \
240                 abort(); \
241         } \
242 } while(0)
243
244 #if defined(HAVE_GETTIMEOFDAY_TZ) || defined(HAVE_GETTIMEOFDAY_TZ_VOID)
245 #define swrapGetTimeOfDay(tval) gettimeofday(tval,NULL)
246 #else
247 #define swrapGetTimeOfDay(tval) gettimeofday(tval)
248 #endif
249
250 /* we need to use a very terse format here as IRIX 6.4 silently
251    truncates names to 16 chars, so if we use a longer name then we
252    can't tell which port a packet came from with recvfrom()
253
254    with this format we have 8 chars left for the directory name
255 */
256 #define SOCKET_FORMAT "%c%02X%04X"
257 #define SOCKET_TYPE_CHAR_TCP            'T'
258 #define SOCKET_TYPE_CHAR_UDP            'U'
259 #define SOCKET_TYPE_CHAR_TCP_V6         'X'
260 #define SOCKET_TYPE_CHAR_UDP_V6         'Y'
261
262 /*
263  * Set the packet MTU to 1500 bytes for stream sockets to make it it easier to
264  * format PCAP capture files (as the caller will simply continue from here).
265  */
266 #define SOCKET_WRAPPER_MTU_DEFAULT 1500
267 #define SOCKET_WRAPPER_MTU_MIN     512
268 #define SOCKET_WRAPPER_MTU_MAX     32768
269
270 #define SOCKET_MAX_SOCKETS 1024
271
272 /*
273  * Maximum number of socket_info structures that can
274  * be used. Can be overriden by the environment variable
275  * SOCKET_WRAPPER_MAX_SOCKETS.
276  */
277 #define SOCKET_WRAPPER_MAX_SOCKETS_DEFAULT 65535
278
279 #define SOCKET_WRAPPER_MAX_SOCKETS_LIMIT 262140
280
281 /* This limit is to avoid broadcast sendto() needing to stat too many
282  * files.  It may be raised (with a performance cost) to up to 254
283  * without changing the format above */
284 #define MAX_WRAPPED_INTERFACES 64
285
286 struct swrap_address {
287         socklen_t sa_socklen;
288         union {
289                 struct sockaddr s;
290                 struct sockaddr_in in;
291 #ifdef HAVE_IPV6
292                 struct sockaddr_in6 in6;
293 #endif
294                 struct sockaddr_un un;
295                 struct sockaddr_storage ss;
296         } sa;
297 };
298
299 static int first_free;
300
301 struct socket_info
302 {
303         /*
304          * Remember to update swrap_unix_scm_right_magic
305          * on any change.
306          */
307
308         int family;
309         int type;
310         int protocol;
311         int bound;
312         int bcast;
313         int is_server;
314         int connected;
315         int defer_connect;
316         int pktinfo;
317         int tcp_nodelay;
318         int listening;
319         int fd_passed;
320
321         /* The unix path so we can unlink it on close() */
322         struct sockaddr_un un_addr;
323
324         struct swrap_address bindname;
325         struct swrap_address myname;
326         struct swrap_address peername;
327
328         struct {
329                 unsigned long pck_snd;
330                 unsigned long pck_rcv;
331         } io;
332 };
333
334 struct socket_info_meta
335 {
336         unsigned int refcount;
337         int next_free;
338         /*
339          * As long as we don't use shared memory
340          * for the sockets array, we use
341          * sockets_si_global as a single mutex.
342          *
343          * pthread_mutex_t mutex;
344          */
345 };
346
347 struct socket_info_container
348 {
349         struct socket_info info;
350         struct socket_info_meta meta;
351 };
352
353 static struct socket_info_container *sockets;
354
355 static size_t socket_info_max = 0;
356
357 /*
358  * Allocate the socket array always on the limit value. We want it to be
359  * at least bigger than the default so if we reach the limit we can
360  * still deal with duplicate fds pointing to the same socket_info.
361  */
362 static size_t socket_fds_max = SOCKET_WRAPPER_MAX_SOCKETS_LIMIT;
363
364 /* Hash table to map fds to corresponding socket_info index */
365 static int *socket_fds_idx;
366
367 /* Mutex for syncronizing port selection during swrap_auto_bind() */
368 static pthread_mutex_t autobind_start_mutex = PTHREAD_MUTEX_INITIALIZER;
369
370 /* Mutex to guard the initialization of array of socket_info structures */
371 static pthread_mutex_t sockets_mutex = PTHREAD_MUTEX_INITIALIZER;
372
373 /* Mutex to guard the socket reset in swrap_close() and swrap_remove_stale() */
374 static pthread_mutex_t socket_reset_mutex = PTHREAD_MUTEX_INITIALIZER;
375
376 /* Mutex to synchronize access to first free index in socket_info array */
377 static pthread_mutex_t first_free_mutex = PTHREAD_MUTEX_INITIALIZER;
378
379 /*
380  * Mutex to synchronize access to to socket_info structures
381  * We use a single global mutex in order to avoid leaking
382  * ~ 38M copy on write memory per fork.
383  * max_sockets=65535 * sizeof(struct socket_info_container)=592 = 38796720
384  */
385 static pthread_mutex_t sockets_si_global = PTHREAD_MUTEX_INITIALIZER;
386
387 /* Mutex to synchronize access to packet capture dump file */
388 static pthread_mutex_t pcap_dump_mutex = PTHREAD_MUTEX_INITIALIZER;
389
390 /* Mutex for synchronizing mtu value fetch*/
391 static pthread_mutex_t mtu_update_mutex = PTHREAD_MUTEX_INITIALIZER;
392
393 /* Function prototypes */
394
395 bool socket_wrapper_enabled(void);
396
397 #if ! defined(HAVE_CONSTRUCTOR_ATTRIBUTE) && defined(HAVE_PRAGMA_INIT)
398 /* xlC and other oldschool compilers support (only) this */
399 #pragma init (swrap_constructor)
400 #endif
401 void swrap_constructor(void) CONSTRUCTOR_ATTRIBUTE;
402 #if ! defined(HAVE_DESTRUCTOR_ATTRIBUTE) && defined(HAVE_PRAGMA_FINI)
403 #pragma fini (swrap_destructor)
404 #endif
405 void swrap_destructor(void) DESTRUCTOR_ATTRIBUTE;
406
407 #ifndef HAVE_GETPROGNAME
408 static const char *getprogname(void)
409 {
410 #if defined(HAVE_PROGRAM_INVOCATION_SHORT_NAME)
411         return program_invocation_short_name;
412 #elif defined(HAVE_GETEXECNAME)
413         return getexecname();
414 #else
415         return NULL;
416 #endif /* HAVE_PROGRAM_INVOCATION_SHORT_NAME */
417 }
418 #endif /* HAVE_GETPROGNAME */
419
420 static void swrap_log(enum swrap_dbglvl_e dbglvl, const char *func, const char *format, ...) PRINTF_ATTRIBUTE(3, 4);
421 # define SWRAP_LOG(dbglvl, ...) swrap_log((dbglvl), __func__, __VA_ARGS__)
422
423 static void swrap_log(enum swrap_dbglvl_e dbglvl,
424                       const char *func,
425                       const char *format, ...)
426 {
427         char buffer[1024];
428         va_list va;
429         const char *d;
430         unsigned int lvl = 0;
431         const char *prefix = "SWRAP";
432         const char *progname = getprogname();
433
434         d = getenv("SOCKET_WRAPPER_DEBUGLEVEL");
435         if (d != NULL) {
436                 lvl = atoi(d);
437         }
438
439         if (lvl < dbglvl) {
440                 return;
441         }
442
443         va_start(va, format);
444         vsnprintf(buffer, sizeof(buffer), format, va);
445         va_end(va);
446
447         switch (dbglvl) {
448                 case SWRAP_LOG_ERROR:
449                         prefix = "SWRAP_ERROR";
450                         break;
451                 case SWRAP_LOG_WARN:
452                         prefix = "SWRAP_WARN";
453                         break;
454                 case SWRAP_LOG_DEBUG:
455                         prefix = "SWRAP_DEBUG";
456                         break;
457                 case SWRAP_LOG_TRACE:
458                         prefix = "SWRAP_TRACE";
459                         break;
460         }
461
462         if (progname == NULL) {
463                 progname = "<unknown>";
464         }
465
466         fprintf(stderr,
467                 "%s[%s (%u)] - %s: %s\n",
468                 prefix,
469                 progname,
470                 (unsigned int)getpid(),
471                 func,
472                 buffer);
473 }
474
475 /*********************************************************
476  * SWRAP LOADING LIBC FUNCTIONS
477  *********************************************************/
478
479 #include <dlfcn.h>
480
481 #ifdef HAVE_ACCEPT4
482 typedef int (*__libc_accept4)(int sockfd,
483                               struct sockaddr *addr,
484                               socklen_t *addrlen,
485                               int flags);
486 #else
487 typedef int (*__libc_accept)(int sockfd,
488                              struct sockaddr *addr,
489                              socklen_t *addrlen);
490 #endif
491 typedef int (*__libc_bind)(int sockfd,
492                            const struct sockaddr *addr,
493                            socklen_t addrlen);
494 typedef int (*__libc_close)(int fd);
495 typedef int (*__libc_connect)(int sockfd,
496                               const struct sockaddr *addr,
497                               socklen_t addrlen);
498 typedef int (*__libc_dup)(int fd);
499 typedef int (*__libc_dup2)(int oldfd, int newfd);
500 typedef int (*__libc_fcntl)(int fd, int cmd, ...);
501 typedef FILE *(*__libc_fopen)(const char *name, const char *mode);
502 #ifdef HAVE_FOPEN64
503 typedef FILE *(*__libc_fopen64)(const char *name, const char *mode);
504 #endif
505 #ifdef HAVE_EVENTFD
506 typedef int (*__libc_eventfd)(int count, int flags);
507 #endif
508 typedef int (*__libc_getpeername)(int sockfd,
509                                   struct sockaddr *addr,
510                                   socklen_t *addrlen);
511 typedef int (*__libc_getsockname)(int sockfd,
512                                   struct sockaddr *addr,
513                                   socklen_t *addrlen);
514 typedef int (*__libc_getsockopt)(int sockfd,
515                                int level,
516                                int optname,
517                                void *optval,
518                                socklen_t *optlen);
519 typedef int (*__libc_ioctl)(int d, unsigned long int request, ...);
520 typedef int (*__libc_listen)(int sockfd, int backlog);
521 typedef int (*__libc_open)(const char *pathname, int flags, ...);
522 #ifdef HAVE_OPEN64
523 typedef int (*__libc_open64)(const char *pathname, int flags, ...);
524 #endif /* HAVE_OPEN64 */
525 typedef int (*__libc_openat)(int dirfd, const char *path, int flags, ...);
526 typedef int (*__libc_pipe)(int pipefd[2]);
527 typedef int (*__libc_read)(int fd, void *buf, size_t count);
528 typedef ssize_t (*__libc_readv)(int fd, const struct iovec *iov, int iovcnt);
529 typedef int (*__libc_recv)(int sockfd, void *buf, size_t len, int flags);
530 typedef int (*__libc_recvfrom)(int sockfd,
531                              void *buf,
532                              size_t len,
533                              int flags,
534                              struct sockaddr *src_addr,
535                              socklen_t *addrlen);
536 typedef int (*__libc_recvmsg)(int sockfd, const struct msghdr *msg, int flags);
537 typedef int (*__libc_send)(int sockfd, const void *buf, size_t len, int flags);
538 typedef int (*__libc_sendmsg)(int sockfd, const struct msghdr *msg, int flags);
539 typedef int (*__libc_sendto)(int sockfd,
540                            const void *buf,
541                            size_t len,
542                            int flags,
543                            const  struct sockaddr *dst_addr,
544                            socklen_t addrlen);
545 typedef int (*__libc_setsockopt)(int sockfd,
546                                int level,
547                                int optname,
548                                const void *optval,
549                                socklen_t optlen);
550 #ifdef HAVE_SIGNALFD
551 typedef int (*__libc_signalfd)(int fd, const sigset_t *mask, int flags);
552 #endif
553 typedef int (*__libc_socket)(int domain, int type, int protocol);
554 typedef int (*__libc_socketpair)(int domain, int type, int protocol, int sv[2]);
555 #ifdef HAVE_TIMERFD_CREATE
556 typedef int (*__libc_timerfd_create)(int clockid, int flags);
557 #endif
558 typedef ssize_t (*__libc_write)(int fd, const void *buf, size_t count);
559 typedef ssize_t (*__libc_writev)(int fd, const struct iovec *iov, int iovcnt);
560
561 #define SWRAP_SYMBOL_ENTRY(i) \
562         union { \
563                 __libc_##i f; \
564                 void *obj; \
565         } _libc_##i
566
567 struct swrap_libc_symbols {
568 #ifdef HAVE_ACCEPT4
569         SWRAP_SYMBOL_ENTRY(accept4);
570 #else
571         SWRAP_SYMBOL_ENTRY(accept);
572 #endif
573         SWRAP_SYMBOL_ENTRY(bind);
574         SWRAP_SYMBOL_ENTRY(close);
575         SWRAP_SYMBOL_ENTRY(connect);
576         SWRAP_SYMBOL_ENTRY(dup);
577         SWRAP_SYMBOL_ENTRY(dup2);
578         SWRAP_SYMBOL_ENTRY(fcntl);
579         SWRAP_SYMBOL_ENTRY(fopen);
580 #ifdef HAVE_FOPEN64
581         SWRAP_SYMBOL_ENTRY(fopen64);
582 #endif
583 #ifdef HAVE_EVENTFD
584         SWRAP_SYMBOL_ENTRY(eventfd);
585 #endif
586         SWRAP_SYMBOL_ENTRY(getpeername);
587         SWRAP_SYMBOL_ENTRY(getsockname);
588         SWRAP_SYMBOL_ENTRY(getsockopt);
589         SWRAP_SYMBOL_ENTRY(ioctl);
590         SWRAP_SYMBOL_ENTRY(listen);
591         SWRAP_SYMBOL_ENTRY(open);
592 #ifdef HAVE_OPEN64
593         SWRAP_SYMBOL_ENTRY(open64);
594 #endif
595         SWRAP_SYMBOL_ENTRY(openat);
596         SWRAP_SYMBOL_ENTRY(pipe);
597         SWRAP_SYMBOL_ENTRY(read);
598         SWRAP_SYMBOL_ENTRY(readv);
599         SWRAP_SYMBOL_ENTRY(recv);
600         SWRAP_SYMBOL_ENTRY(recvfrom);
601         SWRAP_SYMBOL_ENTRY(recvmsg);
602         SWRAP_SYMBOL_ENTRY(send);
603         SWRAP_SYMBOL_ENTRY(sendmsg);
604         SWRAP_SYMBOL_ENTRY(sendto);
605         SWRAP_SYMBOL_ENTRY(setsockopt);
606 #ifdef HAVE_SIGNALFD
607         SWRAP_SYMBOL_ENTRY(signalfd);
608 #endif
609         SWRAP_SYMBOL_ENTRY(socket);
610         SWRAP_SYMBOL_ENTRY(socketpair);
611 #ifdef HAVE_TIMERFD_CREATE
612         SWRAP_SYMBOL_ENTRY(timerfd_create);
613 #endif
614         SWRAP_SYMBOL_ENTRY(write);
615         SWRAP_SYMBOL_ENTRY(writev);
616 };
617
618 struct swrap {
619         struct {
620                 void *handle;
621                 void *socket_handle;
622                 struct swrap_libc_symbols symbols;
623         } libc;
624 };
625
626 static struct swrap swrap;
627
628 /* prototypes */
629 static char *socket_wrapper_dir(void);
630
631 #define LIBC_NAME "libc.so"
632
633 enum swrap_lib {
634     SWRAP_LIBC,
635     SWRAP_LIBSOCKET,
636 };
637
638 static const char *swrap_str_lib(enum swrap_lib lib)
639 {
640         switch (lib) {
641         case SWRAP_LIBC:
642                 return "libc";
643         case SWRAP_LIBSOCKET:
644                 return "libsocket";
645         }
646
647         /* Compiler would warn us about unhandled enum value if we get here */
648         return "unknown";
649 }
650
651 static void *swrap_load_lib_handle(enum swrap_lib lib)
652 {
653         int flags = RTLD_LAZY;
654         void *handle = NULL;
655         int i;
656
657 #ifdef RTLD_DEEPBIND
658         const char *env_preload = getenv("LD_PRELOAD");
659         const char *env_deepbind = getenv("SOCKET_WRAPPER_DISABLE_DEEPBIND");
660         bool enable_deepbind = true;
661
662         /* Don't do a deepbind if we run with libasan */
663         if (env_preload != NULL && strlen(env_preload) < 1024) {
664                 const char *p = strstr(env_preload, "libasan.so");
665                 if (p != NULL) {
666                         enable_deepbind = false;
667                 }
668         }
669
670         if (env_deepbind != NULL && strlen(env_deepbind) >= 1) {
671                 enable_deepbind = false;
672         }
673
674         if (enable_deepbind) {
675                 flags |= RTLD_DEEPBIND;
676         }
677 #endif
678
679         switch (lib) {
680         case SWRAP_LIBSOCKET:
681 #ifdef HAVE_LIBSOCKET
682                 handle = swrap.libc.socket_handle;
683                 if (handle == NULL) {
684                         for (i = 10; i >= 0; i--) {
685                                 char soname[256] = {0};
686
687                                 snprintf(soname, sizeof(soname), "libsocket.so.%d", i);
688                                 handle = dlopen(soname, flags);
689                                 if (handle != NULL) {
690                                         break;
691                                 }
692                         }
693
694                         swrap.libc.socket_handle = handle;
695                 }
696                 break;
697 #endif
698         case SWRAP_LIBC:
699                 handle = swrap.libc.handle;
700 #ifdef LIBC_SO
701                 if (handle == NULL) {
702                         handle = dlopen(LIBC_SO, flags);
703
704                         swrap.libc.handle = handle;
705                 }
706 #endif
707                 if (handle == NULL) {
708                         for (i = 10; i >= 0; i--) {
709                                 char soname[256] = {0};
710
711                                 snprintf(soname, sizeof(soname), "libc.so.%d", i);
712                                 handle = dlopen(soname, flags);
713                                 if (handle != NULL) {
714                                         break;
715                                 }
716                         }
717
718                         swrap.libc.handle = handle;
719                 }
720                 break;
721         }
722
723         if (handle == NULL) {
724 #ifdef RTLD_NEXT
725                 handle = swrap.libc.handle = swrap.libc.socket_handle = RTLD_NEXT;
726 #else
727                 SWRAP_LOG(SWRAP_LOG_ERROR,
728                           "Failed to dlopen library: %s",
729                           dlerror());
730                 exit(-1);
731 #endif
732         }
733
734         return handle;
735 }
736
737 static void *_swrap_bind_symbol(enum swrap_lib lib, const char *fn_name)
738 {
739         void *handle;
740         void *func;
741
742         handle = swrap_load_lib_handle(lib);
743
744         func = dlsym(handle, fn_name);
745         if (func == NULL) {
746                 SWRAP_LOG(SWRAP_LOG_ERROR,
747                           "Failed to find %s: %s",
748                           fn_name,
749                           dlerror());
750                 exit(-1);
751         }
752
753         SWRAP_LOG(SWRAP_LOG_TRACE,
754                   "Loaded %s from %s",
755                   fn_name,
756                   swrap_str_lib(lib));
757
758         return func;
759 }
760
761 #define swrap_mutex_lock(m) _swrap_mutex_lock(m, #m, __func__, __LINE__)
762 static void _swrap_mutex_lock(pthread_mutex_t *mutex, const char *name, const char *caller, unsigned line)
763 {
764         int ret;
765
766         ret = pthread_mutex_lock(mutex);
767         if (ret != 0) {
768                 SWRAP_LOG(SWRAP_LOG_ERROR, "PID(%d):PPID(%d): %s(%u): Couldn't lock pthread mutex(%s) - %s",
769                           getpid(), getppid(), caller, line, name, strerror(ret));
770                 abort();
771         }
772 }
773
774 #define swrap_mutex_unlock(m) _swrap_mutex_unlock(m, #m, __func__, __LINE__)
775 static void _swrap_mutex_unlock(pthread_mutex_t *mutex, const char *name, const char *caller, unsigned line)
776 {
777         int ret;
778
779         ret = pthread_mutex_unlock(mutex);
780         if (ret != 0) {
781                 SWRAP_LOG(SWRAP_LOG_ERROR, "PID(%d):PPID(%d): %s(%u): Couldn't unlock pthread mutex(%s) - %s",
782                           getpid(), getppid(), caller, line, name, strerror(ret));
783                 abort();
784         }
785 }
786
787 /*
788  * These macros have a thread race condition on purpose!
789  *
790  * This is an optimization to avoid locking each time we check if the symbol is
791  * bound.
792  */
793 #define _swrap_bind_symbol_generic(lib, sym_name) do { \
794         swrap.libc.symbols._libc_##sym_name.obj = \
795                 _swrap_bind_symbol(lib, #sym_name); \
796 } while(0);
797
798 #define swrap_bind_symbol_libc(sym_name) \
799         _swrap_bind_symbol_generic(SWRAP_LIBC, sym_name)
800
801 #define swrap_bind_symbol_libsocket(sym_name) \
802         _swrap_bind_symbol_generic(SWRAP_LIBSOCKET, sym_name)
803
804 static void swrap_bind_symbol_all(void);
805
806 /****************************************************************************
807  *                               IMPORTANT
808  ****************************************************************************
809  *
810  * Functions especially from libc need to be loaded individually, you can't
811  * load all at once or gdb will segfault at startup. The same applies to
812  * valgrind and has probably something todo with with the linker.  So we need
813  * load each function at the point it is called the first time.
814  *
815  ****************************************************************************/
816
817 #ifdef HAVE_ACCEPT4
818 static int libc_accept4(int sockfd,
819                         struct sockaddr *addr,
820                         socklen_t *addrlen,
821                         int flags)
822 {
823         swrap_bind_symbol_all();
824
825         return swrap.libc.symbols._libc_accept4.f(sockfd, addr, addrlen, flags);
826 }
827
828 #else /* HAVE_ACCEPT4 */
829
830 static int libc_accept(int sockfd, struct sockaddr *addr, socklen_t *addrlen)
831 {
832         swrap_bind_symbol_all();
833
834         return swrap.libc.symbols._libc_accept.f(sockfd, addr, addrlen);
835 }
836 #endif /* HAVE_ACCEPT4 */
837
838 static int libc_bind(int sockfd,
839                      const struct sockaddr *addr,
840                      socklen_t addrlen)
841 {
842         swrap_bind_symbol_all();
843
844         return swrap.libc.symbols._libc_bind.f(sockfd, addr, addrlen);
845 }
846
847 static int libc_close(int fd)
848 {
849         swrap_bind_symbol_all();
850
851         return swrap.libc.symbols._libc_close.f(fd);
852 }
853
854 static int libc_connect(int sockfd,
855                         const struct sockaddr *addr,
856                         socklen_t addrlen)
857 {
858         swrap_bind_symbol_all();
859
860         return swrap.libc.symbols._libc_connect.f(sockfd, addr, addrlen);
861 }
862
863 static int libc_dup(int fd)
864 {
865         swrap_bind_symbol_all();
866
867         return swrap.libc.symbols._libc_dup.f(fd);
868 }
869
870 static int libc_dup2(int oldfd, int newfd)
871 {
872         swrap_bind_symbol_all();
873
874         return swrap.libc.symbols._libc_dup2.f(oldfd, newfd);
875 }
876
877 #ifdef HAVE_EVENTFD
878 static int libc_eventfd(int count, int flags)
879 {
880         swrap_bind_symbol_all();
881
882         return swrap.libc.symbols._libc_eventfd.f(count, flags);
883 }
884 #endif
885
886 DO_NOT_SANITIZE_ADDRESS_ATTRIBUTE
887 static int libc_vfcntl(int fd, int cmd, va_list ap)
888 {
889         void *arg;
890         int rc;
891
892         swrap_bind_symbol_all();
893
894         arg = va_arg(ap, void *);
895
896         rc = swrap.libc.symbols._libc_fcntl.f(fd, cmd, arg);
897
898         return rc;
899 }
900
901 static int libc_getpeername(int sockfd,
902                             struct sockaddr *addr,
903                             socklen_t *addrlen)
904 {
905         swrap_bind_symbol_all();
906
907         return swrap.libc.symbols._libc_getpeername.f(sockfd, addr, addrlen);
908 }
909
910 static int libc_getsockname(int sockfd,
911                             struct sockaddr *addr,
912                             socklen_t *addrlen)
913 {
914         swrap_bind_symbol_all();
915
916         return swrap.libc.symbols._libc_getsockname.f(sockfd, addr, addrlen);
917 }
918
919 static int libc_getsockopt(int sockfd,
920                            int level,
921                            int optname,
922                            void *optval,
923                            socklen_t *optlen)
924 {
925         swrap_bind_symbol_all();
926
927         return swrap.libc.symbols._libc_getsockopt.f(sockfd,
928                                                      level,
929                                                      optname,
930                                                      optval,
931                                                      optlen);
932 }
933
934 DO_NOT_SANITIZE_ADDRESS_ATTRIBUTE
935 static int libc_vioctl(int d, unsigned long int request, va_list ap)
936 {
937         void *arg;
938         int rc;
939
940         swrap_bind_symbol_all();
941
942         arg = va_arg(ap, void *);
943
944         rc = swrap.libc.symbols._libc_ioctl.f(d, request, arg);
945
946         return rc;
947 }
948
949 static int libc_listen(int sockfd, int backlog)
950 {
951         swrap_bind_symbol_all();
952
953         return swrap.libc.symbols._libc_listen.f(sockfd, backlog);
954 }
955
956 static FILE *libc_fopen(const char *name, const char *mode)
957 {
958         swrap_bind_symbol_all();
959
960         return swrap.libc.symbols._libc_fopen.f(name, mode);
961 }
962
963 #ifdef HAVE_FOPEN64
964 static FILE *libc_fopen64(const char *name, const char *mode)
965 {
966         swrap_bind_symbol_all();
967
968         return swrap.libc.symbols._libc_fopen64.f(name, mode);
969 }
970 #endif /* HAVE_FOPEN64 */
971
972 static int libc_vopen(const char *pathname, int flags, va_list ap)
973 {
974         int mode = 0;
975         int fd;
976
977         swrap_bind_symbol_all();
978
979         if (flags & O_CREAT) {
980                 mode = va_arg(ap, int);
981         }
982         fd = swrap.libc.symbols._libc_open.f(pathname, flags, (mode_t)mode);
983
984         return fd;
985 }
986
987 static int libc_open(const char *pathname, int flags, ...)
988 {
989         va_list ap;
990         int fd;
991
992         va_start(ap, flags);
993         fd = libc_vopen(pathname, flags, ap);
994         va_end(ap);
995
996         return fd;
997 }
998
999 #ifdef HAVE_OPEN64
1000 static int libc_vopen64(const char *pathname, int flags, va_list ap)
1001 {
1002         int mode = 0;
1003         int fd;
1004
1005         swrap_bind_symbol_all();
1006
1007         if (flags & O_CREAT) {
1008                 mode = va_arg(ap, int);
1009         }
1010         fd = swrap.libc.symbols._libc_open64.f(pathname, flags, (mode_t)mode);
1011
1012         return fd;
1013 }
1014 #endif /* HAVE_OPEN64 */
1015
1016 static int libc_vopenat(int dirfd, const char *path, int flags, va_list ap)
1017 {
1018         int mode = 0;
1019         int fd;
1020
1021         swrap_bind_symbol_all();
1022
1023         if (flags & O_CREAT) {
1024                 mode = va_arg(ap, int);
1025         }
1026         fd = swrap.libc.symbols._libc_openat.f(dirfd,
1027                                                path,
1028                                                flags,
1029                                                (mode_t)mode);
1030
1031         return fd;
1032 }
1033
1034 #if 0
1035 static int libc_openat(int dirfd, const char *path, int flags, ...)
1036 {
1037         va_list ap;
1038         int fd;
1039
1040         va_start(ap, flags);
1041         fd = libc_vopenat(dirfd, path, flags, ap);
1042         va_end(ap);
1043
1044         return fd;
1045 }
1046 #endif
1047
1048 static int libc_pipe(int pipefd[2])
1049 {
1050         swrap_bind_symbol_all();
1051
1052         return swrap.libc.symbols._libc_pipe.f(pipefd);
1053 }
1054
1055 static int libc_read(int fd, void *buf, size_t count)
1056 {
1057         swrap_bind_symbol_all();
1058
1059         return swrap.libc.symbols._libc_read.f(fd, buf, count);
1060 }
1061
1062 static ssize_t libc_readv(int fd, const struct iovec *iov, int iovcnt)
1063 {
1064         swrap_bind_symbol_all();
1065
1066         return swrap.libc.symbols._libc_readv.f(fd, iov, iovcnt);
1067 }
1068
1069 static int libc_recv(int sockfd, void *buf, size_t len, int flags)
1070 {
1071         swrap_bind_symbol_all();
1072
1073         return swrap.libc.symbols._libc_recv.f(sockfd, buf, len, flags);
1074 }
1075
1076 static int libc_recvfrom(int sockfd,
1077                          void *buf,
1078                          size_t len,
1079                          int flags,
1080                          struct sockaddr *src_addr,
1081                          socklen_t *addrlen)
1082 {
1083         swrap_bind_symbol_all();
1084
1085         return swrap.libc.symbols._libc_recvfrom.f(sockfd,
1086                                                    buf,
1087                                                    len,
1088                                                    flags,
1089                                                    src_addr,
1090                                                    addrlen);
1091 }
1092
1093 static int libc_recvmsg(int sockfd, struct msghdr *msg, int flags)
1094 {
1095         swrap_bind_symbol_all();
1096
1097         return swrap.libc.symbols._libc_recvmsg.f(sockfd, msg, flags);
1098 }
1099
1100 static int libc_send(int sockfd, const void *buf, size_t len, int flags)
1101 {
1102         swrap_bind_symbol_all();
1103
1104         return swrap.libc.symbols._libc_send.f(sockfd, buf, len, flags);
1105 }
1106
1107 static int libc_sendmsg(int sockfd, const struct msghdr *msg, int flags)
1108 {
1109         swrap_bind_symbol_all();
1110
1111         return swrap.libc.symbols._libc_sendmsg.f(sockfd, msg, flags);
1112 }
1113
1114 static int libc_sendto(int sockfd,
1115                        const void *buf,
1116                        size_t len,
1117                        int flags,
1118                        const  struct sockaddr *dst_addr,
1119                        socklen_t addrlen)
1120 {
1121         swrap_bind_symbol_all();
1122
1123         return swrap.libc.symbols._libc_sendto.f(sockfd,
1124                                                  buf,
1125                                                  len,
1126                                                  flags,
1127                                                  dst_addr,
1128                                                  addrlen);
1129 }
1130
1131 static int libc_setsockopt(int sockfd,
1132                            int level,
1133                            int optname,
1134                            const void *optval,
1135                            socklen_t optlen)
1136 {
1137         swrap_bind_symbol_all();
1138
1139         return swrap.libc.symbols._libc_setsockopt.f(sockfd,
1140                                                      level,
1141                                                      optname,
1142                                                      optval,
1143                                                      optlen);
1144 }
1145
1146 #ifdef HAVE_SIGNALFD
1147 static int libc_signalfd(int fd, const sigset_t *mask, int flags)
1148 {
1149         swrap_bind_symbol_all();
1150
1151         return swrap.libc.symbols._libc_signalfd.f(fd, mask, flags);
1152 }
1153 #endif
1154
1155 static int libc_socket(int domain, int type, int protocol)
1156 {
1157         swrap_bind_symbol_all();
1158
1159         return swrap.libc.symbols._libc_socket.f(domain, type, protocol);
1160 }
1161
1162 static int libc_socketpair(int domain, int type, int protocol, int sv[2])
1163 {
1164         swrap_bind_symbol_all();
1165
1166         return swrap.libc.symbols._libc_socketpair.f(domain, type, protocol, sv);
1167 }
1168
1169 #ifdef HAVE_TIMERFD_CREATE
1170 static int libc_timerfd_create(int clockid, int flags)
1171 {
1172         swrap_bind_symbol_all();
1173
1174         return swrap.libc.symbols._libc_timerfd_create.f(clockid, flags);
1175 }
1176 #endif
1177
1178 static ssize_t libc_write(int fd, const void *buf, size_t count)
1179 {
1180         swrap_bind_symbol_all();
1181
1182         return swrap.libc.symbols._libc_write.f(fd, buf, count);
1183 }
1184
1185 static ssize_t libc_writev(int fd, const struct iovec *iov, int iovcnt)
1186 {
1187         swrap_bind_symbol_all();
1188
1189         return swrap.libc.symbols._libc_writev.f(fd, iov, iovcnt);
1190 }
1191
1192 /* DO NOT call this function during library initialization! */
1193 static void __swrap_bind_symbol_all_once(void)
1194 {
1195 #ifdef HAVE_ACCEPT4
1196         swrap_bind_symbol_libsocket(accept4);
1197 #else
1198         swrap_bind_symbol_libsocket(accept);
1199 #endif
1200         swrap_bind_symbol_libsocket(bind);
1201         swrap_bind_symbol_libc(close);
1202         swrap_bind_symbol_libsocket(connect);
1203         swrap_bind_symbol_libc(dup);
1204         swrap_bind_symbol_libc(dup2);
1205         swrap_bind_symbol_libc(fcntl);
1206         swrap_bind_symbol_libc(fopen);
1207 #ifdef HAVE_FOPEN64
1208         swrap_bind_symbol_libc(fopen64);
1209 #endif
1210 #ifdef HAVE_EVENTFD
1211         swrap_bind_symbol_libc(eventfd);
1212 #endif
1213         swrap_bind_symbol_libsocket(getpeername);
1214         swrap_bind_symbol_libsocket(getsockname);
1215         swrap_bind_symbol_libsocket(getsockopt);
1216         swrap_bind_symbol_libc(ioctl);
1217         swrap_bind_symbol_libsocket(listen);
1218         swrap_bind_symbol_libc(open);
1219 #ifdef HAVE_OPEN64
1220         swrap_bind_symbol_libc(open64);
1221 #endif
1222         swrap_bind_symbol_libc(openat);
1223         swrap_bind_symbol_libsocket(pipe);
1224         swrap_bind_symbol_libc(read);
1225         swrap_bind_symbol_libsocket(readv);
1226         swrap_bind_symbol_libsocket(recv);
1227         swrap_bind_symbol_libsocket(recvfrom);
1228         swrap_bind_symbol_libsocket(recvmsg);
1229         swrap_bind_symbol_libsocket(send);
1230         swrap_bind_symbol_libsocket(sendmsg);
1231         swrap_bind_symbol_libsocket(sendto);
1232         swrap_bind_symbol_libsocket(setsockopt);
1233 #ifdef HAVE_SIGNALFD
1234         swrap_bind_symbol_libsocket(signalfd);
1235 #endif
1236         swrap_bind_symbol_libsocket(socket);
1237         swrap_bind_symbol_libsocket(socketpair);
1238 #ifdef HAVE_TIMERFD_CREATE
1239         swrap_bind_symbol_libc(timerfd_create);
1240 #endif
1241         swrap_bind_symbol_libc(write);
1242         swrap_bind_symbol_libsocket(writev);
1243 }
1244
1245 static void swrap_bind_symbol_all(void)
1246 {
1247         static pthread_once_t all_symbol_binding_once = PTHREAD_ONCE_INIT;
1248
1249         pthread_once(&all_symbol_binding_once, __swrap_bind_symbol_all_once);
1250 }
1251
1252 /*********************************************************
1253  * SWRAP HELPER FUNCTIONS
1254  *********************************************************/
1255
1256 /*
1257  * We return 127.0.0.0 (default) or 10.53.57.0.
1258  *
1259  * This can be controlled by:
1260  * SOCKET_WRAPPER_IPV4_NETWORK=127.0.0.0 (default)
1261  * or
1262  * SOCKET_WRAPPER_IPV4_NETWORK=10.53.57.0
1263  */
1264 static in_addr_t swrap_ipv4_net(void)
1265 {
1266         static int initialized;
1267         static in_addr_t hv;
1268         const char *net_str = NULL;
1269         struct in_addr nv;
1270         int ret;
1271
1272         if (initialized) {
1273                 return hv;
1274         }
1275         initialized = 1;
1276
1277         net_str = getenv("SOCKET_WRAPPER_IPV4_NETWORK");
1278         if (net_str == NULL) {
1279                 net_str = "127.0.0.0";
1280         }
1281
1282         ret = inet_pton(AF_INET, net_str, &nv);
1283         if (ret <= 0) {
1284                 SWRAP_LOG(SWRAP_LOG_ERROR,
1285                           "INVALID IPv4 Network [%s]",
1286                           net_str);
1287                 abort();
1288         }
1289
1290         hv = ntohl(nv.s_addr);
1291
1292         switch (hv) {
1293         case 0x7f000000:
1294                 /* 127.0.0.0 */
1295                 break;
1296         case 0x0a353900:
1297                 /* 10.53.57.0 */
1298                 break;
1299         default:
1300                 SWRAP_LOG(SWRAP_LOG_ERROR,
1301                           "INVALID IPv4 Network [%s][0x%x] should be "
1302                           "127.0.0.0 or 10.53.57.0",
1303                           net_str, (unsigned)hv);
1304                 abort();
1305         }
1306
1307         return hv;
1308 }
1309
1310 /*
1311  * This returns 127.255.255.255 or 10.255.255.255
1312  */
1313 static in_addr_t swrap_ipv4_bcast(void)
1314 {
1315         in_addr_t hv;
1316
1317         hv = swrap_ipv4_net();
1318         hv |= IN_CLASSA_HOST;
1319
1320         return hv;
1321 }
1322
1323 /*
1324  * This returns 127.0.0.${iface} or 10.53.57.${iface}
1325  */
1326 static in_addr_t swrap_ipv4_iface(unsigned int iface)
1327 {
1328         in_addr_t hv;
1329
1330         if (iface == 0 || iface > MAX_WRAPPED_INTERFACES) {
1331                 SWRAP_LOG(SWRAP_LOG_ERROR,
1332                           "swrap_ipv4_iface(%u) invalid!",
1333                           iface);
1334                 abort();
1335                 return -1;
1336         }
1337
1338         hv = swrap_ipv4_net();
1339         hv |= iface;
1340
1341         return hv;
1342 }
1343
1344 #ifdef HAVE_IPV6
1345 /*
1346  * FD00::5357:5FXX
1347  */
1348 static const struct in6_addr *swrap_ipv6(void)
1349 {
1350         static struct in6_addr v;
1351         static int initialized;
1352         int ret;
1353
1354         if (initialized) {
1355                 return &v;
1356         }
1357         initialized = 1;
1358
1359         ret = inet_pton(AF_INET6, "FD00::5357:5F00", &v);
1360         if (ret <= 0) {
1361                 abort();
1362         }
1363
1364         return &v;
1365 }
1366 #endif
1367
1368 static void set_port(int family, int prt, struct swrap_address *addr)
1369 {
1370         switch (family) {
1371         case AF_INET:
1372                 addr->sa.in.sin_port = htons(prt);
1373                 break;
1374 #ifdef HAVE_IPV6
1375         case AF_INET6:
1376                 addr->sa.in6.sin6_port = htons(prt);
1377                 break;
1378 #endif
1379         }
1380 }
1381
1382 static size_t socket_length(int family)
1383 {
1384         switch (family) {
1385         case AF_INET:
1386                 return sizeof(struct sockaddr_in);
1387 #ifdef HAVE_IPV6
1388         case AF_INET6:
1389                 return sizeof(struct sockaddr_in6);
1390 #endif
1391         }
1392         return 0;
1393 }
1394
1395 static struct socket_info *swrap_get_socket_info(int si_index)
1396 {
1397         return (struct socket_info *)(&(sockets[si_index].info));
1398 }
1399
1400 static int swrap_get_refcount(struct socket_info *si)
1401 {
1402         struct socket_info_container *sic = SOCKET_INFO_CONTAINER(si);
1403         return sic->meta.refcount;
1404 }
1405
1406 static void swrap_inc_refcount(struct socket_info *si)
1407 {
1408         struct socket_info_container *sic = SOCKET_INFO_CONTAINER(si);
1409
1410         sic->meta.refcount += 1;
1411 }
1412
1413 static void swrap_dec_refcount(struct socket_info *si)
1414 {
1415         struct socket_info_container *sic = SOCKET_INFO_CONTAINER(si);
1416
1417         sic->meta.refcount -= 1;
1418 }
1419
1420 static int swrap_get_next_free(struct socket_info *si)
1421 {
1422         struct socket_info_container *sic = SOCKET_INFO_CONTAINER(si);
1423
1424         return sic->meta.next_free;
1425 }
1426
1427 static void swrap_set_next_free(struct socket_info *si, int next_free)
1428 {
1429         struct socket_info_container *sic = SOCKET_INFO_CONTAINER(si);
1430
1431         sic->meta.next_free = next_free;
1432 }
1433
1434 static int swrap_un_path(struct sockaddr_un *un,
1435                          const char *swrap_dir,
1436                          char type,
1437                          unsigned int iface,
1438                          unsigned int prt)
1439 {
1440         int ret;
1441
1442         ret = snprintf(un->sun_path,
1443                        sizeof(un->sun_path),
1444                        "%s/"SOCKET_FORMAT,
1445                        swrap_dir,
1446                        type,
1447                        iface,
1448                        prt);
1449         if ((size_t)ret >= sizeof(un->sun_path)) {
1450                 return ENAMETOOLONG;
1451         }
1452
1453         return 0;
1454 }
1455
1456 static int swrap_un_path_EINVAL(struct sockaddr_un *un,
1457                                 const char *swrap_dir)
1458 {
1459         int ret;
1460
1461         ret = snprintf(un->sun_path,
1462                        sizeof(un->sun_path),
1463                        "%s/EINVAL",
1464                        swrap_dir);
1465
1466         if ((size_t)ret >= sizeof(un->sun_path)) {
1467                 return ENAMETOOLONG;
1468         }
1469
1470         return 0;
1471 }
1472
1473 static bool swrap_dir_usable(const char *swrap_dir)
1474 {
1475         struct sockaddr_un un;
1476         int ret;
1477
1478         ret = swrap_un_path(&un, swrap_dir, SOCKET_TYPE_CHAR_TCP, 0, 0);
1479         if (ret == 0) {
1480                 return true;
1481         }
1482
1483         ret = swrap_un_path_EINVAL(&un, swrap_dir);
1484         if (ret == 0) {
1485                 return true;
1486         }
1487
1488         return false;
1489 }
1490
1491 static char *socket_wrapper_dir(void)
1492 {
1493         char *swrap_dir = NULL;
1494         char *s = getenv("SOCKET_WRAPPER_DIR");
1495         char *t;
1496         bool ok;
1497
1498         if (s == NULL || s[0] == '\0') {
1499                 SWRAP_LOG(SWRAP_LOG_WARN, "SOCKET_WRAPPER_DIR not set");
1500                 return NULL;
1501         }
1502
1503         swrap_dir = realpath(s, NULL);
1504         if (swrap_dir == NULL) {
1505                 SWRAP_LOG(SWRAP_LOG_ERROR,
1506                           "Unable to resolve socket_wrapper dir path: %s - %s",
1507                           s,
1508                           strerror(errno));
1509                 abort();
1510         }
1511
1512         ok = swrap_dir_usable(swrap_dir);
1513         if (ok) {
1514                 goto done;
1515         }
1516
1517         free(swrap_dir);
1518
1519         ok = swrap_dir_usable(s);
1520         if (!ok) {
1521                 SWRAP_LOG(SWRAP_LOG_ERROR, "SOCKET_WRAPPER_DIR is too long");
1522                 abort();
1523         }
1524
1525         t = getenv("SOCKET_WRAPPER_DIR_ALLOW_ORIG");
1526         if (t == NULL) {
1527                 SWRAP_LOG(SWRAP_LOG_ERROR,
1528                           "realpath(SOCKET_WRAPPER_DIR) too long and "
1529                           "SOCKET_WRAPPER_DIR_ALLOW_ORIG not set");
1530                 abort();
1531
1532         }
1533
1534         swrap_dir = strdup(s);
1535         if (swrap_dir == NULL) {
1536                 SWRAP_LOG(SWRAP_LOG_ERROR,
1537                           "Unable to duplicate socket_wrapper dir path");
1538                 abort();
1539         }
1540
1541         SWRAP_LOG(SWRAP_LOG_WARN,
1542                   "realpath(SOCKET_WRAPPER_DIR) too long, "
1543                   "using original SOCKET_WRAPPER_DIR\n");
1544
1545 done:
1546         SWRAP_LOG(SWRAP_LOG_TRACE, "socket_wrapper_dir: %s", swrap_dir);
1547         return swrap_dir;
1548 }
1549
1550 static unsigned int socket_wrapper_mtu(void)
1551 {
1552         static unsigned int max_mtu = 0;
1553         unsigned int tmp;
1554         const char *s;
1555         char *endp;
1556
1557         swrap_mutex_lock(&mtu_update_mutex);
1558
1559         if (max_mtu != 0) {
1560                 goto done;
1561         }
1562
1563         max_mtu = SOCKET_WRAPPER_MTU_DEFAULT;
1564
1565         s = getenv("SOCKET_WRAPPER_MTU");
1566         if (s == NULL) {
1567                 goto done;
1568         }
1569
1570         tmp = strtol(s, &endp, 10);
1571         if (s == endp) {
1572                 goto done;
1573         }
1574
1575         if (tmp < SOCKET_WRAPPER_MTU_MIN || tmp > SOCKET_WRAPPER_MTU_MAX) {
1576                 goto done;
1577         }
1578         max_mtu = tmp;
1579
1580 done:
1581         swrap_mutex_unlock(&mtu_update_mutex);
1582         return max_mtu;
1583 }
1584
1585 static int _socket_wrapper_init_mutex(pthread_mutex_t *m, const char *name)
1586 {
1587         pthread_mutexattr_t ma;
1588         bool need_destroy = false;
1589         int ret = 0;
1590
1591 #define __CHECK(cmd) do { \
1592         ret = cmd; \
1593         if (ret != 0) { \
1594                 SWRAP_LOG(SWRAP_LOG_ERROR, \
1595                           "%s: %s - failed %d", \
1596                           name, #cmd, ret); \
1597                 goto done; \
1598         } \
1599 } while(0)
1600
1601         *m = (pthread_mutex_t)PTHREAD_MUTEX_INITIALIZER;
1602         __CHECK(pthread_mutexattr_init(&ma));
1603         need_destroy = true;
1604         __CHECK(pthread_mutexattr_settype(&ma, PTHREAD_MUTEX_ERRORCHECK));
1605         __CHECK(pthread_mutex_init(m, &ma));
1606 done:
1607         if (need_destroy) {
1608                 pthread_mutexattr_destroy(&ma);
1609         }
1610         return ret;
1611 }
1612
1613 static size_t socket_wrapper_max_sockets(void)
1614 {
1615         const char *s;
1616         size_t tmp;
1617         char *endp;
1618
1619         if (socket_info_max != 0) {
1620                 return socket_info_max;
1621         }
1622
1623         socket_info_max = SOCKET_WRAPPER_MAX_SOCKETS_DEFAULT;
1624
1625         s = getenv("SOCKET_WRAPPER_MAX_SOCKETS");
1626         if (s == NULL || s[0] == '\0') {
1627                 goto done;
1628         }
1629
1630         tmp = strtoul(s, &endp, 10);
1631         if (s == endp) {
1632                 goto done;
1633         }
1634         if (tmp == 0) {
1635                 tmp = SOCKET_WRAPPER_MAX_SOCKETS_DEFAULT;
1636                 SWRAP_LOG(SWRAP_LOG_ERROR,
1637                           "Invalid number of sockets specified, "
1638                           "using default (%zu)",
1639                           tmp);
1640         }
1641
1642         if (tmp > SOCKET_WRAPPER_MAX_SOCKETS_LIMIT) {
1643                 tmp = SOCKET_WRAPPER_MAX_SOCKETS_LIMIT;
1644                 SWRAP_LOG(SWRAP_LOG_ERROR,
1645                           "Invalid number of sockets specified, "
1646                           "using maximum (%zu).",
1647                           tmp);
1648         }
1649
1650         socket_info_max = tmp;
1651
1652 done:
1653         return socket_info_max;
1654 }
1655
1656 static void socket_wrapper_init_fds_idx(void)
1657 {
1658         int *tmp = NULL;
1659         size_t i;
1660
1661         if (socket_fds_idx != NULL) {
1662                 return;
1663         }
1664
1665         tmp = (int *)calloc(socket_fds_max, sizeof(int));
1666         if (tmp == NULL) {
1667                 SWRAP_LOG(SWRAP_LOG_ERROR,
1668                           "Failed to allocate socket fds index array: %s",
1669                           strerror(errno));
1670                 exit(-1);
1671         }
1672
1673         for (i = 0; i < socket_fds_max; i++) {
1674                 tmp[i] = -1;
1675         }
1676
1677         socket_fds_idx = tmp;
1678 }
1679
1680 static void socket_wrapper_init_sockets(void)
1681 {
1682         size_t max_sockets;
1683         size_t i;
1684         int ret = 0;
1685
1686         swrap_bind_symbol_all();
1687
1688         swrap_mutex_lock(&sockets_mutex);
1689
1690         if (sockets != NULL) {
1691                 swrap_mutex_unlock(&sockets_mutex);
1692                 return;
1693         }
1694
1695         SWRAP_LOG(SWRAP_LOG_DEBUG,
1696                   "SOCKET_WRAPPER_PACKAGE[%s] SOCKET_WRAPPER_VERSION[%s]",
1697                   SOCKET_WRAPPER_PACKAGE, SOCKET_WRAPPER_VERSION);
1698
1699         /*
1700          * Intialize the static cache early before
1701          * any thread is able to start.
1702          */
1703         (void)swrap_ipv4_net();
1704
1705         socket_wrapper_init_fds_idx();
1706
1707         /* Needs to be called inside the sockets_mutex lock here. */
1708         max_sockets = socket_wrapper_max_sockets();
1709
1710         sockets = (struct socket_info_container *)calloc(max_sockets,
1711                                         sizeof(struct socket_info_container));
1712
1713         if (sockets == NULL) {
1714                 SWRAP_LOG(SWRAP_LOG_ERROR,
1715                           "Failed to allocate sockets array: %s",
1716                           strerror(errno));
1717                 swrap_mutex_unlock(&sockets_mutex);
1718                 exit(-1);
1719         }
1720
1721         swrap_mutex_lock(&first_free_mutex);
1722         swrap_mutex_lock(&sockets_si_global);
1723
1724         first_free = 0;
1725
1726         for (i = 0; i < max_sockets; i++) {
1727                 swrap_set_next_free(&sockets[i].info, i+1);
1728         }
1729
1730         /* mark the end of the free list */
1731         swrap_set_next_free(&sockets[max_sockets-1].info, -1);
1732
1733         swrap_mutex_unlock(&sockets_si_global);
1734         swrap_mutex_unlock(&first_free_mutex);
1735         swrap_mutex_unlock(&sockets_mutex);
1736         if (ret != 0) {
1737                 exit(-1);
1738         }
1739 }
1740
1741 bool socket_wrapper_enabled(void)
1742 {
1743         char *s = socket_wrapper_dir();
1744
1745         if (s == NULL) {
1746                 return false;
1747         }
1748
1749         SAFE_FREE(s);
1750
1751         socket_wrapper_init_sockets();
1752
1753         return true;
1754 }
1755
1756 static unsigned int socket_wrapper_default_iface(void)
1757 {
1758         const char *s = getenv("SOCKET_WRAPPER_DEFAULT_IFACE");
1759         if (s) {
1760                 unsigned int iface;
1761                 if (sscanf(s, "%u", &iface) == 1) {
1762                         if (iface >= 1 && iface <= MAX_WRAPPED_INTERFACES) {
1763                                 return iface;
1764                         }
1765                 }
1766         }
1767
1768         return 1;/* 127.0.0.1 */
1769 }
1770
1771 static void set_socket_info_index(int fd, int idx)
1772 {
1773         SWRAP_LOG(SWRAP_LOG_TRACE,
1774                   "fd=%d idx=%d",
1775                   fd, idx);
1776         socket_fds_idx[fd] = idx;
1777         /* This builtin issues a full memory barrier. */
1778         __sync_synchronize();
1779 }
1780
1781 static void reset_socket_info_index(int fd)
1782 {
1783         SWRAP_LOG(SWRAP_LOG_TRACE,
1784                   "fd=%d idx=%d",
1785                   fd, -1);
1786         set_socket_info_index(fd, -1);
1787 }
1788
1789 static int find_socket_info_index(int fd)
1790 {
1791         if (fd < 0) {
1792                 return -1;
1793         }
1794
1795         if (socket_fds_idx == NULL) {
1796                 return -1;
1797         }
1798
1799         if ((size_t)fd >= socket_fds_max) {
1800                 /*
1801                  * Do not add a log here as some applications do stupid things
1802                  * like:
1803                  *
1804                  *     for (fd = 0; fd <= getdtablesize(); fd++) {
1805                  *         close(fd)
1806                  *     };
1807                  *
1808                  * This would produce millions of lines of debug messages.
1809                  */
1810 #if 0
1811                 SWRAP_LOG(SWRAP_LOG_ERROR,
1812                           "Looking for a socket info for the fd %d is over the "
1813                           "max socket index limit of %zu.",
1814                           fd,
1815                           socket_fds_max);
1816 #endif
1817                 return -1;
1818         }
1819
1820         /* This builtin issues a full memory barrier. */
1821         __sync_synchronize();
1822         return socket_fds_idx[fd];
1823 }
1824
1825 static int swrap_add_socket_info(const struct socket_info *si_input)
1826 {
1827         struct socket_info *si = NULL;
1828         int si_index = -1;
1829
1830         if (si_input == NULL) {
1831                 errno = EINVAL;
1832                 return -1;
1833         }
1834
1835         swrap_mutex_lock(&first_free_mutex);
1836         if (first_free == -1) {
1837                 errno = ENFILE;
1838                 goto out;
1839         }
1840
1841         si_index = first_free;
1842         si = swrap_get_socket_info(si_index);
1843
1844         SWRAP_LOCK_SI(si);
1845
1846         first_free = swrap_get_next_free(si);
1847         *si = *si_input;
1848         swrap_inc_refcount(si);
1849
1850         SWRAP_UNLOCK_SI(si);
1851
1852 out:
1853         swrap_mutex_unlock(&first_free_mutex);
1854
1855         return si_index;
1856 }
1857
1858 static int swrap_create_socket(struct socket_info *si, int fd)
1859 {
1860         int idx;
1861
1862         if ((size_t)fd >= socket_fds_max) {
1863                 SWRAP_LOG(SWRAP_LOG_ERROR,
1864                           "The max socket index limit of %zu has been reached, "
1865                           "trying to add %d",
1866                           socket_fds_max,
1867                           fd);
1868                 errno = EMFILE;
1869                 return -1;
1870         }
1871
1872         idx = swrap_add_socket_info(si);
1873         if (idx == -1) {
1874                 return -1;
1875         }
1876
1877         set_socket_info_index(fd, idx);
1878
1879         return idx;
1880 }
1881
1882 static int convert_un_in(const struct sockaddr_un *un, struct sockaddr *in, socklen_t *len)
1883 {
1884         unsigned int iface;
1885         unsigned int prt;
1886         const char *p;
1887         char type;
1888
1889         p = strrchr(un->sun_path, '/');
1890         if (p) p++; else p = un->sun_path;
1891
1892         if (sscanf(p, SOCKET_FORMAT, &type, &iface, &prt) != 3) {
1893                 SWRAP_LOG(SWRAP_LOG_ERROR, "sun_path[%s] p[%s]",
1894                           un->sun_path, p);
1895                 errno = EINVAL;
1896                 return -1;
1897         }
1898
1899         if (iface == 0 || iface > MAX_WRAPPED_INTERFACES) {
1900                 SWRAP_LOG(SWRAP_LOG_ERROR, "type %c iface %u port %u",
1901                           type, iface, prt);
1902                 errno = EINVAL;
1903                 return -1;
1904         }
1905
1906         if (prt > 0xFFFF) {
1907                 SWRAP_LOG(SWRAP_LOG_ERROR, "type %c iface %u port %u",
1908                           type, iface, prt);
1909                 errno = EINVAL;
1910                 return -1;
1911         }
1912
1913         SWRAP_LOG(SWRAP_LOG_TRACE, "type %c iface %u port %u",
1914                   type, iface, prt);
1915
1916         switch(type) {
1917         case SOCKET_TYPE_CHAR_TCP:
1918         case SOCKET_TYPE_CHAR_UDP: {
1919                 struct sockaddr_in *in2 = (struct sockaddr_in *)(void *)in;
1920
1921                 if ((*len) < sizeof(*in2)) {
1922                         SWRAP_LOG(SWRAP_LOG_ERROR,
1923                                   "V4: *len(%zu) < sizeof(*in2)=%zu",
1924                                   (size_t)*len, sizeof(*in2));
1925                         errno = EINVAL;
1926                         return -1;
1927                 }
1928
1929                 memset(in2, 0, sizeof(*in2));
1930                 in2->sin_family = AF_INET;
1931                 in2->sin_addr.s_addr = htonl(swrap_ipv4_iface(iface));
1932                 in2->sin_port = htons(prt);
1933
1934                 *len = sizeof(*in2);
1935                 break;
1936         }
1937 #ifdef HAVE_IPV6
1938         case SOCKET_TYPE_CHAR_TCP_V6:
1939         case SOCKET_TYPE_CHAR_UDP_V6: {
1940                 struct sockaddr_in6 *in2 = (struct sockaddr_in6 *)(void *)in;
1941
1942                 if ((*len) < sizeof(*in2)) {
1943                         SWRAP_LOG(SWRAP_LOG_ERROR,
1944                                   "V6: *len(%zu) < sizeof(*in2)=%zu",
1945                                   (size_t)*len, sizeof(*in2));
1946                         SWRAP_LOG(SWRAP_LOG_ERROR, "LINE:%d", __LINE__);
1947                         errno = EINVAL;
1948                         return -1;
1949                 }
1950
1951                 memset(in2, 0, sizeof(*in2));
1952                 in2->sin6_family = AF_INET6;
1953                 in2->sin6_addr = *swrap_ipv6();
1954                 in2->sin6_addr.s6_addr[15] = iface;
1955                 in2->sin6_port = htons(prt);
1956
1957                 *len = sizeof(*in2);
1958                 break;
1959         }
1960 #endif
1961         default:
1962                 SWRAP_LOG(SWRAP_LOG_ERROR, "type %c iface %u port %u",
1963                           type, iface, prt);
1964                 errno = EINVAL;
1965                 return -1;
1966         }
1967
1968         return 0;
1969 }
1970
1971 static int convert_in_un_remote(struct socket_info *si, const struct sockaddr *inaddr, struct sockaddr_un *un,
1972                                 int *bcast)
1973 {
1974         char type = '\0';
1975         unsigned int prt;
1976         unsigned int iface;
1977         int is_bcast = 0;
1978         char *swrap_dir = NULL;
1979
1980         if (bcast) *bcast = 0;
1981
1982         switch (inaddr->sa_family) {
1983         case AF_INET: {
1984                 const struct sockaddr_in *in =
1985                     (const struct sockaddr_in *)(const void *)inaddr;
1986                 unsigned int addr = ntohl(in->sin_addr.s_addr);
1987                 char u_type = '\0';
1988                 char b_type = '\0';
1989                 char a_type = '\0';
1990                 const unsigned int sw_net_addr = swrap_ipv4_net();
1991                 const unsigned int sw_bcast_addr = swrap_ipv4_bcast();
1992
1993                 switch (si->type) {
1994                 case SOCK_STREAM:
1995                         u_type = SOCKET_TYPE_CHAR_TCP;
1996                         break;
1997                 case SOCK_DGRAM:
1998                         u_type = SOCKET_TYPE_CHAR_UDP;
1999                         a_type = SOCKET_TYPE_CHAR_UDP;
2000                         b_type = SOCKET_TYPE_CHAR_UDP;
2001                         break;
2002                 default:
2003                         SWRAP_LOG(SWRAP_LOG_ERROR, "Unknown socket type!");
2004                         errno = ESOCKTNOSUPPORT;
2005                         return -1;
2006                 }
2007
2008                 prt = ntohs(in->sin_port);
2009                 if (a_type && addr == 0xFFFFFFFF) {
2010                         /* 255.255.255.255 only udp */
2011                         is_bcast = 2;
2012                         type = a_type;
2013                         iface = socket_wrapper_default_iface();
2014                 } else if (b_type && addr == sw_bcast_addr) {
2015                         /*
2016                          * 127.255.255.255
2017                          * or
2018                          * 10.255.255.255
2019                          * only udp
2020                          */
2021                         is_bcast = 1;
2022                         type = b_type;
2023                         iface = socket_wrapper_default_iface();
2024                 } else if ((addr & 0xFFFFFF00) == sw_net_addr) {
2025                         /* 127.0.0.X or 10.53.57.X */
2026                         is_bcast = 0;
2027                         type = u_type;
2028                         iface = (addr & 0x000000FF);
2029                 } else {
2030                         errno = ENETUNREACH;
2031                         return -1;
2032                 }
2033                 if (bcast) *bcast = is_bcast;
2034                 break;
2035         }
2036 #ifdef HAVE_IPV6
2037         case AF_INET6: {
2038                 const struct sockaddr_in6 *in =
2039                     (const struct sockaddr_in6 *)(const void *)inaddr;
2040                 struct in6_addr cmp1, cmp2;
2041
2042                 switch (si->type) {
2043                 case SOCK_STREAM:
2044                         type = SOCKET_TYPE_CHAR_TCP_V6;
2045                         break;
2046                 case SOCK_DGRAM:
2047                         type = SOCKET_TYPE_CHAR_UDP_V6;
2048                         break;
2049                 default:
2050                         SWRAP_LOG(SWRAP_LOG_ERROR, "Unknown socket type!");
2051                         errno = ESOCKTNOSUPPORT;
2052                         return -1;
2053                 }
2054
2055                 /* XXX no multicast/broadcast */
2056
2057                 prt = ntohs(in->sin6_port);
2058
2059                 cmp1 = *swrap_ipv6();
2060                 cmp2 = in->sin6_addr;
2061                 cmp2.s6_addr[15] = 0;
2062                 if (IN6_ARE_ADDR_EQUAL(&cmp1, &cmp2)) {
2063                         iface = in->sin6_addr.s6_addr[15];
2064                 } else {
2065                         errno = ENETUNREACH;
2066                         return -1;
2067                 }
2068
2069                 break;
2070         }
2071 #endif
2072         default:
2073                 SWRAP_LOG(SWRAP_LOG_ERROR, "Unknown address family!");
2074                 errno = ENETUNREACH;
2075                 return -1;
2076         }
2077
2078         if (prt == 0) {
2079                 SWRAP_LOG(SWRAP_LOG_WARN, "Port not set");
2080                 errno = EINVAL;
2081                 return -1;
2082         }
2083
2084         swrap_dir = socket_wrapper_dir();
2085         if (swrap_dir == NULL) {
2086                 errno = EINVAL;
2087                 return -1;
2088         }
2089
2090         if (is_bcast) {
2091                 swrap_un_path_EINVAL(un, swrap_dir);
2092                 SWRAP_LOG(SWRAP_LOG_DEBUG, "un path [%s]", un->sun_path);
2093                 SAFE_FREE(swrap_dir);
2094                 /* the caller need to do more processing */
2095                 return 0;
2096         }
2097
2098         swrap_un_path(un, swrap_dir, type, iface, prt);
2099         SWRAP_LOG(SWRAP_LOG_DEBUG, "un path [%s]", un->sun_path);
2100
2101         SAFE_FREE(swrap_dir);
2102
2103         return 0;
2104 }
2105
2106 static int convert_in_un_alloc(struct socket_info *si, const struct sockaddr *inaddr, struct sockaddr_un *un,
2107                                int *bcast)
2108 {
2109         char type = '\0';
2110         unsigned int prt;
2111         unsigned int iface;
2112         struct stat st;
2113         int is_bcast = 0;
2114         char *swrap_dir = NULL;
2115
2116         if (bcast) *bcast = 0;
2117
2118         switch (si->family) {
2119         case AF_INET: {
2120                 const struct sockaddr_in *in =
2121                     (const struct sockaddr_in *)(const void *)inaddr;
2122                 unsigned int addr = ntohl(in->sin_addr.s_addr);
2123                 char u_type = '\0';
2124                 char d_type = '\0';
2125                 char b_type = '\0';
2126                 char a_type = '\0';
2127                 const unsigned int sw_net_addr = swrap_ipv4_net();
2128                 const unsigned int sw_bcast_addr = swrap_ipv4_bcast();
2129
2130                 prt = ntohs(in->sin_port);
2131
2132                 switch (si->type) {
2133                 case SOCK_STREAM:
2134                         u_type = SOCKET_TYPE_CHAR_TCP;
2135                         d_type = SOCKET_TYPE_CHAR_TCP;
2136                         break;
2137                 case SOCK_DGRAM:
2138                         u_type = SOCKET_TYPE_CHAR_UDP;
2139                         d_type = SOCKET_TYPE_CHAR_UDP;
2140                         a_type = SOCKET_TYPE_CHAR_UDP;
2141                         b_type = SOCKET_TYPE_CHAR_UDP;
2142                         break;
2143                 default:
2144                         SWRAP_LOG(SWRAP_LOG_ERROR, "Unknown socket type!");
2145                         errno = ESOCKTNOSUPPORT;
2146                         return -1;
2147                 }
2148
2149                 if (addr == 0) {
2150                         /* 0.0.0.0 */
2151                         is_bcast = 0;
2152                         type = d_type;
2153                         iface = socket_wrapper_default_iface();
2154                 } else if (a_type && addr == 0xFFFFFFFF) {
2155                         /* 255.255.255.255 only udp */
2156                         is_bcast = 2;
2157                         type = a_type;
2158                         iface = socket_wrapper_default_iface();
2159                 } else if (b_type && addr == sw_bcast_addr) {
2160                         /* 127.255.255.255 only udp */
2161                         is_bcast = 1;
2162                         type = b_type;
2163                         iface = socket_wrapper_default_iface();
2164                 } else if ((addr & 0xFFFFFF00) == sw_net_addr) {
2165                         /* 127.0.0.X */
2166                         is_bcast = 0;
2167                         type = u_type;
2168                         iface = (addr & 0x000000FF);
2169                 } else {
2170                         errno = EADDRNOTAVAIL;
2171                         return -1;
2172                 }
2173
2174                 /* Store the bind address for connect() */
2175                 if (si->bindname.sa_socklen == 0) {
2176                         struct sockaddr_in bind_in;
2177                         socklen_t blen = sizeof(struct sockaddr_in);
2178
2179                         ZERO_STRUCT(bind_in);
2180                         bind_in.sin_family = in->sin_family;
2181                         bind_in.sin_port = in->sin_port;
2182                         bind_in.sin_addr.s_addr = htonl(swrap_ipv4_iface(iface));
2183                         si->bindname.sa_socklen = blen;
2184                         memcpy(&si->bindname.sa.in, &bind_in, blen);
2185                 }
2186
2187                 break;
2188         }
2189 #ifdef HAVE_IPV6
2190         case AF_INET6: {
2191                 const struct sockaddr_in6 *in =
2192                     (const struct sockaddr_in6 *)(const void *)inaddr;
2193                 struct in6_addr cmp1, cmp2;
2194
2195                 switch (si->type) {
2196                 case SOCK_STREAM:
2197                         type = SOCKET_TYPE_CHAR_TCP_V6;
2198                         break;
2199                 case SOCK_DGRAM:
2200                         type = SOCKET_TYPE_CHAR_UDP_V6;
2201                         break;
2202                 default:
2203                         SWRAP_LOG(SWRAP_LOG_ERROR, "Unknown socket type!");
2204                         errno = ESOCKTNOSUPPORT;
2205                         return -1;
2206                 }
2207
2208                 /* XXX no multicast/broadcast */
2209
2210                 prt = ntohs(in->sin6_port);
2211
2212                 cmp1 = *swrap_ipv6();
2213                 cmp2 = in->sin6_addr;
2214                 cmp2.s6_addr[15] = 0;
2215                 if (IN6_IS_ADDR_UNSPECIFIED(&in->sin6_addr)) {
2216                         iface = socket_wrapper_default_iface();
2217                 } else if (IN6_ARE_ADDR_EQUAL(&cmp1, &cmp2)) {
2218                         iface = in->sin6_addr.s6_addr[15];
2219                 } else {
2220                         errno = EADDRNOTAVAIL;
2221                         return -1;
2222                 }
2223
2224                 /* Store the bind address for connect() */
2225                 if (si->bindname.sa_socklen == 0) {
2226                         struct sockaddr_in6 bind_in;
2227                         socklen_t blen = sizeof(struct sockaddr_in6);
2228
2229                         ZERO_STRUCT(bind_in);
2230                         bind_in.sin6_family = in->sin6_family;
2231                         bind_in.sin6_port = in->sin6_port;
2232
2233                         bind_in.sin6_addr = *swrap_ipv6();
2234                         bind_in.sin6_addr.s6_addr[15] = iface;
2235
2236                         memcpy(&si->bindname.sa.in6, &bind_in, blen);
2237                         si->bindname.sa_socklen = blen;
2238                 }
2239
2240                 break;
2241         }
2242 #endif
2243         default:
2244                 SWRAP_LOG(SWRAP_LOG_ERROR, "Unknown address family");
2245                 errno = EADDRNOTAVAIL;
2246                 return -1;
2247         }
2248
2249
2250         if (bcast) *bcast = is_bcast;
2251
2252         if (iface == 0 || iface > MAX_WRAPPED_INTERFACES) {
2253                 errno = EINVAL;
2254                 return -1;
2255         }
2256
2257         swrap_dir = socket_wrapper_dir();
2258         if (swrap_dir == NULL) {
2259                 errno = EINVAL;
2260                 return -1;
2261         }
2262
2263         if (prt == 0) {
2264                 /* handle auto-allocation of ephemeral ports */
2265                 for (prt = 5001; prt < 10000; prt++) {
2266                         swrap_un_path(un, swrap_dir, type, iface, prt);
2267                         if (stat(un->sun_path, &st) == 0) continue;
2268
2269                         set_port(si->family, prt, &si->myname);
2270                         set_port(si->family, prt, &si->bindname);
2271
2272                         break;
2273                 }
2274
2275                 if (prt == 10000) {
2276                         errno = ENFILE;
2277                         SAFE_FREE(swrap_dir);
2278                         return -1;
2279                 }
2280         }
2281
2282         swrap_un_path(un, swrap_dir, type, iface, prt);
2283         SWRAP_LOG(SWRAP_LOG_DEBUG, "un path [%s]", un->sun_path);
2284
2285         SAFE_FREE(swrap_dir);
2286
2287         return 0;
2288 }
2289
2290 static struct socket_info *find_socket_info(int fd)
2291 {
2292         int idx = find_socket_info_index(fd);
2293
2294         if (idx == -1) {
2295                 return NULL;
2296         }
2297
2298         return swrap_get_socket_info(idx);
2299 }
2300
2301 #if 0 /* FIXME */
2302 static bool check_addr_port_in_use(const struct sockaddr *sa, socklen_t len)
2303 {
2304         struct socket_info_fd *f;
2305         const struct socket_info *last_s = NULL;
2306
2307         /* first catch invalid input */
2308         switch (sa->sa_family) {
2309         case AF_INET:
2310                 if (len < sizeof(struct sockaddr_in)) {
2311                         return false;
2312                 }
2313                 break;
2314 #ifdef HAVE_IPV6
2315         case AF_INET6:
2316                 if (len < sizeof(struct sockaddr_in6)) {
2317                         return false;
2318                 }
2319                 break;
2320 #endif
2321         default:
2322                 return false;
2323                 break;
2324         }
2325
2326         for (f = socket_fds; f; f = f->next) {
2327                 struct socket_info *s = swrap_get_socket_info(f->si_index);
2328
2329                 if (s == last_s) {
2330                         continue;
2331                 }
2332                 last_s = s;
2333
2334                 if (s->myname == NULL) {
2335                         continue;
2336                 }
2337                 if (s->myname->sa_family != sa->sa_family) {
2338                         continue;
2339                 }
2340                 switch (s->myname->sa_family) {
2341                 case AF_INET: {
2342                         struct sockaddr_in *sin1, *sin2;
2343
2344                         sin1 = (struct sockaddr_in *)s->myname;
2345                         sin2 = (struct sockaddr_in *)sa;
2346
2347                         if (sin1->sin_addr.s_addr == htonl(INADDR_ANY)) {
2348                                 continue;
2349                         }
2350                         if (sin1->sin_port != sin2->sin_port) {
2351                                 continue;
2352                         }
2353                         if (sin1->sin_addr.s_addr != sin2->sin_addr.s_addr) {
2354                                 continue;
2355                         }
2356
2357                         /* found */
2358                         return true;
2359                         break;
2360                 }
2361 #ifdef HAVE_IPV6
2362                 case AF_INET6: {
2363                         struct sockaddr_in6 *sin1, *sin2;
2364
2365                         sin1 = (struct sockaddr_in6 *)s->myname;
2366                         sin2 = (struct sockaddr_in6 *)sa;
2367
2368                         if (sin1->sin6_port != sin2->sin6_port) {
2369                                 continue;
2370                         }
2371                         if (!IN6_ARE_ADDR_EQUAL(&sin1->sin6_addr,
2372                                                 &sin2->sin6_addr))
2373                         {
2374                                 continue;
2375                         }
2376
2377                         /* found */
2378                         return true;
2379                         break;
2380                 }
2381 #endif
2382                 default:
2383                         continue;
2384                         break;
2385
2386                 }
2387         }
2388
2389         return false;
2390 }
2391 #endif
2392
2393 static void swrap_remove_stale(int fd)
2394 {
2395         struct socket_info *si;
2396         int si_index;
2397
2398         SWRAP_LOG(SWRAP_LOG_TRACE, "remove stale wrapper for %d", fd);
2399
2400         swrap_mutex_lock(&socket_reset_mutex);
2401
2402         si_index = find_socket_info_index(fd);
2403         if (si_index == -1) {
2404                 swrap_mutex_unlock(&socket_reset_mutex);
2405                 return;
2406         }
2407
2408         reset_socket_info_index(fd);
2409
2410         si = swrap_get_socket_info(si_index);
2411
2412         swrap_mutex_lock(&first_free_mutex);
2413         SWRAP_LOCK_SI(si);
2414
2415         swrap_dec_refcount(si);
2416
2417         if (swrap_get_refcount(si) > 0) {
2418                 goto out;
2419         }
2420
2421         if (si->un_addr.sun_path[0] != '\0') {
2422                 unlink(si->un_addr.sun_path);
2423         }
2424
2425         swrap_set_next_free(si, first_free);
2426         first_free = si_index;
2427
2428 out:
2429         SWRAP_UNLOCK_SI(si);
2430         swrap_mutex_unlock(&first_free_mutex);
2431         swrap_mutex_unlock(&socket_reset_mutex);
2432 }
2433
2434 static int sockaddr_convert_to_un(struct socket_info *si,
2435                                   const struct sockaddr *in_addr,
2436                                   socklen_t in_len,
2437                                   struct sockaddr_un *out_addr,
2438                                   int alloc_sock,
2439                                   int *bcast)
2440 {
2441         struct sockaddr *out = (struct sockaddr *)(void *)out_addr;
2442
2443         (void) in_len; /* unused */
2444
2445         if (out_addr == NULL) {
2446                 return 0;
2447         }
2448
2449         out->sa_family = AF_UNIX;
2450 #ifdef HAVE_STRUCT_SOCKADDR_SA_LEN
2451         out->sa_len = sizeof(*out_addr);
2452 #endif
2453
2454         switch (in_addr->sa_family) {
2455         case AF_UNSPEC: {
2456                 const struct sockaddr_in *sin;
2457                 if (si->family != AF_INET) {
2458                         break;
2459                 }
2460                 if (in_len < sizeof(struct sockaddr_in)) {
2461                         break;
2462                 }
2463                 sin = (const struct sockaddr_in *)(const void *)in_addr;
2464                 if(sin->sin_addr.s_addr != htonl(INADDR_ANY)) {
2465                         break;
2466                 }
2467
2468                 /*
2469                  * Note: in the special case of AF_UNSPEC and INADDR_ANY,
2470                  * AF_UNSPEC is mapped to AF_INET and must be treated here.
2471                  */
2472
2473                 FALL_THROUGH;
2474         }
2475         case AF_INET:
2476 #ifdef HAVE_IPV6
2477         case AF_INET6:
2478 #endif
2479                 switch (si->type) {
2480                 case SOCK_STREAM:
2481                 case SOCK_DGRAM:
2482                         break;
2483                 default:
2484                         SWRAP_LOG(SWRAP_LOG_ERROR, "Unknown socket type!");
2485                         errno = ESOCKTNOSUPPORT;
2486                         return -1;
2487                 }
2488                 if (alloc_sock) {
2489                         return convert_in_un_alloc(si, in_addr, out_addr, bcast);
2490                 } else {
2491                         return convert_in_un_remote(si, in_addr, out_addr, bcast);
2492                 }
2493         default:
2494                 break;
2495         }
2496
2497         errno = EAFNOSUPPORT;
2498         SWRAP_LOG(SWRAP_LOG_ERROR, "Unknown address family");
2499         return -1;
2500 }
2501
2502 static int sockaddr_convert_from_un(const struct socket_info *si,
2503                                     const struct sockaddr_un *in_addr,
2504                                     socklen_t un_addrlen,
2505                                     int family,
2506                                     struct sockaddr *out_addr,
2507                                     socklen_t *out_addrlen)
2508 {
2509         int ret;
2510
2511         if (out_addr == NULL || out_addrlen == NULL)
2512                 return 0;
2513
2514         if (un_addrlen == 0) {
2515                 *out_addrlen = 0;
2516                 return 0;
2517         }
2518
2519         switch (family) {
2520         case AF_INET:
2521 #ifdef HAVE_IPV6
2522         case AF_INET6:
2523 #endif
2524                 switch (si->type) {
2525                 case SOCK_STREAM:
2526                 case SOCK_DGRAM:
2527                         break;
2528                 default:
2529                         SWRAP_LOG(SWRAP_LOG_ERROR, "Unknown socket type!");
2530                         errno = ESOCKTNOSUPPORT;
2531                         return -1;
2532                 }
2533                 ret = convert_un_in(in_addr, out_addr, out_addrlen);
2534 #ifdef HAVE_STRUCT_SOCKADDR_SA_LEN
2535                 out_addr->sa_len = *out_addrlen;
2536 #endif
2537                 return ret;
2538         default:
2539                 break;
2540         }
2541
2542         SWRAP_LOG(SWRAP_LOG_ERROR, "Unknown address family");
2543         errno = EAFNOSUPPORT;
2544         return -1;
2545 }
2546
2547 enum swrap_packet_type {
2548         SWRAP_CONNECT_SEND,
2549         SWRAP_CONNECT_UNREACH,
2550         SWRAP_CONNECT_RECV,
2551         SWRAP_CONNECT_ACK,
2552         SWRAP_ACCEPT_SEND,
2553         SWRAP_ACCEPT_RECV,
2554         SWRAP_ACCEPT_ACK,
2555         SWRAP_RECVFROM,
2556         SWRAP_SENDTO,
2557         SWRAP_SENDTO_UNREACH,
2558         SWRAP_PENDING_RST,
2559         SWRAP_RECV,
2560         SWRAP_RECV_RST,
2561         SWRAP_SEND,
2562         SWRAP_SEND_RST,
2563         SWRAP_CLOSE_SEND,
2564         SWRAP_CLOSE_RECV,
2565         SWRAP_CLOSE_ACK,
2566 };
2567
2568 struct swrap_file_hdr {
2569         uint32_t        magic;
2570         uint16_t        version_major;
2571         uint16_t        version_minor;
2572         int32_t         timezone;
2573         uint32_t        sigfigs;
2574         uint32_t        frame_max_len;
2575 #define SWRAP_FRAME_LENGTH_MAX 0xFFFF
2576         uint32_t        link_type;
2577 };
2578 #define SWRAP_FILE_HDR_SIZE 24
2579
2580 struct swrap_packet_frame {
2581         uint32_t seconds;
2582         uint32_t micro_seconds;
2583         uint32_t recorded_length;
2584         uint32_t full_length;
2585 };
2586 #define SWRAP_PACKET_FRAME_SIZE 16
2587
2588 union swrap_packet_ip {
2589         struct {
2590                 uint8_t         ver_hdrlen;
2591                 uint8_t         tos;
2592                 uint16_t        packet_length;
2593                 uint16_t        identification;
2594                 uint8_t         flags;
2595                 uint8_t         fragment;
2596                 uint8_t         ttl;
2597                 uint8_t         protocol;
2598                 uint16_t        hdr_checksum;
2599                 uint32_t        src_addr;
2600                 uint32_t        dest_addr;
2601         } v4;
2602 #define SWRAP_PACKET_IP_V4_SIZE 20
2603         struct {
2604                 uint8_t         ver_prio;
2605                 uint8_t         flow_label_high;
2606                 uint16_t        flow_label_low;
2607                 uint16_t        payload_length;
2608                 uint8_t         next_header;
2609                 uint8_t         hop_limit;
2610                 uint8_t         src_addr[16];
2611                 uint8_t         dest_addr[16];
2612         } v6;
2613 #define SWRAP_PACKET_IP_V6_SIZE 40
2614 };
2615 #define SWRAP_PACKET_IP_SIZE 40
2616
2617 union swrap_packet_payload {
2618         struct {
2619                 uint16_t        source_port;
2620                 uint16_t        dest_port;
2621                 uint32_t        seq_num;
2622                 uint32_t        ack_num;
2623                 uint8_t         hdr_length;
2624                 uint8_t         control;
2625                 uint16_t        window;
2626                 uint16_t        checksum;
2627                 uint16_t        urg;
2628         } tcp;
2629 #define SWRAP_PACKET_PAYLOAD_TCP_SIZE 20
2630         struct {
2631                 uint16_t        source_port;
2632                 uint16_t        dest_port;
2633                 uint16_t        length;
2634                 uint16_t        checksum;
2635         } udp;
2636 #define SWRAP_PACKET_PAYLOAD_UDP_SIZE 8
2637         struct {
2638                 uint8_t         type;
2639                 uint8_t         code;
2640                 uint16_t        checksum;
2641                 uint32_t        unused;
2642         } icmp4;
2643 #define SWRAP_PACKET_PAYLOAD_ICMP4_SIZE 8
2644         struct {
2645                 uint8_t         type;
2646                 uint8_t         code;
2647                 uint16_t        checksum;
2648                 uint32_t        unused;
2649         } icmp6;
2650 #define SWRAP_PACKET_PAYLOAD_ICMP6_SIZE 8
2651 };
2652 #define SWRAP_PACKET_PAYLOAD_SIZE 20
2653
2654 #define SWRAP_PACKET_MIN_ALLOC \
2655         (SWRAP_PACKET_FRAME_SIZE + \
2656          SWRAP_PACKET_IP_SIZE + \
2657          SWRAP_PACKET_PAYLOAD_SIZE)
2658
2659 static const char *swrap_pcap_init_file(void)
2660 {
2661         static int initialized = 0;
2662         static const char *s = NULL;
2663         static const struct swrap_file_hdr h;
2664         static const struct swrap_packet_frame f;
2665         static const union swrap_packet_ip i;
2666         static const union swrap_packet_payload p;
2667
2668         if (initialized == 1) {
2669                 return s;
2670         }
2671         initialized = 1;
2672
2673         /*
2674          * TODO: don't use the structs use plain buffer offsets
2675          *       and PUSH_U8(), PUSH_U16() and PUSH_U32()
2676          *
2677          * for now make sure we disable PCAP support
2678          * if the struct has alignment!
2679          */
2680         if (sizeof(h) != SWRAP_FILE_HDR_SIZE) {
2681                 return NULL;
2682         }
2683         if (sizeof(f) != SWRAP_PACKET_FRAME_SIZE) {
2684                 return NULL;
2685         }
2686         if (sizeof(i) != SWRAP_PACKET_IP_SIZE) {
2687                 return NULL;
2688         }
2689         if (sizeof(i.v4) != SWRAP_PACKET_IP_V4_SIZE) {
2690                 return NULL;
2691         }
2692         if (sizeof(i.v6) != SWRAP_PACKET_IP_V6_SIZE) {
2693                 return NULL;
2694         }
2695         if (sizeof(p) != SWRAP_PACKET_PAYLOAD_SIZE) {
2696                 return NULL;
2697         }
2698         if (sizeof(p.tcp) != SWRAP_PACKET_PAYLOAD_TCP_SIZE) {
2699                 return NULL;
2700         }
2701         if (sizeof(p.udp) != SWRAP_PACKET_PAYLOAD_UDP_SIZE) {
2702                 return NULL;
2703         }
2704         if (sizeof(p.icmp4) != SWRAP_PACKET_PAYLOAD_ICMP4_SIZE) {
2705                 return NULL;
2706         }
2707         if (sizeof(p.icmp6) != SWRAP_PACKET_PAYLOAD_ICMP6_SIZE) {
2708                 return NULL;
2709         }
2710
2711         s = getenv("SOCKET_WRAPPER_PCAP_FILE");
2712         if (s == NULL) {
2713                 return NULL;
2714         }
2715         if (strncmp(s, "./", 2) == 0) {
2716                 s += 2;
2717         }
2718         SWRAP_LOG(SWRAP_LOG_TRACE, "SOCKET_WRAPPER_PCAP_FILE: %s", s);
2719         return s;
2720 }
2721
2722 static uint8_t *swrap_pcap_packet_init(struct timeval *tval,
2723                                        const struct sockaddr *src,
2724                                        const struct sockaddr *dest,
2725                                        int socket_type,
2726                                        const uint8_t *payload,
2727                                        size_t payload_len,
2728                                        unsigned long tcp_seqno,
2729                                        unsigned long tcp_ack,
2730                                        unsigned char tcp_ctl,
2731                                        int unreachable,
2732                                        size_t *_packet_len)
2733 {
2734         uint8_t *base = NULL;
2735         uint8_t *buf = NULL;
2736         union {
2737                 uint8_t *ptr;
2738                 struct swrap_packet_frame *frame;
2739         } f;
2740         union {
2741                 uint8_t *ptr;
2742                 union swrap_packet_ip *ip;
2743         } i;
2744         union swrap_packet_payload *pay;
2745         size_t packet_len;
2746         size_t alloc_len;
2747         size_t nonwire_len = sizeof(struct swrap_packet_frame);
2748         size_t wire_hdr_len = 0;
2749         size_t wire_len = 0;
2750         size_t ip_hdr_len = 0;
2751         size_t icmp_hdr_len = 0;
2752         size_t icmp_truncate_len = 0;
2753         uint8_t protocol = 0, icmp_protocol = 0;
2754         const struct sockaddr_in *src_in = NULL;
2755         const struct sockaddr_in *dest_in = NULL;
2756 #ifdef HAVE_IPV6
2757         const struct sockaddr_in6 *src_in6 = NULL;
2758         const struct sockaddr_in6 *dest_in6 = NULL;
2759 #endif
2760         uint16_t src_port;
2761         uint16_t dest_port;
2762
2763         switch (src->sa_family) {
2764         case AF_INET:
2765                 src_in = (const struct sockaddr_in *)(const void *)src;
2766                 dest_in = (const struct sockaddr_in *)(const void *)dest;
2767                 src_port = src_in->sin_port;
2768                 dest_port = dest_in->sin_port;
2769                 ip_hdr_len = sizeof(i.ip->v4);
2770                 break;
2771 #ifdef HAVE_IPV6
2772         case AF_INET6:
2773                 src_in6 = (const struct sockaddr_in6 *)(const void *)src;
2774                 dest_in6 = (const struct sockaddr_in6 *)(const void *)dest;
2775                 src_port = src_in6->sin6_port;
2776                 dest_port = dest_in6->sin6_port;
2777                 ip_hdr_len = sizeof(i.ip->v6);
2778                 break;
2779 #endif
2780         default:
2781                 return NULL;
2782         }
2783
2784         switch (socket_type) {
2785         case SOCK_STREAM:
2786                 protocol = 0x06; /* TCP */
2787                 wire_hdr_len = ip_hdr_len + sizeof(pay->tcp);
2788                 wire_len = wire_hdr_len + payload_len;
2789                 break;
2790
2791         case SOCK_DGRAM:
2792                 protocol = 0x11; /* UDP */
2793                 wire_hdr_len = ip_hdr_len + sizeof(pay->udp);
2794                 wire_len = wire_hdr_len + payload_len;
2795                 break;
2796
2797         default:
2798                 return NULL;
2799         }
2800
2801         if (unreachable) {
2802                 icmp_protocol = protocol;
2803                 switch (src->sa_family) {
2804                 case AF_INET:
2805                         protocol = 0x01; /* ICMPv4 */
2806                         icmp_hdr_len = ip_hdr_len + sizeof(pay->icmp4);
2807                         break;
2808 #ifdef HAVE_IPV6
2809                 case AF_INET6:
2810                         protocol = 0x3A; /* ICMPv6 */
2811                         icmp_hdr_len = ip_hdr_len + sizeof(pay->icmp6);
2812                         break;
2813 #endif
2814                 }
2815                 if (wire_len > 64 ) {
2816                         icmp_truncate_len = wire_len - 64;
2817                 }
2818                 wire_len += icmp_hdr_len;
2819         }
2820
2821         packet_len = nonwire_len + wire_len;
2822         alloc_len = packet_len;
2823         if (alloc_len < SWRAP_PACKET_MIN_ALLOC) {
2824                 alloc_len = SWRAP_PACKET_MIN_ALLOC;
2825         }
2826
2827         base = (uint8_t *)calloc(1, alloc_len);
2828         if (base == NULL) {
2829                 return NULL;
2830         }
2831
2832         buf = base;
2833         f.ptr = buf;
2834
2835         f.frame->seconds                = tval->tv_sec;
2836         f.frame->micro_seconds  = tval->tv_usec;
2837         f.frame->recorded_length        = wire_len - icmp_truncate_len;
2838         f.frame->full_length    = wire_len - icmp_truncate_len;
2839
2840         buf += SWRAP_PACKET_FRAME_SIZE;
2841
2842         i.ptr = buf;
2843         switch (src->sa_family) {
2844         case AF_INET:
2845                 if (src_in == NULL || dest_in == NULL) {
2846                         SAFE_FREE(base);
2847                         return NULL;
2848                 }
2849
2850                 i.ip->v4.ver_hdrlen     = 0x45; /* version 4 and 5 * 32 bit words */
2851                 i.ip->v4.tos            = 0x00;
2852                 i.ip->v4.packet_length  = htons(wire_len - icmp_truncate_len);
2853                 i.ip->v4.identification = htons(0xFFFF);
2854                 i.ip->v4.flags          = 0x40; /* BIT 1 set - means don't fragment */
2855                 i.ip->v4.fragment       = htons(0x0000);
2856                 i.ip->v4.ttl            = 0xFF;
2857                 i.ip->v4.protocol       = protocol;
2858                 i.ip->v4.hdr_checksum   = htons(0x0000);
2859                 i.ip->v4.src_addr       = src_in->sin_addr.s_addr;
2860                 i.ip->v4.dest_addr      = dest_in->sin_addr.s_addr;
2861                 buf += SWRAP_PACKET_IP_V4_SIZE;
2862                 break;
2863 #ifdef HAVE_IPV6
2864         case AF_INET6:
2865                 if (src_in6 == NULL || dest_in6 == NULL) {
2866                         SAFE_FREE(base);
2867                         return NULL;
2868                 }
2869
2870                 i.ip->v6.ver_prio               = 0x60; /* version 4 and 5 * 32 bit words */
2871                 i.ip->v6.flow_label_high        = 0x00;
2872                 i.ip->v6.flow_label_low = 0x0000;
2873                 i.ip->v6.payload_length = htons(wire_len - icmp_truncate_len); /* TODO */
2874                 i.ip->v6.next_header    = protocol;
2875                 memcpy(i.ip->v6.src_addr, src_in6->sin6_addr.s6_addr, 16);
2876                 memcpy(i.ip->v6.dest_addr, dest_in6->sin6_addr.s6_addr, 16);
2877                 buf += SWRAP_PACKET_IP_V6_SIZE;
2878                 break;
2879 #endif
2880         }
2881
2882         if (unreachable) {
2883                 pay = (union swrap_packet_payload *)(void *)buf;
2884                 switch (src->sa_family) {
2885                 case AF_INET:
2886                         pay->icmp4.type         = 0x03; /* destination unreachable */
2887                         pay->icmp4.code         = 0x01; /* host unreachable */
2888                         pay->icmp4.checksum     = htons(0x0000);
2889                         pay->icmp4.unused       = htonl(0x00000000);
2890
2891                         buf += SWRAP_PACKET_PAYLOAD_ICMP4_SIZE;
2892
2893                         /* set the ip header in the ICMP payload */
2894                         i.ptr = buf;
2895                         i.ip->v4.ver_hdrlen     = 0x45; /* version 4 and 5 * 32 bit words */
2896                         i.ip->v4.tos            = 0x00;
2897                         i.ip->v4.packet_length  = htons(wire_len - icmp_hdr_len);
2898                         i.ip->v4.identification = htons(0xFFFF);
2899                         i.ip->v4.flags          = 0x40; /* BIT 1 set - means don't fragment */
2900                         i.ip->v4.fragment       = htons(0x0000);
2901                         i.ip->v4.ttl            = 0xFF;
2902                         i.ip->v4.protocol       = icmp_protocol;
2903                         i.ip->v4.hdr_checksum   = htons(0x0000);
2904                         i.ip->v4.src_addr       = dest_in->sin_addr.s_addr;
2905                         i.ip->v4.dest_addr      = src_in->sin_addr.s_addr;
2906
2907                         buf += SWRAP_PACKET_IP_V4_SIZE;
2908
2909                         src_port = dest_in->sin_port;
2910                         dest_port = src_in->sin_port;
2911                         break;
2912 #ifdef HAVE_IPV6
2913                 case AF_INET6:
2914                         pay->icmp6.type         = 0x01; /* destination unreachable */
2915                         pay->icmp6.code         = 0x03; /* address unreachable */
2916                         pay->icmp6.checksum     = htons(0x0000);
2917                         pay->icmp6.unused       = htonl(0x00000000);
2918                         buf += SWRAP_PACKET_PAYLOAD_ICMP6_SIZE;
2919
2920                         /* set the ip header in the ICMP payload */
2921                         i.ptr = buf;
2922                         i.ip->v6.ver_prio               = 0x60; /* version 4 and 5 * 32 bit words */
2923                         i.ip->v6.flow_label_high        = 0x00;
2924                         i.ip->v6.flow_label_low = 0x0000;
2925                         i.ip->v6.payload_length = htons(wire_len - icmp_truncate_len); /* TODO */
2926                         i.ip->v6.next_header    = protocol;
2927                         memcpy(i.ip->v6.src_addr, dest_in6->sin6_addr.s6_addr, 16);
2928                         memcpy(i.ip->v6.dest_addr, src_in6->sin6_addr.s6_addr, 16);
2929
2930                         buf += SWRAP_PACKET_IP_V6_SIZE;
2931
2932                         src_port = dest_in6->sin6_port;
2933                         dest_port = src_in6->sin6_port;
2934                         break;
2935 #endif
2936                 }
2937         }
2938
2939         pay = (union swrap_packet_payload *)(void *)buf;
2940
2941         switch (socket_type) {
2942         case SOCK_STREAM:
2943                 pay->tcp.source_port    = src_port;
2944                 pay->tcp.dest_port      = dest_port;
2945                 pay->tcp.seq_num        = htonl(tcp_seqno);
2946                 pay->tcp.ack_num        = htonl(tcp_ack);
2947                 pay->tcp.hdr_length     = 0x50; /* 5 * 32 bit words */
2948                 pay->tcp.control        = tcp_ctl;
2949                 pay->tcp.window         = htons(0x7FFF);
2950                 pay->tcp.checksum       = htons(0x0000);
2951                 pay->tcp.urg            = htons(0x0000);
2952                 buf += SWRAP_PACKET_PAYLOAD_TCP_SIZE;
2953
2954                 break;
2955
2956         case SOCK_DGRAM:
2957                 pay->udp.source_port    = src_port;
2958                 pay->udp.dest_port      = dest_port;
2959                 pay->udp.length         = htons(8 + payload_len);
2960                 pay->udp.checksum       = htons(0x0000);
2961                 buf += SWRAP_PACKET_PAYLOAD_UDP_SIZE;
2962
2963                 break;
2964         }
2965
2966         if (payload && payload_len > 0) {
2967                 memcpy(buf, payload, payload_len);
2968         }
2969
2970         *_packet_len = packet_len - icmp_truncate_len;
2971         return base;
2972 }
2973
2974 static int swrap_pcap_get_fd(const char *fname)
2975 {
2976         static int fd = -1;
2977
2978         if (fd != -1) {
2979                 return fd;
2980         }
2981
2982         fd = libc_open(fname, O_WRONLY|O_CREAT|O_EXCL|O_APPEND, 0644);
2983         if (fd != -1) {
2984                 struct swrap_file_hdr file_hdr;
2985                 file_hdr.magic          = 0xA1B2C3D4;
2986                 file_hdr.version_major  = 0x0002;
2987                 file_hdr.version_minor  = 0x0004;
2988                 file_hdr.timezone       = 0x00000000;
2989                 file_hdr.sigfigs        = 0x00000000;
2990                 file_hdr.frame_max_len  = SWRAP_FRAME_LENGTH_MAX;
2991                 file_hdr.link_type      = 0x0065; /* 101 RAW IP */
2992
2993                 if (write(fd, &file_hdr, sizeof(file_hdr)) != sizeof(file_hdr)) {
2994                         libc_close(fd);
2995                         fd = -1;
2996                 }
2997                 return fd;
2998         }
2999
3000         fd = libc_open(fname, O_WRONLY|O_APPEND, 0644);
3001
3002         return fd;
3003 }
3004
3005 static uint8_t *swrap_pcap_marshall_packet(struct socket_info *si,
3006                                            const struct sockaddr *addr,
3007                                            enum swrap_packet_type type,
3008                                            const void *buf, size_t len,
3009                                            size_t *packet_len)
3010 {
3011         const struct sockaddr *src_addr;
3012         const struct sockaddr *dest_addr;
3013         unsigned long tcp_seqno = 0;
3014         unsigned long tcp_ack = 0;
3015         unsigned char tcp_ctl = 0;
3016         int unreachable = 0;
3017
3018         struct timeval tv;
3019
3020         switch (si->family) {
3021         case AF_INET:
3022                 break;
3023 #ifdef HAVE_IPV6
3024         case AF_INET6:
3025                 break;
3026 #endif
3027         default:
3028                 return NULL;
3029         }
3030
3031         switch (type) {
3032         case SWRAP_CONNECT_SEND:
3033                 if (si->type != SOCK_STREAM) {
3034                         return NULL;
3035                 }
3036
3037                 src_addr  = &si->myname.sa.s;
3038                 dest_addr = addr;
3039
3040                 tcp_seqno = si->io.pck_snd;
3041                 tcp_ack = si->io.pck_rcv;
3042                 tcp_ctl = 0x02; /* SYN */
3043
3044                 si->io.pck_snd += 1;
3045
3046                 break;
3047
3048         case SWRAP_CONNECT_RECV:
3049                 if (si->type != SOCK_STREAM) {
3050                         return NULL;
3051                 }
3052
3053                 dest_addr = &si->myname.sa.s;
3054                 src_addr = addr;
3055
3056                 tcp_seqno = si->io.pck_rcv;
3057                 tcp_ack = si->io.pck_snd;
3058                 tcp_ctl = 0x12; /** SYN,ACK */
3059
3060                 si->io.pck_rcv += 1;
3061
3062                 break;
3063
3064         case SWRAP_CONNECT_UNREACH:
3065                 if (si->type != SOCK_STREAM) {
3066                         return NULL;
3067                 }
3068
3069                 dest_addr = &si->myname.sa.s;
3070                 src_addr  = addr;
3071
3072                 /* Unreachable: resend the data of SWRAP_CONNECT_SEND */
3073                 tcp_seqno = si->io.pck_snd - 1;
3074                 tcp_ack = si->io.pck_rcv;
3075                 tcp_ctl = 0x02; /* SYN */
3076                 unreachable = 1;
3077
3078                 break;
3079
3080         case SWRAP_CONNECT_ACK:
3081                 if (si->type != SOCK_STREAM) {
3082                         return NULL;
3083                 }
3084
3085                 src_addr  = &si->myname.sa.s;
3086                 dest_addr = addr;
3087
3088                 tcp_seqno = si->io.pck_snd;
3089                 tcp_ack = si->io.pck_rcv;
3090                 tcp_ctl = 0x10; /* ACK */
3091
3092                 break;
3093
3094         case SWRAP_ACCEPT_SEND:
3095                 if (si->type != SOCK_STREAM) {
3096                         return NULL;
3097                 }
3098
3099                 dest_addr = &si->myname.sa.s;
3100                 src_addr = addr;
3101
3102                 tcp_seqno = si->io.pck_rcv;
3103                 tcp_ack = si->io.pck_snd;
3104                 tcp_ctl = 0x02; /* SYN */
3105
3106                 si->io.pck_rcv += 1;
3107
3108                 break;
3109
3110         case SWRAP_ACCEPT_RECV:
3111                 if (si->type != SOCK_STREAM) {
3112                         return NULL;
3113                 }
3114
3115                 src_addr = &si->myname.sa.s;
3116                 dest_addr = addr;
3117
3118                 tcp_seqno = si->io.pck_snd;
3119                 tcp_ack = si->io.pck_rcv;
3120                 tcp_ctl = 0x12; /* SYN,ACK */
3121
3122                 si->io.pck_snd += 1;
3123
3124                 break;
3125
3126         case SWRAP_ACCEPT_ACK:
3127                 if (si->type != SOCK_STREAM) {
3128                         return NULL;
3129                 }
3130
3131                 dest_addr = &si->myname.sa.s;
3132                 src_addr = addr;
3133
3134                 tcp_seqno = si->io.pck_rcv;
3135                 tcp_ack = si->io.pck_snd;
3136                 tcp_ctl = 0x10; /* ACK */
3137
3138                 break;
3139
3140         case SWRAP_SEND:
3141                 src_addr  = &si->myname.sa.s;
3142                 dest_addr = &si->peername.sa.s;
3143
3144                 tcp_seqno = si->io.pck_snd;
3145                 tcp_ack = si->io.pck_rcv;
3146                 tcp_ctl = 0x18; /* PSH,ACK */
3147
3148                 si->io.pck_snd += len;
3149
3150                 break;
3151
3152         case SWRAP_SEND_RST:
3153                 dest_addr = &si->myname.sa.s;
3154                 src_addr  = &si->peername.sa.s;
3155
3156                 if (si->type == SOCK_DGRAM) {
3157                         return swrap_pcap_marshall_packet(si,
3158                                                           &si->peername.sa.s,
3159                                                           SWRAP_SENDTO_UNREACH,
3160                                                           buf,
3161                                                           len,
3162                                                           packet_len);
3163                 }
3164
3165                 tcp_seqno = si->io.pck_rcv;
3166                 tcp_ack = si->io.pck_snd;
3167                 tcp_ctl = 0x14; /** RST,ACK */
3168
3169                 break;
3170
3171         case SWRAP_PENDING_RST:
3172                 dest_addr = &si->myname.sa.s;
3173                 src_addr  = &si->peername.sa.s;
3174
3175                 if (si->type == SOCK_DGRAM) {
3176                         return NULL;
3177                 }
3178
3179                 tcp_seqno = si->io.pck_rcv;
3180                 tcp_ack = si->io.pck_snd;
3181                 tcp_ctl = 0x14; /* RST,ACK */
3182
3183                 break;
3184
3185         case SWRAP_RECV:
3186                 dest_addr = &si->myname.sa.s;
3187                 src_addr  = &si->peername.sa.s;
3188
3189                 tcp_seqno = si->io.pck_rcv;
3190                 tcp_ack = si->io.pck_snd;
3191                 tcp_ctl = 0x18; /* PSH,ACK */
3192
3193                 si->io.pck_rcv += len;
3194
3195                 break;
3196
3197         case SWRAP_RECV_RST:
3198                 dest_addr = &si->myname.sa.s;
3199                 src_addr  = &si->peername.sa.s;
3200
3201                 if (si->type == SOCK_DGRAM) {
3202                         return NULL;
3203                 }
3204
3205                 tcp_seqno = si->io.pck_rcv;
3206                 tcp_ack = si->io.pck_snd;
3207                 tcp_ctl = 0x14; /* RST,ACK */
3208
3209                 break;
3210
3211         case SWRAP_SENDTO:
3212                 src_addr = &si->myname.sa.s;
3213                 dest_addr = addr;
3214
3215                 si->io.pck_snd += len;
3216
3217                 break;
3218
3219         case SWRAP_SENDTO_UNREACH:
3220                 dest_addr = &si->myname.sa.s;
3221                 src_addr = addr;
3222
3223                 unreachable = 1;
3224
3225                 break;
3226
3227         case SWRAP_RECVFROM:
3228                 dest_addr = &si->myname.sa.s;
3229                 src_addr = addr;
3230
3231                 si->io.pck_rcv += len;
3232
3233                 break;
3234
3235         case SWRAP_CLOSE_SEND:
3236                 if (si->type != SOCK_STREAM) {
3237                         return NULL;
3238                 }
3239
3240                 src_addr  = &si->myname.sa.s;
3241                 dest_addr = &si->peername.sa.s;
3242
3243                 tcp_seqno = si->io.pck_snd;
3244                 tcp_ack = si->io.pck_rcv;
3245                 tcp_ctl = 0x11; /* FIN, ACK */
3246
3247                 si->io.pck_snd += 1;
3248
3249                 break;
3250
3251         case SWRAP_CLOSE_RECV:
3252                 if (si->type != SOCK_STREAM) {
3253                         return NULL;
3254                 }
3255
3256                 dest_addr = &si->myname.sa.s;
3257                 src_addr  = &si->peername.sa.s;
3258
3259                 tcp_seqno = si->io.pck_rcv;
3260                 tcp_ack = si->io.pck_snd;
3261                 tcp_ctl = 0x11; /* FIN,ACK */
3262
3263                 si->io.pck_rcv += 1;
3264
3265                 break;
3266
3267         case SWRAP_CLOSE_ACK:
3268                 if (si->type != SOCK_STREAM) {
3269                         return NULL;
3270                 }
3271
3272                 src_addr  = &si->myname.sa.s;
3273                 dest_addr = &si->peername.sa.s;
3274
3275                 tcp_seqno = si->io.pck_snd;
3276                 tcp_ack = si->io.pck_rcv;
3277                 tcp_ctl = 0x10; /* ACK */
3278
3279                 break;
3280         default:
3281                 return NULL;
3282         }
3283
3284         swrapGetTimeOfDay(&tv);
3285
3286         return swrap_pcap_packet_init(&tv,
3287                                       src_addr,
3288                                       dest_addr,
3289                                       si->type,
3290                                       (const uint8_t *)buf,
3291                                       len,
3292                                       tcp_seqno,
3293                                       tcp_ack,
3294                                       tcp_ctl,
3295                                       unreachable,
3296                                       packet_len);
3297 }
3298
3299 static void swrap_pcap_dump_packet(struct socket_info *si,
3300                                    const struct sockaddr *addr,
3301                                    enum swrap_packet_type type,
3302                                    const void *buf, size_t len)
3303 {
3304         const char *file_name;
3305         uint8_t *packet;
3306         size_t packet_len = 0;
3307         int fd;
3308
3309         swrap_mutex_lock(&pcap_dump_mutex);
3310
3311         file_name = swrap_pcap_init_file();
3312         if (!file_name) {
3313                 goto done;
3314         }
3315
3316         packet = swrap_pcap_marshall_packet(si,
3317                                             addr,
3318                                             type,
3319                                             buf,
3320                                             len,
3321                                             &packet_len);
3322         if (packet == NULL) {
3323                 goto done;
3324         }
3325
3326         fd = swrap_pcap_get_fd(file_name);
3327         if (fd != -1) {
3328                 if (write(fd, packet, packet_len) != (ssize_t)packet_len) {
3329                         free(packet);
3330                         goto done;
3331                 }
3332         }
3333
3334         free(packet);
3335
3336 done:
3337         swrap_mutex_unlock(&pcap_dump_mutex);
3338 }
3339
3340 /****************************************************************************
3341  *   SIGNALFD
3342  ***************************************************************************/
3343
3344 #ifdef HAVE_SIGNALFD
3345 static int swrap_signalfd(int fd, const sigset_t *mask, int flags)
3346 {
3347         int rc;
3348
3349         rc = libc_signalfd(fd, mask, flags);
3350         if (rc != -1) {
3351                 swrap_remove_stale(fd);
3352         }
3353
3354         return rc;
3355 }
3356
3357 int signalfd(int fd, const sigset_t *mask, int flags)
3358 {
3359         return swrap_signalfd(fd, mask, flags);
3360 }
3361 #endif
3362
3363 /****************************************************************************
3364  *   SOCKET
3365  ***************************************************************************/
3366
3367 static int swrap_socket(int family, int type, int protocol)
3368 {
3369         struct socket_info *si = NULL;
3370         struct socket_info _si = { 0 };
3371         int fd;
3372         int ret;
3373         int real_type = type;
3374
3375         /*
3376          * Remove possible addition flags passed to socket() so
3377          * do not fail checking the type.
3378          * See https://lwn.net/Articles/281965/
3379          */
3380 #ifdef SOCK_CLOEXEC
3381         real_type &= ~SOCK_CLOEXEC;
3382 #endif
3383 #ifdef SOCK_NONBLOCK
3384         real_type &= ~SOCK_NONBLOCK;
3385 #endif
3386
3387         if (!socket_wrapper_enabled()) {
3388                 return libc_socket(family, type, protocol);
3389         }
3390
3391         switch (family) {
3392         case AF_INET:
3393 #ifdef HAVE_IPV6
3394         case AF_INET6:
3395 #endif
3396                 break;
3397 #ifdef AF_NETLINK
3398         case AF_NETLINK:
3399 #endif /* AF_NETLINK */
3400 #ifdef AF_PACKET
3401         case AF_PACKET:
3402 #endif /* AF_PACKET */
3403         case AF_UNIX:
3404                 fd = libc_socket(family, type, protocol);
3405                 if (fd != -1) {
3406                         /* Check if we have a stale fd and remove it */
3407                         swrap_remove_stale(fd);
3408                         SWRAP_LOG(SWRAP_LOG_TRACE,
3409                                   "Unix socket fd=%d",
3410                                   fd);
3411                 }
3412                 return fd;
3413         default:
3414                 errno = EAFNOSUPPORT;
3415                 return -1;
3416         }
3417
3418         switch (real_type) {
3419         case SOCK_STREAM:
3420                 break;
3421         case SOCK_DGRAM:
3422                 break;
3423         default:
3424                 errno = EPROTONOSUPPORT;
3425                 return -1;
3426         }
3427
3428         switch (protocol) {
3429         case 0:
3430                 break;
3431         case 6:
3432                 if (real_type == SOCK_STREAM) {
3433                         break;
3434                 }
3435                 FALL_THROUGH;
3436         case 17:
3437                 if (real_type == SOCK_DGRAM) {
3438                         break;
3439                 }
3440                 FALL_THROUGH;
3441         default:
3442                 errno = EPROTONOSUPPORT;
3443                 return -1;
3444         }
3445
3446         /*
3447          * We must call libc_socket with type, from the caller, not the version
3448          * we removed SOCK_CLOEXEC and SOCK_NONBLOCK from
3449          */
3450         fd = libc_socket(AF_UNIX, type, 0);
3451
3452         if (fd == -1) {
3453                 return -1;
3454         }
3455
3456         /* Check if we have a stale fd and remove it */
3457         swrap_remove_stale(fd);
3458
3459         si = &_si;
3460         si->family = family;
3461
3462         /* however, the rest of the socket_wrapper code expects just
3463          * the type, not the flags */
3464         si->type = real_type;
3465         si->protocol = protocol;
3466
3467         /*
3468          * Setup myname so getsockname() can succeed to find out the socket
3469          * type.
3470          */
3471         switch(si->family) {
3472         case AF_INET: {
3473                 struct sockaddr_in sin = {
3474                         .sin_family = AF_INET,
3475                 };
3476
3477                 si->myname.sa_socklen = sizeof(struct sockaddr_in);
3478                 memcpy(&si->myname.sa.in, &sin, si->myname.sa_socklen);
3479                 break;
3480         }
3481 #ifdef HAVE_IPV6
3482         case AF_INET6: {
3483                 struct sockaddr_in6 sin6 = {
3484                         .sin6_family = AF_INET6,
3485                 };
3486
3487                 si->myname.sa_socklen = sizeof(struct sockaddr_in6);
3488                 memcpy(&si->myname.sa.in6, &sin6, si->myname.sa_socklen);
3489                 break;
3490         }
3491 #endif
3492         default:
3493                 errno = EINVAL;
3494                 return -1;
3495         }
3496
3497         ret = swrap_create_socket(si, fd);
3498         if (ret == -1) {
3499                 int saved_errno = errno;
3500                 libc_close(fd);
3501                 errno = saved_errno;
3502                 return -1;
3503         }
3504
3505         SWRAP_LOG(SWRAP_LOG_TRACE,
3506                   "Created %s socket for protocol %s, fd=%d",
3507                   family == AF_INET ? "IPv4" : "IPv6",
3508                   real_type == SOCK_DGRAM ? "UDP" : "TCP",
3509                   fd);
3510
3511         return fd;
3512 }
3513
3514 int socket(int family, int type, int protocol)
3515 {
3516         return swrap_socket(family, type, protocol);
3517 }
3518
3519 /****************************************************************************
3520  *   SOCKETPAIR
3521  ***************************************************************************/
3522
3523 static int swrap_socketpair(int family, int type, int protocol, int sv[2])
3524 {
3525         int rc;
3526
3527         rc = libc_socketpair(family, type, protocol, sv);
3528         if (rc != -1) {
3529                 swrap_remove_stale(sv[0]);
3530                 swrap_remove_stale(sv[1]);
3531         }
3532
3533         return rc;
3534 }
3535
3536 int socketpair(int family, int type, int protocol, int sv[2])
3537 {
3538         return swrap_socketpair(family, type, protocol, sv);
3539 }
3540
3541 /****************************************************************************
3542  *   SOCKETPAIR
3543  ***************************************************************************/
3544
3545 #ifdef HAVE_TIMERFD_CREATE
3546 static int swrap_timerfd_create(int clockid, int flags)
3547 {
3548         int fd;
3549
3550         fd = libc_timerfd_create(clockid, flags);
3551         if (fd != -1) {
3552                 swrap_remove_stale(fd);
3553         }
3554
3555         return fd;
3556 }
3557
3558 int timerfd_create(int clockid, int flags)
3559 {
3560         return swrap_timerfd_create(clockid, flags);
3561 }
3562 #endif
3563
3564 /****************************************************************************
3565  *   PIPE
3566  ***************************************************************************/
3567
3568 static int swrap_pipe(int pipefd[2])
3569 {
3570         int rc;
3571
3572         rc = libc_pipe(pipefd);
3573         if (rc != -1) {
3574                 swrap_remove_stale(pipefd[0]);
3575                 swrap_remove_stale(pipefd[1]);
3576         }
3577
3578         return rc;
3579 }
3580
3581 int pipe(int pipefd[2])
3582 {
3583         return swrap_pipe(pipefd);
3584 }
3585
3586 /****************************************************************************
3587  *   ACCEPT
3588  ***************************************************************************/
3589
3590 static int swrap_accept(int s,
3591                         struct sockaddr *addr,
3592                         socklen_t *addrlen,
3593                         int flags)
3594 {
3595         struct socket_info *parent_si, *child_si;
3596         struct socket_info new_si = { 0 };
3597         int fd;
3598         int idx;
3599         struct swrap_address un_addr = {
3600                 .sa_socklen = sizeof(struct sockaddr_un),
3601         };
3602         struct swrap_address un_my_addr = {
3603                 .sa_socklen = sizeof(struct sockaddr_un),
3604         };
3605         struct swrap_address in_addr = {
3606                 .sa_socklen = sizeof(struct sockaddr_storage),
3607         };
3608         struct swrap_address in_my_addr = {
3609                 .sa_socklen = sizeof(struct sockaddr_storage),
3610         };
3611         int ret;
3612
3613         parent_si = find_socket_info(s);
3614         if (!parent_si) {
3615 #ifdef HAVE_ACCEPT4
3616                 return libc_accept4(s, addr, addrlen, flags);
3617 #else
3618                 UNUSED(flags);
3619                 return libc_accept(s, addr, addrlen);
3620 #endif
3621         }
3622
3623
3624         /*
3625          * prevent parent_si from being altered / closed
3626          * while we read it
3627          */
3628         SWRAP_LOCK_SI(parent_si);
3629
3630         /*
3631          * assume out sockaddr have the same size as the in parent
3632          * socket family
3633          */
3634         in_addr.sa_socklen = socket_length(parent_si->family);
3635         if (in_addr.sa_socklen <= 0) {
3636                 SWRAP_UNLOCK_SI(parent_si);
3637                 errno = EINVAL;
3638                 return -1;
3639         }
3640
3641         SWRAP_UNLOCK_SI(parent_si);
3642
3643 #ifdef HAVE_ACCEPT4
3644         ret = libc_accept4(s, &un_addr.sa.s, &un_addr.sa_socklen, flags);
3645 #else
3646         UNUSED(flags);
3647         ret = libc_accept(s, &un_addr.sa.s, &un_addr.sa_socklen);
3648 #endif
3649         if (ret == -1) {
3650                 int saved_errno = errno;
3651                 if (saved_errno == ENOTSOCK) {
3652                         /* Remove stale fds */
3653                         swrap_remove_stale(s);
3654                 }
3655                 errno = saved_errno;
3656                 return ret;
3657         }
3658
3659         fd = ret;
3660
3661         /* Check if we have a stale fd and remove it */
3662         swrap_remove_stale(fd);
3663
3664         if (un_addr.sa.un.sun_path[0] == '\0') {
3665                 /*
3666                  * FreeBSD seems to have a problem where
3667                  * accept4() on the unix socket doesn't
3668                  * ECONNABORTED for already disconnected connections.
3669                  *
3670                  * Let's try libc_getpeername() to get the peer address
3671                  * as a fallback, but it'll likely return ENOTCONN,
3672                  * which we have to map to ECONNABORTED.
3673                  */
3674                 un_addr.sa_socklen = sizeof(struct sockaddr_un),
3675                 ret = libc_getpeername(fd, &un_addr.sa.s, &un_addr.sa_socklen);
3676                 if (ret == -1) {
3677                         int saved_errno = errno;
3678                         libc_close(fd);
3679                         if (saved_errno == ENOTCONN) {
3680                                 /*
3681                                  * If the connection is already disconnected
3682                                  * we should return ECONNABORTED.
3683                                  */
3684                                 saved_errno = ECONNABORTED;
3685                         }
3686                         errno = saved_errno;
3687                         return ret;
3688                 }
3689         }
3690
3691         ret = libc_getsockname(fd,
3692                                &un_my_addr.sa.s,
3693                                &un_my_addr.sa_socklen);
3694         if (ret == -1) {
3695                 int saved_errno = errno;
3696                 libc_close(fd);
3697                 if (saved_errno == ENOTCONN) {
3698                         /*
3699                          * If the connection is already disconnected
3700                          * we should return ECONNABORTED.
3701                          */
3702                         saved_errno = ECONNABORTED;
3703                 }
3704                 errno = saved_errno;
3705                 return ret;
3706         }
3707
3708         SWRAP_LOCK_SI(parent_si);
3709
3710         ret = sockaddr_convert_from_un(parent_si,
3711                                        &un_addr.sa.un,
3712                                        un_addr.sa_socklen,
3713                                        parent_si->family,
3714                                        &in_addr.sa.s,
3715                                        &in_addr.sa_socklen);
3716         if (ret == -1) {
3717                 int saved_errno = errno;
3718                 SWRAP_UNLOCK_SI(parent_si);
3719                 libc_close(fd);
3720                 errno = saved_errno;
3721                 return ret;
3722         }
3723
3724         child_si = &new_si;
3725
3726         child_si->family = parent_si->family;
3727         child_si->type = parent_si->type;
3728         child_si->protocol = parent_si->protocol;
3729         child_si->bound = 1;
3730         child_si->is_server = 1;
3731         child_si->connected = 1;
3732
3733         SWRAP_UNLOCK_SI(parent_si);
3734
3735         child_si->peername = (struct swrap_address) {
3736                 .sa_socklen = in_addr.sa_socklen,
3737         };
3738         memcpy(&child_si->peername.sa.ss, &in_addr.sa.ss, in_addr.sa_socklen);
3739
3740         if (addr != NULL && addrlen != NULL) {
3741                 size_t copy_len = MIN(*addrlen, in_addr.sa_socklen);
3742                 if (copy_len > 0) {
3743                         memcpy(addr, &in_addr.sa.ss, copy_len);
3744                 }
3745                 *addrlen = in_addr.sa_socklen;
3746         }
3747
3748         ret = sockaddr_convert_from_un(child_si,
3749                                        &un_my_addr.sa.un,
3750                                        un_my_addr.sa_socklen,
3751                                        child_si->family,
3752                                        &in_my_addr.sa.s,
3753                                        &in_my_addr.sa_socklen);
3754         if (ret == -1) {
3755                 int saved_errno = errno;
3756                 libc_close(fd);
3757                 errno = saved_errno;
3758                 return ret;
3759         }
3760
3761         SWRAP_LOG(SWRAP_LOG_TRACE,
3762                   "accept() path=%s, fd=%d",
3763                   un_my_addr.sa.un.sun_path, s);
3764
3765         child_si->myname = (struct swrap_address) {
3766                 .sa_socklen = in_my_addr.sa_socklen,
3767         };
3768         memcpy(&child_si->myname.sa.ss, &in_my_addr.sa.ss, in_my_addr.sa_socklen);
3769
3770         idx = swrap_create_socket(&new_si, fd);
3771         if (idx == -1) {
3772                 int saved_errno = errno;
3773                 libc_close(fd);
3774                 errno = saved_errno;
3775                 return -1;
3776         }
3777
3778         if (addr != NULL) {
3779                 struct socket_info *si = swrap_get_socket_info(idx);
3780
3781                 SWRAP_LOCK_SI(si);
3782                 swrap_pcap_dump_packet(si, addr, SWRAP_ACCEPT_SEND, NULL, 0);
3783                 swrap_pcap_dump_packet(si, addr, SWRAP_ACCEPT_RECV, NULL, 0);
3784                 swrap_pcap_dump_packet(si, addr, SWRAP_ACCEPT_ACK, NULL, 0);
3785                 SWRAP_UNLOCK_SI(si);
3786         }
3787
3788         return fd;
3789 }
3790
3791 #ifdef HAVE_ACCEPT4
3792 int accept4(int s, struct sockaddr *addr, socklen_t *addrlen, int flags)
3793 {
3794         return swrap_accept(s, addr, (socklen_t *)addrlen, flags);
3795 }
3796 #endif
3797
3798 #ifdef HAVE_ACCEPT_PSOCKLEN_T
3799 int accept(int s, struct sockaddr *addr, Psocklen_t addrlen)
3800 #else
3801 int accept(int s, struct sockaddr *addr, socklen_t *addrlen)
3802 #endif
3803 {
3804         return swrap_accept(s, addr, (socklen_t *)addrlen, 0);
3805 }
3806
3807 static int autobind_start_init;
3808 static int autobind_start;
3809
3810 /* using sendto() or connect() on an unbound socket would give the
3811    recipient no way to reply, as unlike UDP and TCP, a unix domain
3812    socket can't auto-assign ephemeral port numbers, so we need to
3813    assign it here.
3814    Note: this might change the family from ipv6 to ipv4
3815 */
3816 static int swrap_auto_bind(int fd, struct socket_info *si, int family)
3817 {
3818         struct swrap_address un_addr = {
3819                 .sa_socklen = sizeof(struct sockaddr_un),
3820         };
3821         int i;
3822         char type;
3823         int ret;
3824         int port;
3825         struct stat st;
3826         char *swrap_dir = NULL;
3827
3828         swrap_mutex_lock(&autobind_start_mutex);
3829
3830         if (autobind_start_init != 1) {
3831                 autobind_start_init = 1;
3832                 autobind_start = getpid();
3833                 autobind_start %= 50000;
3834                 autobind_start += 10000;
3835         }
3836
3837         un_addr.sa.un.sun_family = AF_UNIX;
3838
3839         switch (family) {
3840         case AF_INET: {
3841                 struct sockaddr_in in;
3842
3843                 switch (si->type) {
3844                 case SOCK_STREAM:
3845                         type = SOCKET_TYPE_CHAR_TCP;
3846                         break;
3847                 case SOCK_DGRAM:
3848                         type = SOCKET_TYPE_CHAR_UDP;
3849                         break;
3850                 default:
3851                         errno = ESOCKTNOSUPPORT;
3852                         ret = -1;
3853                         goto done;
3854                 }
3855
3856                 memset(&in, 0, sizeof(in));
3857                 in.sin_family = AF_INET;
3858                 in.sin_addr.s_addr = htonl(swrap_ipv4_iface(
3859                                            socket_wrapper_default_iface()));
3860
3861                 si->myname = (struct swrap_address) {
3862                         .sa_socklen = sizeof(in),
3863                 };
3864                 memcpy(&si->myname.sa.in, &in, si->myname.sa_socklen);
3865                 break;
3866         }
3867 #ifdef HAVE_IPV6
3868         case AF_INET6: {
3869                 struct sockaddr_in6 in6;
3870
3871                 if (si->family != family) {
3872                         errno = ENETUNREACH;
3873                         ret = -1;
3874                         goto done;
3875                 }
3876
3877                 switch (si->type) {
3878                 case SOCK_STREAM:
3879                         type = SOCKET_TYPE_CHAR_TCP_V6;
3880                         break;
3881                 case SOCK_DGRAM:
3882                         type = SOCKET_TYPE_CHAR_UDP_V6;
3883                         break;
3884                 default:
3885                         errno = ESOCKTNOSUPPORT;
3886                         ret = -1;
3887                         goto done;
3888                 }
3889
3890                 memset(&in6, 0, sizeof(in6));
3891                 in6.sin6_family = AF_INET6;
3892                 in6.sin6_addr = *swrap_ipv6();
3893                 in6.sin6_addr.s6_addr[15] = socket_wrapper_default_iface();
3894
3895                 si->myname = (struct swrap_address) {
3896                         .sa_socklen = sizeof(in6),
3897                 };
3898                 memcpy(&si->myname.sa.in6, &in6, si->myname.sa_socklen);
3899                 break;
3900         }
3901 #endif
3902         default:
3903                 errno = ESOCKTNOSUPPORT;
3904                 ret = -1;
3905                 goto done;
3906         }
3907
3908         if (autobind_start > 60000) {
3909                 autobind_start = 10000;
3910         }
3911
3912         swrap_dir = socket_wrapper_dir();
3913         if (swrap_dir == NULL) {
3914                 errno = EINVAL;
3915                 ret = -1;
3916                 goto done;
3917         }
3918
3919         for (i = 0; i < SOCKET_MAX_SOCKETS; i++) {
3920                 port = autobind_start + i;
3921                 swrap_un_path(&un_addr.sa.un,
3922                               swrap_dir,
3923                               type,
3924                               socket_wrapper_default_iface(),
3925                               port);
3926                 if (stat(un_addr.sa.un.sun_path, &st) == 0) continue;
3927
3928                 ret = libc_bind(fd, &un_addr.sa.s, un_addr.sa_socklen);
3929                 if (ret == -1) {
3930                         goto done;
3931                 }
3932
3933                 si->un_addr = un_addr.sa.un;
3934
3935                 si->bound = 1;
3936                 autobind_start = port + 1;
3937                 break;
3938         }
3939         if (i == SOCKET_MAX_SOCKETS) {
3940                 SWRAP_LOG(SWRAP_LOG_ERROR, "Too many open unix sockets (%u) for "
3941                                            "interface "SOCKET_FORMAT,
3942                                            SOCKET_MAX_SOCKETS,
3943                                            type,
3944                                            socket_wrapper_default_iface(),
3945                                            0);
3946                 errno = ENFILE;
3947                 ret = -1;
3948                 goto done;
3949         }
3950
3951         si->family = family;
3952         set_port(si->family, port, &si->myname);
3953
3954         ret = 0;
3955
3956 done:
3957         SAFE_FREE(swrap_dir);
3958         swrap_mutex_unlock(&autobind_start_mutex);
3959         return ret;
3960 }
3961
3962 /****************************************************************************
3963  *   CONNECT
3964  ***************************************************************************/
3965
3966 static int swrap_connect(int s, const struct sockaddr *serv_addr,
3967                          socklen_t addrlen)
3968 {
3969         int ret;
3970         struct swrap_address un_addr = {
3971                 .sa_socklen = sizeof(struct sockaddr_un),
3972         };
3973         struct socket_info *si = find_socket_info(s);
3974         int bcast = 0;
3975
3976         if (!si) {
3977                 return libc_connect(s, serv_addr, addrlen);
3978         }
3979
3980         SWRAP_LOCK_SI(si);
3981
3982         if (si->bound == 0) {
3983                 ret = swrap_auto_bind(s, si, serv_addr->sa_family);
3984                 if (ret == -1) {
3985                         goto done;
3986                 }
3987         }
3988
3989         if (si->family != serv_addr->sa_family) {
3990                 SWRAP_LOG(SWRAP_LOG_ERROR,
3991                           "called for fd=%d (family=%d) called with invalid family=%d",
3992                           s, si->family, serv_addr->sa_family);
3993                 errno = EINVAL;
3994                 ret = -1;
3995                 goto done;
3996         }
3997
3998         ret = sockaddr_convert_to_un(si, serv_addr,
3999                                      addrlen, &un_addr.sa.un, 0, &bcast);
4000         if (ret == -1) {
4001                 goto done;
4002         }
4003
4004         if (bcast) {
4005                 errno = ENETUNREACH;
4006                 ret = -1;
4007                 goto done;
4008         }
4009
4010         if (si->type == SOCK_DGRAM) {
4011                 si->defer_connect = 1;
4012                 ret = 0;
4013         } else {
4014                 swrap_pcap_dump_packet(si, serv_addr, SWRAP_CONNECT_SEND, NULL, 0);
4015
4016                 ret = libc_connect(s,
4017                                    &un_addr.sa.s,
4018                                    un_addr.sa_socklen);
4019         }
4020
4021         SWRAP_LOG(SWRAP_LOG_TRACE,
4022                   "connect() path=%s, fd=%d",
4023                   un_addr.sa.un.sun_path, s);
4024
4025
4026         /* to give better errors */
4027         if (ret == -1 && errno == ENOENT) {
4028                 errno = EHOSTUNREACH;
4029         }
4030
4031         if (ret == 0) {
4032                 si->peername = (struct swrap_address) {
4033                         .sa_socklen = addrlen,
4034                 };
4035
4036                 memcpy(&si->peername.sa.ss, serv_addr, addrlen);
4037                 si->connected = 1;
4038
4039                 /*
4040                  * When we connect() on a socket than we have to bind the
4041                  * outgoing connection on the interface we use for the
4042                  * transport. We already bound it on the right interface
4043                  * but here we have to update the name so getsockname()
4044                  * returns correct information.
4045                  */
4046                 if (si->bindname.sa_socklen > 0) {
4047                         si->myname = (struct swrap_address) {
4048                                 .sa_socklen = si->bindname.sa_socklen,
4049                         };
4050
4051                         memcpy(&si->myname.sa.ss,
4052                                &si->bindname.sa.ss,
4053                                si->bindname.sa_socklen);
4054
4055                         /* Cleanup bindname */
4056                         si->bindname = (struct swrap_address) {
4057                                 .sa_socklen = 0,
4058                         };
4059                 }
4060
4061                 swrap_pcap_dump_packet(si, serv_addr, SWRAP_CONNECT_RECV, NULL, 0);
4062                 swrap_pcap_dump_packet(si, serv_addr, SWRAP_CONNECT_ACK, NULL, 0);
4063         } else {
4064                 swrap_pcap_dump_packet(si, serv_addr, SWRAP_CONNECT_UNREACH, NULL, 0);
4065         }
4066
4067 done:
4068         SWRAP_UNLOCK_SI(si);
4069         return ret;
4070 }
4071
4072 int connect(int s, const struct sockaddr *serv_addr, socklen_t addrlen)
4073 {
4074         return swrap_connect(s, serv_addr, addrlen);
4075 }
4076
4077 /****************************************************************************
4078  *   BIND
4079  ***************************************************************************/
4080
4081 static int swrap_bind(int s, const struct sockaddr *myaddr, socklen_t addrlen)
4082 {
4083         int ret;
4084         struct swrap_address un_addr = {
4085                 .sa_socklen = sizeof(struct sockaddr_un),
4086         };
4087         struct socket_info *si = find_socket_info(s);
4088         int bind_error = 0;
4089 #if 0 /* FIXME */
4090         bool in_use;
4091 #endif
4092
4093         if (!si) {
4094                 return libc_bind(s, myaddr, addrlen);
4095         }
4096
4097         SWRAP_LOCK_SI(si);
4098
4099         switch (si->family) {
4100         case AF_INET: {
4101                 const struct sockaddr_in *sin;
4102                 if (addrlen < sizeof(struct sockaddr_in)) {
4103                         bind_error = EINVAL;
4104                         break;
4105                 }
4106
4107                 sin = (const struct sockaddr_in *)(const void *)myaddr;
4108
4109                 if (sin->sin_family != AF_INET) {
4110                         bind_error = EAFNOSUPPORT;
4111                 }
4112
4113                 /* special case for AF_UNSPEC */
4114                 if (sin->sin_family == AF_UNSPEC &&
4115                     (sin->sin_addr.s_addr == htonl(INADDR_ANY)))
4116                 {
4117                         bind_error = 0;
4118                 }
4119
4120                 break;
4121         }
4122 #ifdef HAVE_IPV6
4123         case AF_INET6: {
4124                 const struct sockaddr_in6 *sin6;
4125                 if (addrlen < sizeof(struct sockaddr_in6)) {
4126                         bind_error = EINVAL;
4127                         break;
4128                 }
4129
4130                 sin6 = (const struct sockaddr_in6 *)(const void *)myaddr;
4131
4132                 if (sin6->sin6_family != AF_INET6) {
4133                         bind_error = EAFNOSUPPORT;
4134                 }
4135
4136                 break;
4137         }
4138 #endif
4139         default:
4140                 bind_error = EINVAL;
4141                 break;
4142         }
4143
4144         if (bind_error != 0) {
4145                 errno = bind_error;
4146                 ret = -1;
4147                 goto out;
4148         }
4149
4150 #if 0 /* FIXME */
4151         in_use = check_addr_port_in_use(myaddr, addrlen);
4152         if (in_use) {
4153                 errno = EADDRINUSE;
4154                 ret = -1;
4155                 goto out;
4156         }
4157 #endif
4158
4159         si->myname.sa_socklen = addrlen;
4160         memcpy(&si->myname.sa.ss, myaddr, addrlen);
4161
4162         ret = sockaddr_convert_to_un(si,
4163                                      myaddr,
4164                                      addrlen,
4165                                      &un_addr.sa.un,
4166                                      1,
4167                                      &si->bcast);
4168         if (ret == -1) {
4169                 goto out;
4170         }
4171
4172         unlink(un_addr.sa.un.sun_path);
4173
4174         ret = libc_bind(s, &un_addr.sa.s, un_addr.sa_socklen);
4175
4176         SWRAP_LOG(SWRAP_LOG_TRACE,
4177                   "bind() path=%s, fd=%d",
4178                   un_addr.sa.un.sun_path, s);
4179
4180         if (ret == 0) {
4181                 si->bound = 1;
4182         }
4183
4184 out:
4185         SWRAP_UNLOCK_SI(si);
4186
4187         return ret;
4188 }
4189
4190 int bind(int s, const struct sockaddr *myaddr, socklen_t addrlen)
4191 {
4192         return swrap_bind(s, myaddr, addrlen);
4193 }
4194
4195 /****************************************************************************
4196  *   BINDRESVPORT
4197  ***************************************************************************/
4198
4199 #ifdef HAVE_BINDRESVPORT
4200 static int swrap_getsockname(int s, struct sockaddr *name, socklen_t *addrlen);
4201
4202 static int swrap_bindresvport_sa(int sd, struct sockaddr *sa)
4203 {
4204         struct swrap_address myaddr = {
4205                 .sa_socklen = sizeof(struct sockaddr_storage),
4206         };
4207         socklen_t salen;
4208         static uint16_t port;
4209         uint16_t i;
4210         int rc = -1;
4211         int af;
4212
4213 #define SWRAP_STARTPORT 600
4214 #define SWRAP_ENDPORT (IPPORT_RESERVED - 1)
4215 #define SWRAP_NPORTS (SWRAP_ENDPORT - SWRAP_STARTPORT + 1)
4216
4217         if (port == 0) {
4218                 port = (getpid() % SWRAP_NPORTS) + SWRAP_STARTPORT;
4219         }
4220
4221         if (sa == NULL) {
4222                 salen = myaddr.sa_socklen;
4223                 sa = &myaddr.sa.s;
4224
4225                 rc = swrap_getsockname(sd, &myaddr.sa.s, &salen);
4226                 if (rc < 0) {
4227                         return -1;
4228                 }
4229
4230                 af = sa->sa_family;
4231                 memset(&myaddr.sa.ss, 0, salen);
4232         } else {
4233                 af = sa->sa_family;
4234         }
4235
4236         for (i = 0; i < SWRAP_NPORTS; i++, port++) {
4237                 switch(af) {
4238                 case AF_INET: {
4239                         struct sockaddr_in *sinp = (struct sockaddr_in *)(void *)sa;
4240
4241                         salen = sizeof(struct sockaddr_in);
4242                         sinp->sin_port = htons(port);
4243                         break;
4244                 }
4245                 case AF_INET6: {
4246                         struct sockaddr_in6 *sin6p = (struct sockaddr_in6 *)(void *)sa;
4247
4248                         salen = sizeof(struct sockaddr_in6);
4249                         sin6p->sin6_port = htons(port);
4250                         break;
4251                 }
4252                 default:
4253                         errno = EAFNOSUPPORT;
4254                         return -1;
4255                 }
4256                 sa->sa_family = af;
4257
4258                 if (port > SWRAP_ENDPORT) {
4259                         port = SWRAP_STARTPORT;
4260                 }
4261
4262                 rc = swrap_bind(sd, (struct sockaddr *)sa, salen);
4263                 if (rc == 0 || errno != EADDRINUSE) {
4264                         break;
4265                 }
4266         }
4267
4268         return rc;
4269 }
4270
4271 int bindresvport(int sockfd, struct sockaddr_in *sinp)
4272 {
4273         return swrap_bindresvport_sa(sockfd, (struct sockaddr *)sinp);
4274 }
4275 #endif
4276
4277 /****************************************************************************
4278  *   LISTEN
4279  ***************************************************************************/
4280
4281 static int swrap_listen(int s, int backlog)
4282 {
4283         int ret;
4284         struct socket_info *si = find_socket_info(s);
4285
4286         if (!si) {
4287                 return libc_listen(s, backlog);
4288         }
4289
4290         SWRAP_LOCK_SI(si);
4291
4292         if (si->bound == 0) {
4293                 ret = swrap_auto_bind(s, si, si->family);
4294                 if (ret == -1) {
4295                         errno = EADDRINUSE;
4296                         goto out;
4297                 }
4298         }
4299
4300         ret = libc_listen(s, backlog);
4301         if (ret == 0) {
4302                 si->listening = 1;
4303         }
4304
4305 out:
4306         SWRAP_UNLOCK_SI(si);
4307
4308         return ret;
4309 }
4310
4311 int listen(int s, int backlog)
4312 {
4313         return swrap_listen(s, backlog);
4314 }
4315
4316 /****************************************************************************
4317  *   FOPEN
4318  ***************************************************************************/
4319
4320 static FILE *swrap_fopen(const char *name, const char *mode)
4321 {
4322         FILE *fp;
4323
4324         fp = libc_fopen(name, mode);
4325         if (fp != NULL) {
4326                 int fd = fileno(fp);
4327
4328                 swrap_remove_stale(fd);
4329         }
4330
4331         return fp;
4332 }
4333
4334 FILE *fopen(const char *name, const char *mode)
4335 {
4336         return swrap_fopen(name, mode);
4337 }
4338
4339 /****************************************************************************
4340  *   FOPEN64
4341  ***************************************************************************/
4342
4343 #ifdef HAVE_FOPEN64
4344 static FILE *swrap_fopen64(const char *name, const char *mode)
4345 {
4346         FILE *fp;
4347
4348         fp = libc_fopen64(name, mode);
4349         if (fp != NULL) {
4350                 int fd = fileno(fp);
4351
4352                 swrap_remove_stale(fd);
4353         }
4354
4355         return fp;
4356 }
4357
4358 FILE *fopen64(const char *name, const char *mode)
4359 {
4360         return swrap_fopen64(name, mode);
4361 }
4362 #endif /* HAVE_FOPEN64 */
4363
4364 /****************************************************************************
4365  *   OPEN
4366  ***************************************************************************/
4367
4368 static int swrap_vopen(const char *pathname, int flags, va_list ap)
4369 {
4370         int ret;
4371
4372         ret = libc_vopen(pathname, flags, ap);
4373         if (ret != -1) {
4374                 /*
4375                  * There are methods for closing descriptors (libc-internal code
4376                  * paths, direct syscalls) which close descriptors in ways that
4377                  * we can't intercept, so try to recover when we notice that
4378                  * that's happened
4379                  */
4380                 swrap_remove_stale(ret);
4381         }
4382         return ret;
4383 }
4384
4385 int open(const char *pathname, int flags, ...)
4386 {
4387         va_list ap;
4388         int fd;
4389
4390         va_start(ap, flags);
4391         fd = swrap_vopen(pathname, flags, ap);
4392         va_end(ap);
4393
4394         return fd;
4395 }
4396
4397 /****************************************************************************
4398  *   OPEN64
4399  ***************************************************************************/
4400
4401 #ifdef HAVE_OPEN64
4402 static int swrap_vopen64(const char *pathname, int flags, va_list ap)
4403 {
4404         int ret;
4405
4406         ret = libc_vopen64(pathname, flags, ap);
4407         if (ret != -1) {
4408                 /*
4409                  * There are methods for closing descriptors (libc-internal code
4410                  * paths, direct syscalls) which close descriptors in ways that
4411                  * we can't intercept, so try to recover when we notice that
4412                  * that's happened
4413                  */
4414                 swrap_remove_stale(ret);
4415         }
4416         return ret;
4417 }
4418
4419 int open64(const char *pathname, int flags, ...)
4420 {
4421         va_list ap;
4422         int fd;
4423
4424         va_start(ap, flags);
4425         fd = swrap_vopen64(pathname, flags, ap);
4426         va_end(ap);
4427
4428         return fd;
4429 }
4430 #endif /* HAVE_OPEN64 */
4431
4432 /****************************************************************************
4433  *   OPENAT
4434  ***************************************************************************/
4435
4436 static int swrap_vopenat(int dirfd, const char *path, int flags, va_list ap)
4437 {
4438         int ret;
4439
4440         ret = libc_vopenat(dirfd, path, flags, ap);
4441         if (ret != -1) {
4442                 /*
4443                  * There are methods for closing descriptors (libc-internal code
4444                  * paths, direct syscalls) which close descriptors in ways that
4445                  * we can't intercept, so try to recover when we notice that
4446                  * that's happened
4447                  */
4448                 swrap_remove_stale(ret);
4449         }
4450
4451         return ret;
4452 }
4453
4454 int openat(int dirfd, const char *path, int flags, ...)
4455 {
4456         va_list ap;
4457         int fd;
4458
4459         va_start(ap, flags);
4460         fd = swrap_vopenat(dirfd, path, flags, ap);
4461         va_end(ap);
4462
4463         return fd;
4464 }
4465
4466 /****************************************************************************
4467  *   GETPEERNAME
4468  ***************************************************************************/
4469
4470 static int swrap_getpeername(int s, struct sockaddr *name, socklen_t *addrlen)
4471 {
4472         struct socket_info *si = find_socket_info(s);
4473         socklen_t len;
4474         int ret = -1;
4475
4476         if (!si) {
4477                 return libc_getpeername(s, name, addrlen);
4478         }
4479
4480         SWRAP_LOCK_SI(si);
4481
4482         if (si->peername.sa_socklen == 0)
4483         {
4484                 errno = ENOTCONN;
4485                 goto out;
4486         }
4487
4488         len = MIN(*addrlen, si->peername.sa_socklen);
4489         if (len == 0) {
4490                 ret = 0;
4491                 goto out;
4492         }
4493
4494         memcpy(name, &si->peername.sa.ss, len);
4495         *addrlen = si->peername.sa_socklen;
4496
4497         ret = 0;
4498 out:
4499         SWRAP_UNLOCK_SI(si);
4500
4501         return ret;
4502 }
4503
4504 #ifdef HAVE_ACCEPT_PSOCKLEN_T
4505 int getpeername(int s, struct sockaddr *name, Psocklen_t addrlen)
4506 #else
4507 int getpeername(int s, struct sockaddr *name, socklen_t *addrlen)
4508 #endif
4509 {
4510         return swrap_getpeername(s, name, (socklen_t *)addrlen);
4511 }
4512
4513 /****************************************************************************
4514  *   GETSOCKNAME
4515  ***************************************************************************/
4516
4517 static int swrap_getsockname(int s, struct sockaddr *name, socklen_t *addrlen)
4518 {
4519         struct socket_info *si = find_socket_info(s);
4520         socklen_t len;
4521         int ret = -1;
4522
4523         if (!si) {
4524                 return libc_getsockname(s, name, addrlen);
4525         }
4526
4527         SWRAP_LOCK_SI(si);
4528
4529         len = MIN(*addrlen, si->myname.sa_socklen);
4530         if (len == 0) {
4531                 ret = 0;
4532                 goto out;
4533         }
4534
4535         memcpy(name, &si->myname.sa.ss, len);
4536         *addrlen = si->myname.sa_socklen;
4537
4538         ret = 0;
4539 out:
4540         SWRAP_UNLOCK_SI(si);
4541
4542         return ret;
4543 }
4544
4545 #ifdef HAVE_ACCEPT_PSOCKLEN_T
4546 int getsockname(int s, struct sockaddr *name, Psocklen_t addrlen)
4547 #else
4548 int getsockname(int s, struct sockaddr *name, socklen_t *addrlen)
4549 #endif
4550 {
4551         return swrap_getsockname(s, name, (socklen_t *)addrlen);
4552 }
4553
4554 /****************************************************************************
4555  *   GETSOCKOPT
4556  ***************************************************************************/
4557
4558 #ifndef SO_PROTOCOL
4559 # ifdef SO_PROTOTYPE /* The Solaris name */
4560 #  define SO_PROTOCOL SO_PROTOTYPE
4561 # endif /* SO_PROTOTYPE */
4562 #endif /* SO_PROTOCOL */
4563
4564 static int swrap_getsockopt(int s, int level, int optname,
4565                             void *optval, socklen_t *optlen)
4566 {
4567         struct socket_info *si = find_socket_info(s);
4568         int ret;
4569
4570         if (!si) {
4571                 return libc_getsockopt(s,
4572                                        level,
4573                                        optname,
4574                                        optval,
4575                                        optlen);
4576         }
4577
4578         SWRAP_LOCK_SI(si);
4579
4580         if (level == SOL_SOCKET) {
4581                 switch (optname) {
4582 #ifdef SO_DOMAIN
4583                 case SO_DOMAIN:
4584                         if (optval == NULL || optlen == NULL ||
4585                             *optlen < (socklen_t)sizeof(int)) {
4586                                 errno = EINVAL;
4587                                 ret = -1;
4588                                 goto done;
4589                         }
4590
4591                         *optlen = sizeof(int);
4592                         *(int *)optval = si->family;
4593                         ret = 0;
4594                         goto done;
4595 #endif /* SO_DOMAIN */
4596
4597 #ifdef SO_PROTOCOL
4598                 case SO_PROTOCOL:
4599                         if (optval == NULL || optlen == NULL ||
4600                             *optlen < (socklen_t)sizeof(int)) {
4601                                 errno = EINVAL;
4602                                 ret = -1;
4603                                 goto done;
4604                         }
4605
4606                         *optlen = sizeof(int);
4607                         *(int *)optval = si->protocol;
4608                         ret = 0;
4609                         goto done;
4610 #endif /* SO_PROTOCOL */
4611                 case SO_TYPE:
4612                         if (optval == NULL || optlen == NULL ||
4613                             *optlen < (socklen_t)sizeof(int)) {
4614                                 errno = EINVAL;
4615                                 ret = -1;
4616                                 goto done;
4617                         }
4618
4619                         *optlen = sizeof(int);
4620                         *(int *)optval = si->type;
4621                         ret = 0;
4622                         goto done;
4623                 default:
4624                         ret = libc_getsockopt(s,
4625                                               level,
4626                                               optname,
4627                                               optval,
4628                                               optlen);
4629                         goto done;
4630                 }
4631         } else if (level == IPPROTO_TCP) {
4632                 switch (optname) {
4633 #ifdef TCP_NODELAY
4634                 case TCP_NODELAY:
4635                         /*
4636                          * This enables sending packets directly out over TCP.
4637                          * As a unix socket is doing that any way, report it as
4638                          * enabled.
4639                          */
4640                         if (optval == NULL || optlen == NULL ||
4641                             *optlen < (socklen_t)sizeof(int)) {
4642                                 errno = EINVAL;
4643                                 ret = -1;
4644                                 goto done;
4645                         }
4646
4647                         *optlen = sizeof(int);
4648                         *(int *)optval = si->tcp_nodelay;
4649
4650                         ret = 0;
4651                         goto done;
4652 #endif /* TCP_NODELAY */
4653 #ifdef TCP_INFO
4654                 case TCP_INFO: {
4655                         struct tcp_info info;
4656                         socklen_t ilen = sizeof(info);
4657
4658 #ifdef HAVE_NETINET_TCP_FSM_H
4659 /* This is FreeBSD */
4660 # define __TCP_LISTEN TCPS_LISTEN
4661 # define __TCP_ESTABLISHED TCPS_ESTABLISHED
4662 # define __TCP_CLOSE TCPS_CLOSED
4663 #else
4664 /* This is Linux */
4665 # define __TCP_LISTEN TCP_LISTEN
4666 # define __TCP_ESTABLISHED TCP_ESTABLISHED
4667 # define __TCP_CLOSE TCP_CLOSE
4668 #endif
4669
4670                         ZERO_STRUCT(info);
4671                         if (si->listening) {
4672                                 info.tcpi_state = __TCP_LISTEN;
4673                         } else if (si->connected) {
4674                                 /*
4675                                  * For now we just fake a few values
4676                                  * supported both by FreeBSD and Linux
4677                                  */
4678                                 info.tcpi_state = __TCP_ESTABLISHED;
4679                                 info.tcpi_rto = 200000;  /* 200 msec */
4680                                 info.tcpi_rtt = 5000;    /* 5 msec */
4681                                 info.tcpi_rttvar = 5000; /* 5 msec */
4682                         } else {
4683                                 info.tcpi_state = __TCP_CLOSE;
4684                                 info.tcpi_rto = 1000000;  /* 1 sec */
4685                                 info.tcpi_rtt = 0;
4686                                 info.tcpi_rttvar = 250000; /* 250 msec */
4687                         }
4688
4689                         if (optval == NULL || optlen == NULL ||
4690                             *optlen < (socklen_t)ilen) {
4691                                 errno = EINVAL;
4692                                 ret = -1;
4693                                 goto done;
4694                         }
4695
4696                         *optlen = ilen;
4697                         memcpy(optval, &info, ilen);
4698
4699                         ret = 0;
4700                         goto done;
4701                 }
4702 #endif /* TCP_INFO */
4703                 default:
4704                         break;
4705                 }
4706         }
4707
4708         errno = ENOPROTOOPT;
4709         ret = -1;
4710
4711 done:
4712         SWRAP_UNLOCK_SI(si);
4713         return ret;
4714 }
4715
4716 #ifdef HAVE_ACCEPT_PSOCKLEN_T
4717 int getsockopt(int s, int level, int optname, void *optval, Psocklen_t optlen)
4718 #else
4719 int getsockopt(int s, int level, int optname, void *optval, socklen_t *optlen)
4720 #endif
4721 {
4722         return swrap_getsockopt(s, level, optname, optval, (socklen_t *)optlen);
4723 }
4724
4725 /****************************************************************************
4726  *   SETSOCKOPT
4727  ***************************************************************************/
4728
4729 static int swrap_setsockopt(int s, int level, int optname,
4730                             const void *optval, socklen_t optlen)
4731 {
4732         struct socket_info *si = find_socket_info(s);
4733         int ret;
4734
4735         if (!si) {
4736                 return libc_setsockopt(s,
4737                                        level,
4738                                        optname,
4739                                        optval,
4740                                        optlen);
4741         }
4742
4743         if (level == SOL_SOCKET) {
4744                 return libc_setsockopt(s,
4745                                        level,
4746                                        optname,
4747                                        optval,
4748                                        optlen);
4749         }
4750
4751         SWRAP_LOCK_SI(si);
4752
4753         if (level == IPPROTO_TCP) {
4754                 switch (optname) {
4755 #ifdef TCP_NODELAY
4756                 case TCP_NODELAY: {
4757                         int i;
4758
4759                         /*
4760                          * This enables sending packets directly out over TCP.
4761                          * A unix socket is doing that any way.
4762                          */
4763                         if (optval == NULL || optlen == 0 ||
4764                             optlen < (socklen_t)sizeof(int)) {
4765                                 errno = EINVAL;
4766                                 ret = -1;
4767                                 goto done;
4768                         }
4769
4770                         i = *discard_const_p(int, optval);
4771                         if (i != 0 && i != 1) {
4772                                 errno = EINVAL;
4773                                 ret = -1;
4774                                 goto done;
4775                         }
4776                         si->tcp_nodelay = i;
4777
4778                         ret = 0;
4779                         goto done;
4780                 }
4781 #endif /* TCP_NODELAY */
4782                 default:
4783                         break;
4784                 }
4785         }
4786
4787         switch (si->family) {
4788         case AF_INET:
4789                 if (level == IPPROTO_IP) {
4790 #ifdef IP_PKTINFO
4791                         if (optname == IP_PKTINFO) {
4792                                 si->pktinfo = AF_INET;
4793                         }
4794 #endif /* IP_PKTINFO */
4795                 }
4796                 ret = 0;
4797                 goto done;
4798 #ifdef HAVE_IPV6
4799         case AF_INET6:
4800                 if (level == IPPROTO_IPV6) {
4801 #ifdef IPV6_RECVPKTINFO
4802                         if (optname == IPV6_RECVPKTINFO) {
4803                                 si->pktinfo = AF_INET6;
4804                         }
4805 #endif /* IPV6_PKTINFO */
4806                 }
4807                 ret = 0;
4808                 goto done;
4809 #endif
4810         default:
4811                 errno = ENOPROTOOPT;
4812                 ret = -1;
4813                 goto done;
4814         }
4815
4816 done:
4817         SWRAP_UNLOCK_SI(si);
4818         return ret;
4819 }
4820
4821 int setsockopt(int s, int level, int optname,
4822                const void *optval, socklen_t optlen)
4823 {
4824         return swrap_setsockopt(s, level, optname, optval, optlen);
4825 }
4826
4827 /****************************************************************************
4828  *   IOCTL
4829  ***************************************************************************/
4830
4831 static int swrap_vioctl(int s, unsigned long int r, va_list va)
4832 {
4833         struct socket_info *si = find_socket_info(s);
4834         va_list ap;
4835         int *value_ptr = NULL;
4836         int rc;
4837
4838         if (!si) {
4839                 return libc_vioctl(s, r, va);
4840         }
4841
4842         SWRAP_LOCK_SI(si);
4843
4844         va_copy(ap, va);
4845
4846         rc = libc_vioctl(s, r, va);
4847
4848         switch (r) {
4849         case FIONREAD:
4850                 if (rc == 0) {
4851                         value_ptr = ((int *)va_arg(ap, int *));
4852                 }
4853
4854                 if (rc == -1 && errno != EAGAIN && errno != ENOBUFS) {
4855                         swrap_pcap_dump_packet(si, NULL, SWRAP_PENDING_RST, NULL, 0);
4856                 } else if (value_ptr != NULL && *value_ptr == 0) { /* END OF FILE */
4857                         swrap_pcap_dump_packet(si, NULL, SWRAP_PENDING_RST, NULL, 0);
4858                 }
4859                 break;
4860 #ifdef FIONWRITE
4861         case FIONWRITE:
4862                 /* this is FreeBSD */
4863                 FALL_THROUGH; /* to TIOCOUTQ */
4864 #endif /* FIONWRITE */
4865         case TIOCOUTQ: /* same as SIOCOUTQ on Linux */
4866                 /*
4867                  * This may return more bytes then the application
4868                  * sent into the socket, for tcp it should
4869                  * return the number of unacked bytes.
4870                  *
4871                  * On AF_UNIX, all bytes are immediately acked!
4872                  */
4873                 if (rc == 0) {
4874                         value_ptr = ((int *)va_arg(ap, int *));
4875                         *value_ptr = 0;
4876                 }
4877                 break;
4878         }
4879
4880         va_end(ap);
4881
4882         SWRAP_UNLOCK_SI(si);
4883         return rc;
4884 }
4885
4886 #ifdef HAVE_IOCTL_INT
4887 int ioctl(int s, int r, ...)
4888 #else
4889 int ioctl(int s, unsigned long int r, ...)
4890 #endif
4891 {
4892         va_list va;
4893         int rc;
4894
4895         va_start(va, r);
4896
4897         rc = swrap_vioctl(s, (unsigned long int) r, va);
4898
4899         va_end(va);
4900
4901         return rc;
4902 }
4903
4904 /*****************
4905  * CMSG
4906  *****************/
4907
4908 #ifdef HAVE_STRUCT_MSGHDR_MSG_CONTROL
4909
4910 #ifndef CMSG_ALIGN
4911 # ifdef _ALIGN /* BSD */
4912 #define CMSG_ALIGN _ALIGN
4913 # else
4914 #define CMSG_ALIGN(len) (((len) + sizeof(size_t) - 1) & ~(sizeof(size_t) - 1))
4915 # endif /* _ALIGN */
4916 #endif /* CMSG_ALIGN */
4917
4918 /**
4919  * @brief Add a cmsghdr to a msghdr.
4920  *
4921  * This is an function to add any type of cmsghdr. It will operate on the
4922  * msg->msg_control and msg->msg_controllen you pass in by adapting them to
4923  * the buffer position after the added cmsg element. Hence, this function is
4924  * intended to be used with an intermediate msghdr and not on the original
4925  * one handed in by the client.
4926  *
4927  * @param[in]  msg      The msghdr to which to add the cmsg.
4928  *
4929  * @param[in]  level    The cmsg level to set.
4930  *
4931  * @param[in]  type     The cmsg type to set.
4932  *
4933  * @param[in]  data     The cmsg data to set.
4934  *
4935  * @param[in]  len      the length of the data to set.
4936  */
4937 static void swrap_msghdr_add_cmsghdr(struct msghdr *msg,
4938                                      int level,
4939                                      int type,
4940                                      const void *data,
4941                                      size_t len)
4942 {
4943         size_t cmlen = CMSG_LEN(len);
4944         size_t cmspace = CMSG_SPACE(len);
4945         uint8_t cmbuf[cmspace];
4946         void *cast_ptr = (void *)cmbuf;
4947         struct cmsghdr *cm = (struct cmsghdr *)cast_ptr;
4948         uint8_t *p;
4949
4950         memset(cmbuf, 0, cmspace);
4951
4952         if (msg->msg_controllen < cmlen) {
4953                 cmlen = msg->msg_controllen;
4954                 msg->msg_flags |= MSG_CTRUNC;
4955         }
4956
4957         if (msg->msg_controllen < cmspace) {
4958                 cmspace = msg->msg_controllen;
4959         }
4960
4961         /*
4962          * We copy the full input data into an intermediate cmsghdr first
4963          * in order to more easily cope with truncation.
4964          */
4965         cm->cmsg_len = cmlen;
4966         cm->cmsg_level = level;
4967         cm->cmsg_type = type;
4968         memcpy(CMSG_DATA(cm), data, len);
4969
4970         /*
4971          * We now copy the possibly truncated buffer.
4972          * We copy cmlen bytes, but consume cmspace bytes,
4973          * leaving the possible padding uninitialiazed.
4974          */
4975         p = (uint8_t *)msg->msg_control;
4976         memcpy(p, cm, cmlen);
4977         p += cmspace;
4978         msg->msg_control = p;
4979         msg->msg_controllen -= cmspace;
4980
4981         return;
4982 }
4983
4984 static int swrap_msghdr_add_pktinfo(struct socket_info *si,
4985                                     struct msghdr *msg)
4986 {
4987         /* Add packet info */
4988         switch (si->pktinfo) {
4989 #if defined(IP_PKTINFO) && (defined(HAVE_STRUCT_IN_PKTINFO) || defined(IP_RECVDSTADDR))
4990         case AF_INET: {
4991                 struct sockaddr_in *sin;
4992 #if defined(HAVE_STRUCT_IN_PKTINFO)
4993                 struct in_pktinfo pkt;
4994 #elif defined(IP_RECVDSTADDR)
4995                 struct in_addr pkt;
4996 #endif
4997
4998                 if (si->bindname.sa_socklen == sizeof(struct sockaddr_in)) {
4999                         sin = &si->bindname.sa.in;
5000                 } else {
5001                         if (si->myname.sa_socklen != sizeof(struct sockaddr_in)) {
5002                                 return 0;
5003                         }
5004                         sin = &si->myname.sa.in;
5005                 }
5006
5007                 ZERO_STRUCT(pkt);
5008
5009 #if defined(HAVE_STRUCT_IN_PKTINFO)
5010                 pkt.ipi_ifindex = socket_wrapper_default_iface();
5011                 pkt.ipi_addr.s_addr = sin->sin_addr.s_addr;
5012 #elif defined(IP_RECVDSTADDR)
5013                 pkt = sin->sin_addr;
5014 #endif
5015
5016                 swrap_msghdr_add_cmsghdr(msg, IPPROTO_IP, IP_PKTINFO,
5017                                          &pkt, sizeof(pkt));
5018
5019                 break;
5020         }
5021 #endif /* IP_PKTINFO */
5022 #if defined(HAVE_IPV6)
5023         case AF_INET6: {
5024 #if defined(IPV6_PKTINFO) && defined(HAVE_STRUCT_IN6_PKTINFO)
5025                 struct sockaddr_in6 *sin6;
5026                 struct in6_pktinfo pkt6;
5027
5028                 if (si->bindname.sa_socklen == sizeof(struct sockaddr_in6)) {
5029                         sin6 = &si->bindname.sa.in6;
5030                 } else {
5031                         if (si->myname.sa_socklen != sizeof(struct sockaddr_in6)) {
5032                                 return 0;
5033                         }
5034                         sin6 = &si->myname.sa.in6;
5035                 }
5036
5037                 ZERO_STRUCT(pkt6);
5038
5039                 pkt6.ipi6_ifindex = socket_wrapper_default_iface();
5040                 pkt6.ipi6_addr = sin6->sin6_addr;
5041
5042                 swrap_msghdr_add_cmsghdr(msg, IPPROTO_IPV6, IPV6_PKTINFO,
5043                                         &pkt6, sizeof(pkt6));
5044 #endif /* HAVE_STRUCT_IN6_PKTINFO */
5045
5046                 break;
5047         }
5048 #endif /* IPV6_PKTINFO */
5049         default:
5050                 return -1;
5051         }
5052
5053         return 0;
5054 }
5055
5056 static int swrap_msghdr_add_socket_info(struct socket_info *si,
5057                                         struct msghdr *omsg)
5058 {
5059         int rc = 0;
5060
5061         if (si->pktinfo > 0) {
5062                 rc = swrap_msghdr_add_pktinfo(si, omsg);
5063         }
5064
5065         return rc;
5066 }
5067
5068 static int swrap_sendmsg_copy_cmsg(const struct cmsghdr *cmsg,
5069                                    uint8_t **cm_data,
5070                                    size_t *cm_data_space);
5071 static int swrap_sendmsg_filter_cmsg_ipproto_ip(const struct cmsghdr *cmsg,
5072                                                 uint8_t **cm_data,
5073                                                 size_t *cm_data_space);
5074 static int swrap_sendmsg_filter_cmsg_sol_socket(const struct cmsghdr *cmsg,
5075                                                 uint8_t **cm_data,
5076                                                 size_t *cm_data_space);
5077
5078 static int swrap_sendmsg_filter_cmsghdr(const struct msghdr *_msg,
5079                                         uint8_t **cm_data,
5080                                         size_t *cm_data_space)
5081 {
5082         struct msghdr *msg = discard_const_p(struct msghdr, _msg);
5083         struct cmsghdr *cmsg;
5084         int rc = -1;
5085
5086         /* Nothing to do */
5087         if (msg->msg_controllen == 0 || msg->msg_control == NULL) {
5088                 return 0;
5089         }
5090
5091         for (cmsg = CMSG_FIRSTHDR(msg);
5092              cmsg != NULL;
5093              cmsg = CMSG_NXTHDR(msg, cmsg)) {
5094                 switch (cmsg->cmsg_level) {
5095                 case IPPROTO_IP:
5096                         rc = swrap_sendmsg_filter_cmsg_ipproto_ip(cmsg,
5097                                                                   cm_data,
5098                                                                   cm_data_space);
5099                         break;
5100                 case SOL_SOCKET:
5101                         rc = swrap_sendmsg_filter_cmsg_sol_socket(cmsg,
5102                                                                   cm_data,
5103                                                                   cm_data_space);
5104                         break;
5105                 default:
5106                         rc = swrap_sendmsg_copy_cmsg(cmsg,
5107                                                      cm_data,
5108                                                      cm_data_space);
5109                         break;
5110                 }
5111                 if (rc < 0) {
5112                         int saved_errno = errno;
5113                         SAFE_FREE(*cm_data);
5114                         *cm_data_space = 0;
5115                         errno = saved_errno;
5116                         return rc;
5117                 }
5118         }
5119
5120         return rc;
5121 }
5122
5123 static int swrap_sendmsg_copy_cmsg(const struct cmsghdr *cmsg,
5124                                    uint8_t **cm_data,
5125                                    size_t *cm_data_space)
5126 {
5127         size_t cmspace;
5128         uint8_t *p;
5129
5130         cmspace = *cm_data_space + CMSG_ALIGN(cmsg->cmsg_len);
5131
5132         p = realloc((*cm_data), cmspace);
5133         if (p == NULL) {
5134                 return -1;
5135         }
5136         (*cm_data) = p;
5137
5138         p = (*cm_data) + (*cm_data_space);
5139         *cm_data_space = cmspace;
5140
5141         memcpy(p, cmsg, cmsg->cmsg_len);
5142
5143         return 0;
5144 }
5145
5146 static int swrap_sendmsg_filter_cmsg_pktinfo(const struct cmsghdr *cmsg,
5147                                             uint8_t **cm_data,
5148                                             size_t *cm_data_space);
5149
5150
5151 static int swrap_sendmsg_filter_cmsg_ipproto_ip(const struct cmsghdr *cmsg,
5152                                                 uint8_t **cm_data,
5153                                                 size_t *cm_data_space)
5154 {
5155         int rc = -1;
5156
5157         switch(cmsg->cmsg_type) {
5158 #ifdef IP_PKTINFO
5159         case IP_PKTINFO:
5160                 rc = swrap_sendmsg_filter_cmsg_pktinfo(cmsg,
5161                                                        cm_data,
5162                                                        cm_data_space);
5163                 break;
5164 #endif
5165 #ifdef IPV6_PKTINFO
5166         case IPV6_PKTINFO:
5167                 rc = swrap_sendmsg_filter_cmsg_pktinfo(cmsg,
5168                                                        cm_data,
5169                                                        cm_data_space);
5170                 break;
5171 #endif
5172         default:
5173                 break;
5174         }
5175
5176         return rc;
5177 }
5178
5179 static int swrap_sendmsg_filter_cmsg_pktinfo(const struct cmsghdr *cmsg,
5180                                              uint8_t **cm_data,
5181                                              size_t *cm_data_space)
5182 {
5183         (void)cmsg; /* unused */
5184         (void)cm_data; /* unused */
5185         (void)cm_data_space; /* unused */
5186
5187         /*
5188          * Passing a IP pktinfo to a unix socket might be rejected by the
5189          * Kernel, at least on FreeBSD. So skip this cmsg.
5190          */
5191         return 0;
5192 }
5193
5194 static int swrap_sendmsg_filter_cmsg_sol_socket(const struct cmsghdr *cmsg,
5195                                                 uint8_t **cm_data,
5196                                                 size_t *cm_data_space)
5197 {
5198         int rc = -1;
5199
5200         switch (cmsg->cmsg_type) {
5201         case SCM_RIGHTS:
5202                 SWRAP_LOG(SWRAP_LOG_TRACE,
5203                           "Ignoring SCM_RIGHTS on inet socket!");
5204                 rc = 0;
5205                 break;
5206 #ifdef SCM_CREDENTIALS
5207         case SCM_CREDENTIALS:
5208                 SWRAP_LOG(SWRAP_LOG_TRACE,
5209                           "Ignoring SCM_CREDENTIALS on inet socket!");
5210                 rc = 0;
5211                 break;
5212 #endif /* SCM_CREDENTIALS */
5213         default:
5214                 rc = swrap_sendmsg_copy_cmsg(cmsg,
5215                                              cm_data,
5216                                              cm_data_space);
5217                 break;
5218         }
5219
5220         return rc;
5221 }
5222
5223 static const uint64_t swrap_unix_scm_right_magic = 0x8e0e13f27c42fc36;
5224
5225 /*
5226  * We only allow up to 6 fds at a time
5227  * as that's more than enough for Samba
5228  * and it means we can keep the logic simple
5229  * and work with fixed size arrays.
5230  *
5231  * We also keep sizeof(struct swrap_unix_scm_rights)
5232  * under PIPE_BUF (4096) in order to allow a non-blocking
5233  * write into the pipe.
5234  */
5235 #ifndef PIPE_BUF
5236 #define PIPE_BUF 4096
5237 #endif
5238 #define SWRAP_MAX_PASSED_FDS ((size_t)6)
5239 #define SWRAP_MAX_PASSED_SOCKET_INFO SWRAP_MAX_PASSED_FDS
5240 struct swrap_unix_scm_rights_payload {
5241         uint8_t num_idxs;
5242         int8_t idxs[SWRAP_MAX_PASSED_FDS];
5243         struct socket_info infos[SWRAP_MAX_PASSED_SOCKET_INFO];
5244 };
5245 struct swrap_unix_scm_rights {
5246         uint64_t magic;
5247         char package_name[sizeof(SOCKET_WRAPPER_PACKAGE)];
5248         char package_version[sizeof(SOCKET_WRAPPER_VERSION)];
5249         uint32_t full_size;
5250         uint32_t payload_size;
5251         struct swrap_unix_scm_rights_payload payload;
5252 };
5253
5254 static void swrap_dec_fd_passed_array(size_t num, struct socket_info **array)
5255 {
5256         int saved_errno = errno;
5257         size_t i;
5258
5259         for (i = 0; i < num; i++) {
5260                 struct socket_info *si = array[i];
5261                 if (si == NULL) {
5262                         continue;
5263                 }
5264
5265                 SWRAP_LOCK_SI(si);
5266                 swrap_dec_refcount(si);
5267                 if (si->fd_passed > 0) {
5268                         si->fd_passed -= 1;
5269                 }
5270                 SWRAP_UNLOCK_SI(si);
5271                 array[i] = NULL;
5272         }
5273
5274         errno = saved_errno;
5275 }
5276
5277 static void swrap_undo_si_idx_array(size_t num, int *array)
5278 {
5279         int saved_errno = errno;
5280         size_t i;
5281
5282         swrap_mutex_lock(&first_free_mutex);
5283
5284         for (i = 0; i < num; i++) {
5285                 struct socket_info *si = NULL;
5286
5287                 if (array[i] == -1) {
5288                         continue;
5289                 }
5290
5291                 si = swrap_get_socket_info(array[i]);
5292                 if (si == NULL) {
5293                         continue;
5294                 }
5295
5296                 SWRAP_LOCK_SI(si);
5297                 swrap_dec_refcount(si);
5298                 SWRAP_UNLOCK_SI(si);
5299
5300                 swrap_set_next_free(si, first_free);
5301                 first_free = array[i];
5302                 array[i] = -1;
5303         }
5304
5305         swrap_mutex_unlock(&first_free_mutex);
5306         errno = saved_errno;
5307 }
5308
5309 static void swrap_close_fd_array(size_t num, const int *array)
5310 {
5311         int saved_errno = errno;
5312         size_t i;
5313
5314         for (i = 0; i < num; i++) {
5315                 if (array[i] == -1) {
5316                         continue;
5317                 }
5318                 libc_close(array[i]);
5319         }
5320
5321         errno = saved_errno;
5322 }
5323
5324 union __swrap_fds {
5325         const uint8_t *p;
5326         int *fds;
5327 };
5328
5329 union __swrap_cmsghdr {
5330         const uint8_t *p;
5331         struct cmsghdr *cmsg;
5332 };
5333
5334 static int swrap_sendmsg_unix_scm_rights(const struct cmsghdr *cmsg,
5335                                          uint8_t **cm_data,
5336                                          size_t *cm_data_space,
5337                                          int *scm_rights_pipe_fd)
5338 {
5339         struct swrap_unix_scm_rights info;
5340         struct swrap_unix_scm_rights_payload *payload = NULL;
5341         int si_idx_array[SWRAP_MAX_PASSED_FDS];
5342         struct socket_info *si_array[SWRAP_MAX_PASSED_FDS] = { NULL, };
5343         size_t info_idx = 0;
5344         size_t size_fds_in;
5345         size_t num_fds_in;
5346         union __swrap_fds __fds_in = { .p = NULL, };
5347         const int *fds_in = NULL;
5348         size_t num_fds_out;
5349         size_t size_fds_out;
5350         union __swrap_fds __fds_out = { .p = NULL, };
5351         int *fds_out = NULL;
5352         size_t cmsg_len;
5353         size_t cmsg_space;
5354         size_t new_cm_data_space;
5355         union __swrap_cmsghdr __new_cmsg = { .p = NULL, };
5356         struct cmsghdr *new_cmsg = NULL;
5357         uint8_t *p = NULL;
5358         size_t i;
5359         int pipefd[2] = { -1, -1 };
5360         int rc;
5361         ssize_t sret;
5362
5363         /*
5364          * We pass this a buffer to the kernel make sure any padding
5365          * is also cleared.
5366          */
5367         ZERO_STRUCT(info);
5368         info.magic = swrap_unix_scm_right_magic;
5369         memcpy(info.package_name,
5370                SOCKET_WRAPPER_PACKAGE,
5371                sizeof(info.package_name));
5372         memcpy(info.package_version,
5373                SOCKET_WRAPPER_VERSION,
5374                sizeof(info.package_version));
5375         info.full_size = sizeof(info);
5376         info.payload_size = sizeof(info.payload);
5377         payload = &info.payload;
5378
5379         if (*scm_rights_pipe_fd != -1) {
5380                 SWRAP_LOG(SWRAP_LOG_ERROR,
5381                           "Two SCM_RIGHTS headers are not supported by socket_wrapper");
5382                 errno = EINVAL;
5383                 return -1;
5384         }
5385
5386         if (cmsg->cmsg_len < CMSG_LEN(0)) {
5387                 SWRAP_LOG(SWRAP_LOG_ERROR,
5388                           "cmsg->cmsg_len=%zu < CMSG_LEN(0)=%zu",
5389                           (size_t)cmsg->cmsg_len,
5390                           CMSG_LEN(0));
5391                 errno = EINVAL;
5392                 return -1;
5393         }
5394         size_fds_in = cmsg->cmsg_len - CMSG_LEN(0);
5395         if ((size_fds_in % sizeof(int)) != 0) {
5396                 SWRAP_LOG(SWRAP_LOG_ERROR,
5397                           "cmsg->cmsg_len=%zu => (size_fds_in=%zu %% sizeof(int)=%zu) != 0",
5398                           (size_t)cmsg->cmsg_len,
5399                           size_fds_in,
5400                           sizeof(int));
5401                 errno = EINVAL;
5402                 return -1;
5403         }
5404         num_fds_in = size_fds_in / sizeof(int);
5405         if (num_fds_in > SWRAP_MAX_PASSED_FDS) {
5406                 SWRAP_LOG(SWRAP_LOG_ERROR,
5407                           "cmsg->cmsg_len=%zu,size_fds_in=%zu => "
5408                           "num_fds_in=%zu > "
5409                           "SWRAP_MAX_PASSED_FDS(%zu)",
5410                           (size_t)cmsg->cmsg_len,
5411                           size_fds_in,
5412                           num_fds_in,
5413                           SWRAP_MAX_PASSED_FDS);
5414                 errno = EINVAL;
5415                 return -1;
5416         }
5417         if (num_fds_in == 0) {
5418                 SWRAP_LOG(SWRAP_LOG_ERROR,
5419                           "cmsg->cmsg_len=%zu,size_fds_in=%zu => "
5420                           "num_fds_in=%zu",
5421                           (size_t)cmsg->cmsg_len,
5422                           size_fds_in,
5423                           num_fds_in);
5424                 errno = EINVAL;
5425                 return -1;
5426         }
5427         __fds_in.p = CMSG_DATA(cmsg);
5428         fds_in = __fds_in.fds;
5429         num_fds_out = num_fds_in + 1;
5430
5431         SWRAP_LOG(SWRAP_LOG_TRACE,
5432                   "num_fds_in=%zu num_fds_out=%zu",
5433                   num_fds_in, num_fds_out);
5434
5435         size_fds_out = sizeof(int) * num_fds_out;
5436         cmsg_len = CMSG_LEN(size_fds_out);
5437         cmsg_space = CMSG_SPACE(size_fds_out);
5438
5439         new_cm_data_space = *cm_data_space + cmsg_space;
5440
5441         p = realloc((*cm_data), new_cm_data_space);
5442         if (p == NULL) {
5443                 return -1;
5444         }
5445         (*cm_data) = p;
5446         p = (*cm_data) + (*cm_data_space);
5447         memset(p, 0, cmsg_space);
5448         __new_cmsg.p = p;
5449         new_cmsg = __new_cmsg.cmsg;
5450         *new_cmsg = *cmsg;
5451         __fds_out.p = CMSG_DATA(new_cmsg);
5452         fds_out = __fds_out.fds;
5453         memcpy(fds_out, fds_in, size_fds_in);
5454         new_cmsg->cmsg_len = cmsg->cmsg_len;
5455
5456         for (i = 0; i < num_fds_in; i++) {
5457                 size_t j;
5458
5459                 payload->idxs[i] = -1;
5460                 payload->num_idxs++;
5461
5462                 si_idx_array[i] = find_socket_info_index(fds_in[i]);
5463                 if (si_idx_array[i] == -1) {
5464                         continue;
5465                 }
5466
5467                 si_array[i] = swrap_get_socket_info(si_idx_array[i]);
5468                 if (si_array[i] == NULL) {
5469                         SWRAP_LOG(SWRAP_LOG_ERROR,
5470                                   "fds_in[%zu]=%d si_idx_array[%zu]=%d missing!",
5471                                   i, fds_in[i], i, si_idx_array[i]);
5472                         errno = EINVAL;
5473                         return -1;
5474                 }
5475
5476                 for (j = 0; j < i; j++) {
5477                         if (si_array[j] == si_array[i]) {
5478                                 payload->idxs[i] = payload->idxs[j];
5479                                 break;
5480                         }
5481                 }
5482                 if (payload->idxs[i] == -1) {
5483                         if (info_idx >= SWRAP_MAX_PASSED_SOCKET_INFO) {
5484                                 SWRAP_LOG(SWRAP_LOG_ERROR,
5485                                           "fds_in[%zu]=%d,si_idx_array[%zu]=%d: "
5486                                           "info_idx=%zu >= SWRAP_MAX_PASSED_FDS(%zu)!",
5487                                           i, fds_in[i], i, si_idx_array[i],
5488                                           info_idx,
5489                                           SWRAP_MAX_PASSED_SOCKET_INFO);
5490                                 errno = EINVAL;
5491                                 return -1;
5492                         }
5493                         payload->idxs[i] = info_idx;
5494                         info_idx += 1;
5495                         continue;
5496                 }
5497         }
5498
5499         for (i = 0; i < num_fds_in; i++) {
5500                 struct socket_info *si = si_array[i];
5501
5502                 if (si == NULL) {
5503                         SWRAP_LOG(SWRAP_LOG_TRACE,
5504                                   "fds_in[%zu]=%d not an inet socket",
5505                                   i, fds_in[i]);
5506                         continue;
5507                 }
5508
5509                 SWRAP_LOG(SWRAP_LOG_TRACE,
5510                           "fds_in[%zu]=%d si_idx_array[%zu]=%d "
5511                           "passing as info.idxs[%zu]=%d!",
5512                           i, fds_in[i],
5513                           i, si_idx_array[i],
5514                           i, payload->idxs[i]);
5515
5516                 SWRAP_LOCK_SI(si);
5517                 si->fd_passed += 1;
5518                 payload->infos[payload->idxs[i]] = *si;
5519                 payload->infos[payload->idxs[i]].fd_passed = 0;
5520                 SWRAP_UNLOCK_SI(si);
5521         }
5522
5523         rc = pipe(pipefd);
5524         if (rc == -1) {
5525                 int saved_errno = errno;
5526                 SWRAP_LOG(SWRAP_LOG_ERROR,
5527                           "pipe() failed - %d %s",
5528                           saved_errno,
5529                           strerror(saved_errno));
5530                 swrap_dec_fd_passed_array(num_fds_in, si_array);
5531                 errno = saved_errno;
5532                 return -1;
5533         }
5534
5535         sret = write(pipefd[1], &info, sizeof(info));
5536         if (sret != sizeof(info)) {
5537                 int saved_errno = errno;
5538                 if (sret != -1) {
5539                         saved_errno = EINVAL;
5540                 }
5541                 SWRAP_LOG(SWRAP_LOG_ERROR,
5542                           "write() failed - sret=%zd - %d %s",
5543                           sret, saved_errno,
5544                           strerror(saved_errno));
5545                 swrap_dec_fd_passed_array(num_fds_in, si_array);
5546                 libc_close(pipefd[1]);
5547                 libc_close(pipefd[0]);
5548                 errno = saved_errno;
5549                 return -1;
5550         }
5551         libc_close(pipefd[1]);
5552
5553         /*
5554          * Add the pipe read end to the end of the passed fd array
5555          */
5556         fds_out[num_fds_in] = pipefd[0];
5557         new_cmsg->cmsg_len = cmsg_len;
5558
5559         /* we're done ... */
5560         *scm_rights_pipe_fd = pipefd[0];
5561         *cm_data_space = new_cm_data_space;
5562
5563         return 0;
5564 }
5565
5566 static int swrap_sendmsg_unix_sol_socket(const struct cmsghdr *cmsg,
5567                                          uint8_t **cm_data,
5568                                          size_t *cm_data_space,
5569                                          int *scm_rights_pipe_fd)
5570 {
5571         int rc = -1;
5572
5573         switch (cmsg->cmsg_type) {
5574         case SCM_RIGHTS:
5575                 rc = swrap_sendmsg_unix_scm_rights(cmsg,
5576                                                    cm_data,
5577                                                    cm_data_space,
5578                                                    scm_rights_pipe_fd);
5579                 break;
5580         default:
5581                 rc = swrap_sendmsg_copy_cmsg(cmsg,
5582                                              cm_data,
5583                                              cm_data_space);
5584                 break;
5585         }
5586
5587         return rc;
5588 }
5589
5590 static int swrap_recvmsg_unix_scm_rights(const struct cmsghdr *cmsg,
5591                                          uint8_t **cm_data,
5592                                          size_t *cm_data_space)
5593 {
5594         int scm_rights_pipe_fd = -1;
5595         struct swrap_unix_scm_rights info;
5596         struct swrap_unix_scm_rights_payload *payload = NULL;
5597         int si_idx_array[SWRAP_MAX_PASSED_FDS];
5598         size_t size_fds_in;
5599         size_t num_fds_in;
5600         union __swrap_fds __fds_in = { .p = NULL, };
5601         const int *fds_in = NULL;
5602         size_t num_fds_out;
5603         size_t size_fds_out;
5604         union __swrap_fds __fds_out = { .p = NULL, };
5605         int *fds_out = NULL;
5606         size_t cmsg_len;
5607         size_t cmsg_space;
5608         size_t new_cm_data_space;
5609         union __swrap_cmsghdr __new_cmsg = { .p = NULL, };
5610         struct cmsghdr *new_cmsg = NULL;
5611         uint8_t *p = NULL;
5612         ssize_t sret;
5613         size_t i;
5614         int cmp;
5615
5616         if (cmsg->cmsg_len < CMSG_LEN(0)) {
5617                 SWRAP_LOG(SWRAP_LOG_ERROR,
5618                           "cmsg->cmsg_len=%zu < CMSG_LEN(0)=%zu",
5619                           (size_t)cmsg->cmsg_len,
5620                           CMSG_LEN(0));
5621                 errno = EINVAL;
5622                 return -1;
5623         }
5624         size_fds_in = cmsg->cmsg_len - CMSG_LEN(0);
5625         if ((size_fds_in % sizeof(int)) != 0) {
5626                 SWRAP_LOG(SWRAP_LOG_ERROR,
5627                           "cmsg->cmsg_len=%zu => (size_fds_in=%zu %% sizeof(int)=%zu) != 0",
5628                           (size_t)cmsg->cmsg_len,
5629                           size_fds_in,
5630                           sizeof(int));
5631                 errno = EINVAL;
5632                 return -1;
5633         }
5634         num_fds_in = size_fds_in / sizeof(int);
5635         if (num_fds_in > (SWRAP_MAX_PASSED_FDS + 1)) {
5636                 SWRAP_LOG(SWRAP_LOG_ERROR,
5637                           "cmsg->cmsg_len=%zu,size_fds_in=%zu => "
5638                           "num_fds_in=%zu > SWRAP_MAX_PASSED_FDS+1(%zu)",
5639                           (size_t)cmsg->cmsg_len,
5640                           size_fds_in,
5641                           num_fds_in,
5642                           SWRAP_MAX_PASSED_FDS+1);
5643                 errno = EINVAL;
5644                 return -1;
5645         }
5646         if (num_fds_in <= 1) {
5647                 SWRAP_LOG(SWRAP_LOG_ERROR,
5648                           "cmsg->cmsg_len=%zu,size_fds_in=%zu => "
5649                           "num_fds_in=%zu",
5650                           (size_t)cmsg->cmsg_len,
5651                           size_fds_in,
5652                           num_fds_in);
5653                 errno = EINVAL;
5654                 return -1;
5655         }
5656         __fds_in.p = CMSG_DATA(cmsg);
5657         fds_in = __fds_in.fds;
5658         num_fds_out = num_fds_in - 1;
5659
5660         SWRAP_LOG(SWRAP_LOG_TRACE,
5661                   "num_fds_in=%zu num_fds_out=%zu",
5662                   num_fds_in, num_fds_out);
5663
5664         for (i = 0; i < num_fds_in; i++) {
5665                 /* Check if we have a stale fd and remove it */
5666                 swrap_remove_stale(fds_in[i]);
5667         }
5668
5669         scm_rights_pipe_fd = fds_in[num_fds_out];
5670         size_fds_out = sizeof(int) * num_fds_out;
5671         cmsg_len = CMSG_LEN(size_fds_out);
5672         cmsg_space = CMSG_SPACE(size_fds_out);
5673
5674         new_cm_data_space = *cm_data_space + cmsg_space;
5675
5676         p = realloc((*cm_data), new_cm_data_space);
5677         if (p == NULL) {
5678                 swrap_close_fd_array(num_fds_in, fds_in);
5679                 return -1;
5680         }
5681         (*cm_data) = p;
5682         p = (*cm_data) + (*cm_data_space);
5683         memset(p, 0, cmsg_space);
5684         __new_cmsg.p = p;
5685         new_cmsg = __new_cmsg.cmsg;
5686         *new_cmsg = *cmsg;
5687         __fds_out.p = CMSG_DATA(new_cmsg);
5688         fds_out = __fds_out.fds;
5689         memcpy(fds_out, fds_in, size_fds_out);
5690         new_cmsg->cmsg_len = cmsg_len;
5691
5692         sret = read(scm_rights_pipe_fd, &info, sizeof(info));
5693         if (sret != sizeof(info)) {
5694                 int saved_errno = errno;
5695                 if (sret != -1) {
5696                         saved_errno = EINVAL;
5697                 }
5698                 SWRAP_LOG(SWRAP_LOG_ERROR,
5699                           "read() failed - sret=%zd - %d %s",
5700                           sret, saved_errno,
5701                           strerror(saved_errno));
5702                 swrap_close_fd_array(num_fds_in, fds_in);
5703                 errno = saved_errno;
5704                 return -1;
5705         }
5706         libc_close(scm_rights_pipe_fd);
5707         payload = &info.payload;
5708
5709         if (info.magic != swrap_unix_scm_right_magic) {
5710                 SWRAP_LOG(SWRAP_LOG_ERROR,
5711                           "info.magic=0x%llx != swrap_unix_scm_right_magic=0x%llx",
5712                           (unsigned long long)info.magic,
5713                           (unsigned long long)swrap_unix_scm_right_magic);
5714                 swrap_close_fd_array(num_fds_out, fds_out);
5715                 errno = EINVAL;
5716                 return -1;
5717         }
5718
5719         cmp = memcmp(info.package_name,
5720                      SOCKET_WRAPPER_PACKAGE,
5721                      sizeof(info.package_name));
5722         if (cmp != 0) {
5723                 SWRAP_LOG(SWRAP_LOG_ERROR,
5724                           "info.package_name='%.*s' != '%s'",
5725                           (int)sizeof(info.package_name),
5726                           info.package_name,
5727                           SOCKET_WRAPPER_PACKAGE);
5728                 swrap_close_fd_array(num_fds_out, fds_out);
5729                 errno = EINVAL;
5730                 return -1;
5731         }
5732
5733         cmp = memcmp(info.package_version,
5734                      SOCKET_WRAPPER_VERSION,
5735                      sizeof(info.package_version));
5736         if (cmp != 0) {
5737                 SWRAP_LOG(SWRAP_LOG_ERROR,
5738                           "info.package_version='%.*s' != '%s'",
5739                           (int)sizeof(info.package_version),
5740                           info.package_version,
5741                           SOCKET_WRAPPER_VERSION);
5742                 swrap_close_fd_array(num_fds_out, fds_out);
5743                 errno = EINVAL;
5744                 return -1;
5745         }
5746
5747         if (info.full_size != sizeof(info)) {
5748                 SWRAP_LOG(SWRAP_LOG_ERROR,
5749                           "info.full_size=%zu != sizeof(info)=%zu",
5750                           (size_t)info.full_size,
5751                           sizeof(info));
5752                 swrap_close_fd_array(num_fds_out, fds_out);
5753                 errno = EINVAL;
5754                 return -1;
5755         }
5756
5757         if (info.payload_size != sizeof(info.payload)) {
5758                 SWRAP_LOG(SWRAP_LOG_ERROR,
5759                           "info.payload_size=%zu != sizeof(info.payload)=%zu",
5760                           (size_t)info.payload_size,
5761                           sizeof(info.payload));
5762                 swrap_close_fd_array(num_fds_out, fds_out);
5763                 errno = EINVAL;
5764                 return -1;
5765         }
5766
5767         if (payload->num_idxs != num_fds_out) {
5768                 SWRAP_LOG(SWRAP_LOG_ERROR,
5769                           "info.num_idxs=%u != num_fds_out=%zu",
5770                           payload->num_idxs, num_fds_out);
5771                 swrap_close_fd_array(num_fds_out, fds_out);
5772                 errno = EINVAL;
5773                 return -1;
5774         }
5775
5776         for (i = 0; i < num_fds_out; i++) {
5777                 size_t j;
5778
5779                 si_idx_array[i] = -1;
5780
5781                 if (payload->idxs[i] == -1) {
5782                         SWRAP_LOG(SWRAP_LOG_TRACE,
5783                                   "fds_out[%zu]=%d not an inet socket",
5784                                   i, fds_out[i]);
5785                         continue;
5786                 }
5787
5788                 if (payload->idxs[i] < 0) {
5789                         SWRAP_LOG(SWRAP_LOG_ERROR,
5790                                   "fds_out[%zu]=%d info.idxs[%zu]=%d < 0!",
5791                                   i, fds_out[i], i, payload->idxs[i]);
5792                         swrap_close_fd_array(num_fds_out, fds_out);
5793                         errno = EINVAL;
5794                         return -1;
5795                 }
5796
5797                 if (payload->idxs[i] >= payload->num_idxs) {
5798                         SWRAP_LOG(SWRAP_LOG_ERROR,
5799                                   "fds_out[%zu]=%d info.idxs[%zu]=%d >= %u!",
5800                                   i, fds_out[i], i, payload->idxs[i],
5801                                   payload->num_idxs);
5802                         swrap_close_fd_array(num_fds_out, fds_out);
5803                         errno = EINVAL;
5804                         return -1;
5805                 }
5806
5807                 if ((size_t)fds_out[i] >= socket_fds_max) {
5808                         SWRAP_LOG(SWRAP_LOG_ERROR,
5809                                   "The max socket index limit of %zu has been reached, "
5810                                   "trying to add %d",
5811                                   socket_fds_max,
5812                                   fds_out[i]);
5813                         swrap_close_fd_array(num_fds_out, fds_out);
5814                         errno = EMFILE;
5815                         return -1;
5816                 }
5817
5818                 SWRAP_LOG(SWRAP_LOG_TRACE,
5819                           "fds_in[%zu]=%d "
5820                           "received as info.idxs[%zu]=%d!",
5821                           i, fds_out[i],
5822                           i, payload->idxs[i]);
5823
5824                 for (j = 0; j < i; j++) {
5825                         if (payload->idxs[j] == -1) {
5826                                 continue;
5827                         }
5828                         if (payload->idxs[j] == payload->idxs[i]) {
5829                                 si_idx_array[i] = si_idx_array[j];
5830                         }
5831                 }
5832                 if (si_idx_array[i] == -1) {
5833                         const struct socket_info *si = &payload->infos[payload->idxs[i]];
5834
5835                         si_idx_array[i] = swrap_add_socket_info(si);
5836                         if (si_idx_array[i] == -1) {
5837                                 int saved_errno = errno;
5838                                 SWRAP_LOG(SWRAP_LOG_ERROR,
5839                                           "The max socket index limit of %zu has been reached, "
5840                                           "trying to add %d",
5841                                           socket_fds_max,
5842                                           fds_out[i]);
5843                                 swrap_undo_si_idx_array(i, si_idx_array);
5844                                 swrap_close_fd_array(num_fds_out, fds_out);
5845                                 errno = saved_errno;
5846                                 return -1;
5847                         }
5848                         SWRAP_LOG(SWRAP_LOG_TRACE,
5849                                   "Imported %s socket for protocol %s, fd=%d",
5850                                   si->family == AF_INET ? "IPv4" : "IPv6",
5851                                   si->type == SOCK_DGRAM ? "UDP" : "TCP",
5852                                   fds_out[i]);
5853                 }
5854         }
5855
5856         for (i = 0; i < num_fds_out; i++) {
5857                 if (si_idx_array[i] == -1) {
5858                         continue;
5859                 }
5860                 set_socket_info_index(fds_out[i], si_idx_array[i]);
5861         }
5862
5863         /* we're done ... */
5864         *cm_data_space = new_cm_data_space;
5865
5866         return 0;
5867 }
5868
5869 static int swrap_recvmsg_unix_sol_socket(const struct cmsghdr *cmsg,
5870                                          uint8_t **cm_data,
5871                                          size_t *cm_data_space)
5872 {
5873         int rc = -1;
5874
5875         switch (cmsg->cmsg_type) {
5876         case SCM_RIGHTS:
5877                 rc = swrap_recvmsg_unix_scm_rights(cmsg,
5878                                                    cm_data,
5879                                                    cm_data_space);
5880                 break;
5881         default:
5882                 rc = swrap_sendmsg_copy_cmsg(cmsg,
5883                                              cm_data,
5884                                              cm_data_space);
5885                 break;
5886         }
5887
5888         return rc;
5889 }
5890
5891 #endif /* HAVE_STRUCT_MSGHDR_MSG_CONTROL */
5892
5893 static int swrap_sendmsg_before_unix(const struct msghdr *_msg_in,
5894                                      struct msghdr *msg_tmp,
5895                                      int *scm_rights_pipe_fd)
5896 {
5897 #ifdef HAVE_STRUCT_MSGHDR_MSG_CONTROL
5898         struct msghdr *msg_in = discard_const_p(struct msghdr, _msg_in);
5899         struct cmsghdr *cmsg = NULL;
5900         uint8_t *cm_data = NULL;
5901         size_t cm_data_space = 0;
5902         int rc = -1;
5903
5904         *msg_tmp = *msg_in;
5905         *scm_rights_pipe_fd = -1;
5906
5907         /* Nothing to do */
5908         if (msg_in->msg_controllen == 0 || msg_in->msg_control == NULL) {
5909                 return 0;
5910         }
5911
5912         for (cmsg = CMSG_FIRSTHDR(msg_in);
5913              cmsg != NULL;
5914              cmsg = CMSG_NXTHDR(msg_in, cmsg)) {
5915                 switch (cmsg->cmsg_level) {
5916                 case SOL_SOCKET:
5917                         rc = swrap_sendmsg_unix_sol_socket(cmsg,
5918                                                            &cm_data,
5919                                                            &cm_data_space,
5920                                                            scm_rights_pipe_fd);
5921                         break;
5922
5923                 default:
5924                         rc = swrap_sendmsg_copy_cmsg(cmsg,
5925                                                      &cm_data,
5926                                                      &cm_data_space);
5927                         break;
5928                 }
5929                 if (rc < 0) {
5930                         int saved_errno = errno;
5931                         SAFE_FREE(cm_data);
5932                         errno = saved_errno;
5933                         return rc;
5934                 }
5935         }
5936
5937         msg_tmp->msg_controllen = cm_data_space;
5938         msg_tmp->msg_control = cm_data;
5939
5940         return 0;
5941 #else /* HAVE_STRUCT_MSGHDR_MSG_CONTROL */
5942         *msg_tmp = *_msg_in;
5943         return 0;
5944 #endif /* ! HAVE_STRUCT_MSGHDR_MSG_CONTROL */
5945 }
5946
5947 static ssize_t swrap_sendmsg_after_unix(struct msghdr *msg_tmp,
5948                                         ssize_t ret,
5949                                         int scm_rights_pipe_fd)
5950 {
5951 #ifdef HAVE_STRUCT_MSGHDR_MSG_CONTROL
5952         int saved_errno = errno;
5953         SAFE_FREE(msg_tmp->msg_control);
5954         if (scm_rights_pipe_fd != -1) {
5955                 libc_close(scm_rights_pipe_fd);
5956         }
5957         errno = saved_errno;
5958 #endif /* HAVE_STRUCT_MSGHDR_MSG_CONTROL */
5959         return ret;
5960 }
5961
5962 static int swrap_recvmsg_before_unix(struct msghdr *msg_in,
5963                                      struct msghdr *msg_tmp)
5964 {
5965 #ifdef HAVE_STRUCT_MSGHDR_MSG_CONTROL
5966         const size_t cm_extra_space = CMSG_SPACE(sizeof(int));
5967         uint8_t *cm_data = NULL;
5968         size_t cm_data_space = 0;
5969
5970         *msg_tmp = *msg_in;
5971
5972         SWRAP_LOG(SWRAP_LOG_TRACE,
5973                   "msg_in->msg_controllen=%zu",
5974                   (size_t)msg_in->msg_controllen);
5975
5976         /* Nothing to do */
5977         if (msg_in->msg_controllen == 0 || msg_in->msg_control == NULL) {
5978                 return 0;
5979         }
5980
5981         /*
5982          * We need to give the kernel a bit more space in order
5983          * recv the pipe fd, added by swrap_sendmsg_before_unix()).
5984          * swrap_recvmsg_after_unix() will hide it again.
5985          */
5986         cm_data_space = msg_in->msg_controllen;
5987         if (cm_data_space < (INT32_MAX - cm_extra_space)) {
5988                 cm_data_space += cm_extra_space;
5989         }
5990         cm_data = calloc(1, cm_data_space);
5991         if (cm_data == NULL) {
5992                 return -1;
5993         }
5994         memcpy(cm_data, msg_in->msg_control, msg_in->msg_controllen);
5995
5996         msg_tmp->msg_controllen = cm_data_space;
5997         msg_tmp->msg_control = cm_data;
5998
5999         SWRAP_LOG(SWRAP_LOG_TRACE,
6000                   "msg_tmp->msg_controllen=%zu",
6001                   (size_t)msg_tmp->msg_controllen);
6002         return 0;
6003 #else /* HAVE_STRUCT_MSGHDR_MSG_CONTROL */
6004         *msg_tmp = *msg_in;
6005         return 0;
6006 #endif /* ! HAVE_STRUCT_MSGHDR_MSG_CONTROL */
6007 }
6008
6009 static ssize_t swrap_recvmsg_after_unix(struct msghdr *msg_tmp,
6010                                         struct msghdr *msg_out,
6011                                         ssize_t ret)
6012 {
6013 #ifdef HAVE_STRUCT_MSGHDR_MSG_CONTROL
6014         struct cmsghdr *cmsg = NULL;
6015         uint8_t *cm_data = NULL;
6016         size_t cm_data_space = 0;
6017         int rc = -1;
6018
6019         SWRAP_LOG(SWRAP_LOG_TRACE,
6020                   "msg_tmp->msg_controllen=%zu",
6021                   (size_t)msg_tmp->msg_controllen);
6022
6023         /* Nothing to do */
6024         if (msg_tmp->msg_controllen == 0 || msg_tmp->msg_control == NULL) {
6025                 *msg_out = *msg_tmp;
6026                 return ret;
6027         }
6028
6029         for (cmsg = CMSG_FIRSTHDR(msg_tmp);
6030              cmsg != NULL;
6031              cmsg = CMSG_NXTHDR(msg_tmp, cmsg)) {
6032                 switch (cmsg->cmsg_level) {
6033                 case SOL_SOCKET:
6034                         rc = swrap_recvmsg_unix_sol_socket(cmsg,
6035                                                            &cm_data,
6036                                                            &cm_data_space);
6037                         break;
6038
6039                 default:
6040                         rc = swrap_sendmsg_copy_cmsg(cmsg,
6041                                                      &cm_data,
6042                                                      &cm_data_space);
6043                         break;
6044                 }
6045                 if (rc < 0) {
6046                         int saved_errno = errno;
6047                         SAFE_FREE(cm_data);
6048                         errno = saved_errno;
6049                         return rc;
6050                 }
6051         }
6052
6053         /*
6054          * msg_tmp->msg_control was created by swrap_recvmsg_before_unix()
6055          * and msg_out->msg_control is still the buffer of the caller.
6056          */
6057         SAFE_FREE(msg_tmp->msg_control);
6058         msg_tmp->msg_control = msg_out->msg_control;
6059         msg_tmp->msg_controllen = msg_out->msg_controllen;
6060         *msg_out = *msg_tmp;
6061
6062         cm_data_space = MIN(cm_data_space, msg_out->msg_controllen);
6063         memcpy(msg_out->msg_control, cm_data, cm_data_space);
6064         msg_out->msg_controllen = cm_data_space;
6065         SAFE_FREE(cm_data);
6066
6067         SWRAP_LOG(SWRAP_LOG_TRACE,
6068                   "msg_out->msg_controllen=%zu",
6069                   (size_t)msg_out->msg_controllen);
6070         return ret;
6071 #else /* HAVE_STRUCT_MSGHDR_MSG_CONTROL */
6072         *msg_out = *msg_tmp;
6073         return ret;
6074 #endif /* ! HAVE_STRUCT_MSGHDR_MSG_CONTROL */
6075 }
6076
6077 static ssize_t swrap_sendmsg_before(int fd,
6078                                     struct socket_info *si,
6079                                     struct msghdr *msg,
6080                                     struct iovec *tmp_iov,
6081                                     struct sockaddr_un *tmp_un,
6082                                     const struct sockaddr_un **to_un,
6083                                     const struct sockaddr **to,
6084                                     int *bcast)
6085 {
6086         size_t i, len = 0;
6087         ssize_t ret = -1;
6088
6089         if (to_un) {
6090                 *to_un = NULL;
6091         }
6092         if (to) {
6093                 *to = NULL;
6094         }
6095         if (bcast) {
6096                 *bcast = 0;
6097         }
6098
6099         SWRAP_LOCK_SI(si);
6100
6101         switch (si->type) {
6102         case SOCK_STREAM: {
6103                 unsigned long mtu;
6104
6105                 if (!si->connected) {
6106                         errno = ENOTCONN;
6107                         goto out;
6108                 }
6109
6110                 if (msg->msg_iovlen == 0) {
6111                         break;
6112                 }
6113
6114                 mtu = socket_wrapper_mtu();
6115                 for (i = 0; i < (size_t)msg->msg_iovlen; i++) {
6116                         size_t nlen;
6117                         nlen = len + msg->msg_iov[i].iov_len;
6118                         if (nlen < len) {
6119                                 /* overflow */
6120                                 errno = EMSGSIZE;
6121                                 goto out;
6122                         }
6123                         if (nlen > mtu) {
6124                                 break;
6125                         }
6126                 }
6127                 msg->msg_iovlen = i;
6128                 if (msg->msg_iovlen == 0) {
6129                         *tmp_iov = msg->msg_iov[0];
6130                         tmp_iov->iov_len = MIN((size_t)tmp_iov->iov_len,
6131                                                (size_t)mtu);
6132                         msg->msg_iov = tmp_iov;
6133                         msg->msg_iovlen = 1;
6134                 }
6135                 break;
6136         }
6137         case SOCK_DGRAM:
6138                 if (si->connected) {
6139                         if (msg->msg_name != NULL) {
6140                                 /*
6141                                  * We are dealing with unix sockets and if we
6142                                  * are connected, we should only talk to the
6143                                  * connected unix path. Using the fd to send
6144                                  * to another server would be hard to achieve.
6145                                  */
6146                                 msg->msg_name = NULL;
6147                                 msg->msg_namelen = 0;
6148                         }
6149                 } else {
6150                         const struct sockaddr *msg_name;
6151                         msg_name = (const struct sockaddr *)msg->msg_name;
6152
6153                         if (msg_name == NULL) {
6154                                 errno = ENOTCONN;
6155                                 goto out;
6156                         }
6157
6158
6159                         ret = sockaddr_convert_to_un(si, msg_name, msg->msg_namelen,
6160                                                      tmp_un, 0, bcast);
6161                         if (ret == -1) {
6162                                 goto out;
6163                         }
6164
6165                         if (to_un) {
6166                                 *to_un = tmp_un;
6167                         }
6168                         if (to) {
6169                                 *to = msg_name;
6170                         }
6171                         msg->msg_name = tmp_un;
6172                         msg->msg_namelen = sizeof(*tmp_un);
6173                 }
6174
6175                 if (si->bound == 0) {
6176                         ret = swrap_auto_bind(fd, si, si->family);
6177                         if (ret == -1) {
6178                                 SWRAP_UNLOCK_SI(si);
6179                                 if (errno == ENOTSOCK) {
6180                                         swrap_remove_stale(fd);
6181                                         ret = -ENOTSOCK;
6182                                 } else {
6183                                         SWRAP_LOG(SWRAP_LOG_ERROR, "swrap_sendmsg_before failed");
6184                                 }
6185                                 return ret;
6186                         }
6187                 }
6188
6189                 if (!si->defer_connect) {
6190                         break;
6191                 }
6192
6193                 ret = sockaddr_convert_to_un(si,
6194                                              &si->peername.sa.s,
6195                                              si->peername.sa_socklen,
6196                                              tmp_un,
6197                                              0,
6198                                              NULL);
6199                 if (ret == -1) {
6200                         goto out;
6201                 }
6202
6203                 ret = libc_connect(fd,
6204                                    (struct sockaddr *)(void *)tmp_un,
6205                                    sizeof(*tmp_un));
6206
6207                 /* to give better errors */
6208                 if (ret == -1 && errno == ENOENT) {
6209                         errno = EHOSTUNREACH;
6210                 }
6211
6212                 if (ret == -1) {
6213                         goto out;
6214                 }
6215
6216                 si->defer_connect = 0;
6217                 break;
6218         default:
6219                 errno = EHOSTUNREACH;
6220                 goto out;
6221         }
6222
6223         ret = 0;
6224 out:
6225         SWRAP_UNLOCK_SI(si);
6226
6227         return ret;
6228 }
6229
6230 static void swrap_sendmsg_after(int fd,
6231                                 struct socket_info *si,
6232                                 struct msghdr *msg,
6233                                 const struct sockaddr *to,
6234                                 ssize_t ret)
6235 {
6236         int saved_errno = errno;
6237         size_t i, len = 0;
6238         uint8_t *buf;
6239         off_t ofs = 0;
6240         size_t avail = 0;
6241         size_t remain;
6242
6243         /* to give better errors */
6244         if (ret == -1) {
6245                 if (saved_errno == ENOENT) {
6246                         saved_errno = EHOSTUNREACH;
6247                 } else if (saved_errno == ENOTSOCK) {
6248                         /* If the fd is not a socket, remove it */
6249                         swrap_remove_stale(fd);
6250                 }
6251         }
6252
6253         for (i = 0; i < (size_t)msg->msg_iovlen; i++) {
6254                 avail += msg->msg_iov[i].iov_len;
6255         }
6256
6257         if (ret == -1) {
6258                 remain = MIN(80, avail);
6259         } else {
6260                 remain = ret;
6261         }
6262
6263         /* we capture it as one single packet */
6264         buf = (uint8_t *)malloc(remain);
6265         if (!buf) {
6266                 /* we just not capture the packet */
6267                 errno = saved_errno;
6268                 return;
6269         }
6270
6271         for (i = 0; i < (size_t)msg->msg_iovlen; i++) {
6272                 size_t this_time = MIN(remain, (size_t)msg->msg_iov[i].iov_len);
6273                 memcpy(buf + ofs,
6274                        msg->msg_iov[i].iov_base,
6275                        this_time);
6276                 ofs += this_time;
6277                 remain -= this_time;
6278         }
6279         len = ofs;
6280
6281         SWRAP_LOCK_SI(si);
6282
6283         switch (si->type) {
6284         case SOCK_STREAM:
6285                 if (ret == -1) {
6286                         swrap_pcap_dump_packet(si, NULL, SWRAP_SEND, buf, len);
6287                         swrap_pcap_dump_packet(si, NULL, SWRAP_SEND_RST, NULL, 0);
6288                 } else {
6289                         swrap_pcap_dump_packet(si, NULL, SWRAP_SEND, buf, len);
6290                 }
6291                 break;
6292
6293         case SOCK_DGRAM:
6294                 if (si->connected) {
6295                         to = &si->peername.sa.s;
6296                 }
6297                 if (ret == -1) {
6298                         swrap_pcap_dump_packet(si, to, SWRAP_SENDTO, buf, len);
6299                         swrap_pcap_dump_packet(si, to, SWRAP_SENDTO_UNREACH, buf, len);
6300                 } else {
6301                         swrap_pcap_dump_packet(si, to, SWRAP_SENDTO, buf, len);
6302                 }
6303                 break;
6304         }
6305
6306         SWRAP_UNLOCK_SI(si);
6307
6308         free(buf);
6309         errno = saved_errno;
6310 }
6311
6312 static int swrap_recvmsg_before(int fd,
6313                                 struct socket_info *si,
6314                                 struct msghdr *msg,
6315                                 struct iovec *tmp_iov)
6316 {
6317         size_t i, len = 0;
6318         int ret = -1;
6319
6320         SWRAP_LOCK_SI(si);
6321
6322         (void)fd; /* unused */
6323
6324         switch (si->type) {
6325         case SOCK_STREAM: {
6326                 unsigned int mtu;
6327                 if (!si->connected) {
6328                         errno = ENOTCONN;
6329                         goto out;
6330                 }
6331
6332                 if (msg->msg_iovlen == 0) {
6333                         break;
6334                 }
6335
6336                 mtu = socket_wrapper_mtu();
6337                 for (i = 0; i < (size_t)msg->msg_iovlen; i++) {
6338                         size_t nlen;
6339                         nlen = len + msg->msg_iov[i].iov_len;
6340                         if (nlen > mtu) {
6341                                 break;
6342                         }
6343                 }
6344                 msg->msg_iovlen = i;
6345                 if (msg->msg_iovlen == 0) {
6346                         *tmp_iov = msg->msg_iov[0];
6347                         tmp_iov->iov_len = MIN((size_t)tmp_iov->iov_len,
6348                                                (size_t)mtu);
6349                         msg->msg_iov = tmp_iov;
6350                         msg->msg_iovlen = 1;
6351                 }
6352                 break;
6353         }
6354         case SOCK_DGRAM:
6355                 if (msg->msg_name == NULL) {
6356                         errno = EINVAL;
6357                         goto out;
6358                 }
6359
6360                 if (msg->msg_iovlen == 0) {
6361                         break;
6362                 }
6363
6364                 if (si->bound == 0) {
6365                         ret = swrap_auto_bind(fd, si, si->family);
6366                         if (ret == -1) {
6367                                 SWRAP_UNLOCK_SI(si);
6368                                 /*
6369                                  * When attempting to read or write to a
6370                                  * descriptor, if an underlying autobind fails
6371                                  * because it's not a socket, stop intercepting
6372                                  * uses of that descriptor.
6373                                  */
6374                                 if (errno == ENOTSOCK) {
6375                                         swrap_remove_stale(fd);
6376                                         ret = -ENOTSOCK;
6377                                 } else {
6378                                         SWRAP_LOG(SWRAP_LOG_ERROR,
6379                                                   "swrap_recvmsg_before failed");
6380                                 }
6381                                 return ret;
6382                         }
6383                 }
6384                 break;
6385         default:
6386                 errno = EHOSTUNREACH;
6387                 goto out;
6388         }
6389
6390         ret = 0;
6391 out:
6392         SWRAP_UNLOCK_SI(si);
6393
6394         return ret;
6395 }
6396
6397 static int swrap_recvmsg_after(int fd,
6398                                struct socket_info *si,
6399                                struct msghdr *msg,
6400                                const struct sockaddr_un *un_addr,
6401                                socklen_t un_addrlen,
6402                                ssize_t ret)
6403 {
6404         int saved_errno = errno;
6405         size_t i;
6406         uint8_t *buf = NULL;
6407         off_t ofs = 0;
6408         size_t avail = 0;
6409         size_t remain;
6410         int rc;
6411
6412         /* to give better errors */
6413         if (ret == -1) {
6414                 if (saved_errno == ENOENT) {
6415                         saved_errno = EHOSTUNREACH;
6416                 } else if (saved_errno == ENOTSOCK) {
6417                         /* If the fd is not a socket, remove it */
6418                         swrap_remove_stale(fd);
6419                 }
6420         }
6421
6422         for (i = 0; i < (size_t)msg->msg_iovlen; i++) {
6423                 avail += msg->msg_iov[i].iov_len;
6424         }
6425
6426         SWRAP_LOCK_SI(si);
6427
6428         /* Convert the socket address before we leave */
6429         if (si->type == SOCK_DGRAM && un_addr != NULL) {
6430                 rc = sockaddr_convert_from_un(si,
6431                                               un_addr,
6432                                               un_addrlen,
6433                                               si->family,
6434                                               msg->msg_name,
6435                                               &msg->msg_namelen);
6436                 if (rc == -1) {
6437                         goto done;
6438                 }
6439         }
6440
6441         if (avail == 0) {
6442                 rc = 0;
6443                 goto done;
6444         }
6445
6446         if (ret == -1) {
6447                 remain = MIN(80, avail);
6448         } else {
6449                 remain = ret;
6450         }
6451
6452         /* we capture it as one single packet */
6453         buf = (uint8_t *)malloc(remain);
6454         if (buf == NULL) {
6455                 /* we just not capture the packet */
6456                 SWRAP_UNLOCK_SI(si);
6457                 errno = saved_errno;
6458                 return -1;
6459         }
6460
6461         for (i = 0; i < (size_t)msg->msg_iovlen; i++) {
6462                 size_t this_time = MIN(remain, (size_t)msg->msg_iov[i].iov_len);
6463                 memcpy(buf + ofs,
6464                        msg->msg_iov[i].iov_base,
6465                        this_time);
6466                 ofs += this_time;
6467                 remain -= this_time;
6468         }
6469
6470         switch (si->type) {
6471         case SOCK_STREAM:
6472                 if (ret == -1 && saved_errno != EAGAIN && saved_errno != ENOBUFS) {
6473                         swrap_pcap_dump_packet(si, NULL, SWRAP_RECV_RST, NULL, 0);
6474                 } else if (ret == 0) { /* END OF FILE */
6475                         swrap_pcap_dump_packet(si, NULL, SWRAP_RECV_RST, NULL, 0);
6476                 } else if (ret > 0) {
6477                         swrap_pcap_dump_packet(si, NULL, SWRAP_RECV, buf, ret);
6478                 }
6479                 break;
6480
6481         case SOCK_DGRAM:
6482                 if (ret == -1) {
6483                         break;
6484                 }
6485
6486                 if (un_addr != NULL) {
6487                         swrap_pcap_dump_packet(si,
6488                                           msg->msg_name,
6489                                           SWRAP_RECVFROM,
6490                                           buf,
6491                                           ret);
6492                 } else {
6493                         swrap_pcap_dump_packet(si,
6494                                           msg->msg_name,
6495                                           SWRAP_RECV,
6496                                           buf,
6497                                           ret);
6498                 }
6499
6500                 break;
6501         }
6502
6503         rc = 0;
6504 done:
6505         free(buf);
6506         errno = saved_errno;
6507
6508 #ifdef HAVE_STRUCT_MSGHDR_MSG_CONTROL
6509         if (rc == 0 &&
6510             msg->msg_controllen > 0 &&
6511             msg->msg_control != NULL) {
6512                 rc = swrap_msghdr_add_socket_info(si, msg);
6513                 if (rc < 0) {
6514                         SWRAP_UNLOCK_SI(si);
6515                         return -1;
6516                 }
6517         }
6518 #endif
6519
6520         SWRAP_UNLOCK_SI(si);
6521         return rc;
6522 }
6523
6524 /****************************************************************************
6525  *   RECVFROM
6526  ***************************************************************************/
6527
6528 static ssize_t swrap_recvfrom(int s, void *buf, size_t len, int flags,
6529                               struct sockaddr *from, socklen_t *fromlen)
6530 {
6531         struct swrap_address from_addr = {
6532                 .sa_socklen = sizeof(struct sockaddr_un),
6533         };
6534         ssize_t ret;
6535         struct socket_info *si = find_socket_info(s);
6536         struct swrap_address saddr = {
6537                 .sa_socklen = sizeof(struct sockaddr_storage),
6538         };
6539         struct msghdr msg;
6540         struct iovec tmp;
6541         int tret;
6542
6543         if (!si) {
6544                 return libc_recvfrom(s,
6545                                      buf,
6546                                      len,
6547                                      flags,
6548                                      from,
6549                                      fromlen);
6550         }
6551
6552         tmp.iov_base = buf;
6553         tmp.iov_len = len;
6554
6555         ZERO_STRUCT(msg);
6556         if (from != NULL && fromlen != NULL) {
6557                 msg.msg_name = from;   /* optional address */
6558                 msg.msg_namelen = *fromlen; /* size of address */
6559         } else {
6560                 msg.msg_name = &saddr.sa.s; /* optional address */
6561                 msg.msg_namelen = saddr.sa_socklen; /* size of address */
6562         }
6563         msg.msg_iov = &tmp;            /* scatter/gather array */
6564         msg.msg_iovlen = 1;            /* # elements in msg_iov */
6565 #ifdef HAVE_STRUCT_MSGHDR_MSG_CONTROL
6566         msg.msg_control = NULL;        /* ancillary data, see below */
6567         msg.msg_controllen = 0;        /* ancillary data buffer len */
6568         msg.msg_flags = 0;             /* flags on received message */
6569 #endif
6570
6571         tret = swrap_recvmsg_before(s, si, &msg, &tmp);
6572         if (tret < 0) {
6573                 return -1;
6574         }
6575
6576         buf = msg.msg_iov[0].iov_base;
6577         len = msg.msg_iov[0].iov_len;
6578
6579         ret = libc_recvfrom(s,
6580                             buf,
6581                             len,
6582                             flags,
6583                             &from_addr.sa.s,
6584                             &from_addr.sa_socklen);
6585         if (ret == -1) {
6586                 return ret;
6587         }
6588
6589         tret = swrap_recvmsg_after(s,
6590                                    si,
6591                                    &msg,
6592                                    &from_addr.sa.un,
6593                                    from_addr.sa_socklen,
6594                                    ret);
6595         if (tret != 0) {
6596                 return tret;
6597         }
6598
6599         if (from != NULL && fromlen != NULL) {
6600                 *fromlen = msg.msg_namelen;
6601         }
6602
6603         return ret;
6604 }
6605
6606 #ifdef HAVE_ACCEPT_PSOCKLEN_T
6607 ssize_t recvfrom(int s, void *buf, size_t len, int flags,
6608                  struct sockaddr *from, Psocklen_t fromlen)
6609 #else
6610 ssize_t recvfrom(int s, void *buf, size_t len, int flags,
6611                  struct sockaddr *from, socklen_t *fromlen)
6612 #endif
6613 {
6614         return swrap_recvfrom(s, buf, len, flags, from, (socklen_t *)fromlen);
6615 }
6616
6617 /****************************************************************************
6618  *   SENDTO
6619  ***************************************************************************/
6620
6621 static ssize_t swrap_sendto(int s, const void *buf, size_t len, int flags,
6622                             const struct sockaddr *to, socklen_t tolen)
6623 {
6624         struct msghdr msg;
6625         struct iovec tmp;
6626         struct swrap_address un_addr = {
6627                 .sa_socklen = sizeof(struct sockaddr_un),
6628         };
6629         const struct sockaddr_un *to_un = NULL;
6630         ssize_t ret;
6631         int rc;
6632         struct socket_info *si = find_socket_info(s);
6633         int bcast = 0;
6634
6635         if (!si) {
6636                 return libc_sendto(s, buf, len, flags, to, tolen);
6637         }
6638
6639         tmp.iov_base = discard_const_p(char, buf);
6640         tmp.iov_len = len;
6641
6642         ZERO_STRUCT(msg);
6643         msg.msg_name = discard_const_p(struct sockaddr, to); /* optional address */
6644         msg.msg_namelen = tolen;       /* size of address */
6645         msg.msg_iov = &tmp;            /* scatter/gather array */
6646         msg.msg_iovlen = 1;            /* # elements in msg_iov */
6647 #ifdef HAVE_STRUCT_MSGHDR_MSG_CONTROL
6648         msg.msg_control = NULL;        /* ancillary data, see below */
6649         msg.msg_controllen = 0;        /* ancillary data buffer len */
6650         msg.msg_flags = 0;             /* flags on received message */
6651 #endif
6652
6653         rc = swrap_sendmsg_before(s,
6654                                   si,
6655                                   &msg,
6656                                   &tmp,
6657                                   &un_addr.sa.un,
6658                                   &to_un,
6659                                   &to,
6660                                   &bcast);
6661         if (rc < 0) {
6662                 return -1;
6663         }
6664
6665         buf = msg.msg_iov[0].iov_base;
6666         len = msg.msg_iov[0].iov_len;
6667
6668         if (bcast) {
6669                 struct stat st;
6670                 unsigned int iface;
6671                 unsigned int prt = ntohs(((const struct sockaddr_in *)(const void *)to)->sin_port);
6672                 char type;
6673                 char *swrap_dir = NULL;
6674
6675                 type = SOCKET_TYPE_CHAR_UDP;
6676
6677                 swrap_dir = socket_wrapper_dir();
6678                 if (swrap_dir == NULL) {
6679                         return -1;
6680                 }
6681
6682                 for(iface=0; iface <= MAX_WRAPPED_INTERFACES; iface++) {
6683                         swrap_un_path(&un_addr.sa.un,
6684                                       swrap_dir,
6685                                       type,
6686                                       iface,
6687                                       prt);
6688                         if (stat(un_addr.sa.un.sun_path, &st) != 0) continue;
6689
6690                         /* ignore the any errors in broadcast sends */
6691                         libc_sendto(s,
6692                                     buf,
6693                                     len,
6694                                     flags,
6695                                     &un_addr.sa.s,
6696                                     un_addr.sa_socklen);
6697                 }
6698
6699                 SAFE_FREE(swrap_dir);
6700
6701                 SWRAP_LOCK_SI(si);
6702
6703                 swrap_pcap_dump_packet(si, to, SWRAP_SENDTO, buf, len);
6704
6705                 SWRAP_UNLOCK_SI(si);
6706
6707                 return len;
6708         }
6709
6710         SWRAP_LOCK_SI(si);
6711         /*
6712          * If it is a dgram socket and we are connected, don't include the
6713          * 'to' address.
6714          */
6715         if (si->type == SOCK_DGRAM && si->connected) {
6716                 ret = libc_sendto(s,
6717                                   buf,
6718                                   len,
6719                                   flags,
6720                                   NULL,
6721                                   0);
6722         } else {
6723                 ret = libc_sendto(s,
6724                                   buf,
6725                                   len,
6726                                   flags,
6727                                   (struct sockaddr *)msg.msg_name,
6728                                   msg.msg_namelen);
6729         }
6730
6731         SWRAP_UNLOCK_SI(si);
6732
6733         swrap_sendmsg_after(s, si, &msg, to, ret);
6734
6735         return ret;
6736 }
6737
6738 ssize_t sendto(int s, const void *buf, size_t len, int flags,
6739                const struct sockaddr *to, socklen_t tolen)
6740 {
6741         return swrap_sendto(s, buf, len, flags, to, tolen);
6742 }
6743
6744 /****************************************************************************
6745  *   READV
6746  ***************************************************************************/
6747
6748 static ssize_t swrap_recv(int s, void *buf, size_t len, int flags)
6749 {
6750         struct socket_info *si;
6751         struct msghdr msg;
6752         struct swrap_address saddr = {
6753                 .sa_socklen = sizeof(struct sockaddr_storage),
6754         };
6755         struct iovec tmp;
6756         ssize_t ret;
6757         int tret;
6758
6759         si = find_socket_info(s);
6760         if (si == NULL) {
6761                 return libc_recv(s, buf, len, flags);
6762         }
6763
6764         tmp.iov_base = buf;
6765         tmp.iov_len = len;
6766
6767         ZERO_STRUCT(msg);
6768         msg.msg_name = &saddr.sa.s;    /* optional address */
6769         msg.msg_namelen = saddr.sa_socklen; /* size of address */
6770         msg.msg_iov = &tmp;            /* scatter/gather array */
6771         msg.msg_iovlen = 1;            /* # elements in msg_iov */
6772 #ifdef HAVE_STRUCT_MSGHDR_MSG_CONTROL
6773         msg.msg_control = NULL;        /* ancillary data, see below */
6774         msg.msg_controllen = 0;        /* ancillary data buffer len */
6775         msg.msg_flags = 0;             /* flags on received message */
6776 #endif
6777
6778         tret = swrap_recvmsg_before(s, si, &msg, &tmp);
6779         if (tret < 0) {
6780                 return -1;
6781         }
6782
6783         buf = msg.msg_iov[0].iov_base;
6784         len = msg.msg_iov[0].iov_len;
6785
6786         ret = libc_recv(s, buf, len, flags);
6787
6788         tret = swrap_recvmsg_after(s, si, &msg, NULL, 0, ret);
6789         if (tret != 0) {
6790                 return tret;
6791         }
6792
6793         return ret;
6794 }
6795
6796 ssize_t recv(int s, void *buf, size_t len, int flags)
6797 {
6798         return swrap_recv(s, buf, len, flags);
6799 }
6800
6801 /****************************************************************************
6802  *   READ
6803  ***************************************************************************/
6804
6805 static ssize_t swrap_read(int s, void *buf, size_t len)
6806 {
6807         struct socket_info *si;
6808         struct msghdr msg;
6809         struct iovec tmp;
6810         struct swrap_address saddr = {
6811                 .sa_socklen = sizeof(struct sockaddr_storage),
6812         };
6813         ssize_t ret;
6814         int tret;
6815
6816         si = find_socket_info(s);
6817         if (si == NULL) {
6818                 return libc_read(s, buf, len);
6819         }
6820
6821         tmp.iov_base = buf;
6822         tmp.iov_len = len;
6823
6824         ZERO_STRUCT(msg);
6825         msg.msg_name = &saddr.sa.ss;   /* optional address */
6826         msg.msg_namelen = saddr.sa_socklen; /* size of address */
6827         msg.msg_iov = &tmp;            /* scatter/gather array */
6828         msg.msg_iovlen = 1;            /* # elements in msg_iov */
6829 #ifdef HAVE_STRUCT_MSGHDR_MSG_CONTROL
6830         msg.msg_control = NULL;        /* ancillary data, see below */
6831         msg.msg_controllen = 0;        /* ancillary data buffer len */
6832         msg.msg_flags = 0;             /* flags on received message */
6833 #endif
6834
6835         tret = swrap_recvmsg_before(s, si, &msg, &tmp);
6836         if (tret < 0) {
6837                 if (tret == -ENOTSOCK) {
6838                         return libc_read(s, buf, len);
6839                 }
6840                 return -1;
6841         }
6842
6843         buf = msg.msg_iov[0].iov_base;
6844         len = msg.msg_iov[0].iov_len;
6845
6846         ret = libc_read(s, buf, len);
6847
6848         tret = swrap_recvmsg_after(s, si, &msg, NULL, 0, ret);
6849         if (tret != 0) {
6850                 return tret;
6851         }
6852
6853         return ret;
6854 }
6855
6856 ssize_t read(int s, void *buf, size_t len)
6857 {
6858         return swrap_read(s, buf, len);
6859 }
6860
6861 /****************************************************************************
6862  *   WRITE
6863  ***************************************************************************/
6864
6865 static ssize_t swrap_write(int s, const void *buf, size_t len)
6866 {
6867         struct msghdr msg;
6868         struct iovec tmp;
6869         struct sockaddr_un un_addr;
6870         ssize_t ret;
6871         int rc;
6872         struct socket_info *si;
6873
6874         si = find_socket_info(s);
6875         if (si == NULL) {
6876                 return libc_write(s, buf, len);
6877         }
6878
6879         tmp.iov_base = discard_const_p(char, buf);
6880         tmp.iov_len = len;
6881
6882         ZERO_STRUCT(msg);
6883         msg.msg_name = NULL;           /* optional address */
6884         msg.msg_namelen = 0;           /* size of address */
6885         msg.msg_iov = &tmp;            /* scatter/gather array */
6886         msg.msg_iovlen = 1;            /* # elements in msg_iov */
6887 #ifdef HAVE_STRUCT_MSGHDR_MSG_CONTROL
6888         msg.msg_control = NULL;        /* ancillary data, see below */
6889         msg.msg_controllen = 0;        /* ancillary data buffer len */
6890         msg.msg_flags = 0;             /* flags on received message */
6891 #endif
6892
6893         rc = swrap_sendmsg_before(s, si, &msg, &tmp, &un_addr, NULL, NULL, NULL);
6894         if (rc < 0) {
6895                 return -1;
6896         }
6897
6898         buf = msg.msg_iov[0].iov_base;
6899         len = msg.msg_iov[0].iov_len;
6900
6901         ret = libc_write(s, buf, len);
6902
6903         swrap_sendmsg_after(s, si, &msg, NULL, ret);
6904
6905         return ret;
6906 }
6907
6908 ssize_t write(int s, const void *buf, size_t len)
6909 {
6910         return swrap_write(s, buf, len);
6911 }
6912
6913 /****************************************************************************
6914  *   SEND
6915  ***************************************************************************/
6916
6917 static ssize_t swrap_send(int s, const void *buf, size_t len, int flags)
6918 {
6919         struct msghdr msg;
6920         struct iovec tmp;
6921         struct sockaddr_un un_addr;
6922         ssize_t ret;
6923         int rc;
6924         struct socket_info *si = find_socket_info(s);
6925
6926         if (!si) {
6927                 return libc_send(s, buf, len, flags);
6928         }
6929
6930         tmp.iov_base = discard_const_p(char, buf);
6931         tmp.iov_len = len;
6932
6933         ZERO_STRUCT(msg);
6934         msg.msg_name = NULL;           /* optional address */
6935         msg.msg_namelen = 0;           /* size of address */
6936         msg.msg_iov = &tmp;            /* scatter/gather array */
6937         msg.msg_iovlen = 1;            /* # elements in msg_iov */
6938 #ifdef HAVE_STRUCT_MSGHDR_MSG_CONTROL
6939         msg.msg_control = NULL;        /* ancillary data, see below */
6940         msg.msg_controllen = 0;        /* ancillary data buffer len */
6941         msg.msg_flags = 0;             /* flags on received message */
6942 #endif
6943
6944         rc = swrap_sendmsg_before(s, si, &msg, &tmp, &un_addr, NULL, NULL, NULL);
6945         if (rc < 0) {
6946                 return -1;
6947         }
6948
6949         buf = msg.msg_iov[0].iov_base;
6950         len = msg.msg_iov[0].iov_len;
6951
6952         ret = libc_send(s, buf, len, flags);
6953
6954         swrap_sendmsg_after(s, si, &msg, NULL, ret);
6955
6956         return ret;
6957 }
6958
6959 ssize_t send(int s, const void *buf, size_t len, int flags)
6960 {
6961         return swrap_send(s, buf, len, flags);
6962 }
6963
6964 /****************************************************************************
6965  *   RECVMSG
6966  ***************************************************************************/
6967
6968 static ssize_t swrap_recvmsg(int s, struct msghdr *omsg, int flags)
6969 {
6970         struct swrap_address from_addr = {
6971                 .sa_socklen = sizeof(struct sockaddr_un),
6972         };
6973         struct swrap_address convert_addr = {
6974                 .sa_socklen = sizeof(struct sockaddr_storage),
6975         };
6976         struct socket_info *si;
6977         struct msghdr msg;
6978         struct iovec tmp;
6979 #ifdef HAVE_STRUCT_MSGHDR_MSG_CONTROL
6980         size_t msg_ctrllen_filled;
6981         size_t msg_ctrllen_left;
6982 #endif
6983
6984         ssize_t ret;
6985         int rc;
6986
6987         si = find_socket_info(s);
6988         if (si == NULL) {
6989                 rc = swrap_recvmsg_before_unix(omsg, &msg);
6990                 if (rc < 0) {
6991                         return rc;
6992                 }
6993                 ret = libc_recvmsg(s, &msg, flags);
6994                 return swrap_recvmsg_after_unix(&msg, omsg, ret);
6995         }
6996
6997         tmp.iov_base = NULL;
6998         tmp.iov_len = 0;
6999
7000         ZERO_STRUCT(msg);
7001         msg.msg_name = &from_addr.sa;              /* optional address */
7002         msg.msg_namelen = from_addr.sa_socklen;    /* size of address */
7003         msg.msg_iov = omsg->msg_iov;               /* scatter/gather array */
7004         msg.msg_iovlen = omsg->msg_iovlen;         /* # elements in msg_iov */
7005 #ifdef HAVE_STRUCT_MSGHDR_MSG_CONTROL
7006         msg_ctrllen_filled = 0;
7007         msg_ctrllen_left = omsg->msg_controllen;
7008
7009         msg.msg_control = omsg->msg_control;       /* ancillary data, see below */
7010         msg.msg_controllen = omsg->msg_controllen; /* ancillary data buffer len */
7011         msg.msg_flags = omsg->msg_flags;           /* flags on received message */
7012 #endif
7013
7014         rc = swrap_recvmsg_before(s, si, &msg, &tmp);
7015         if (rc < 0) {
7016                 return -1;
7017         }
7018
7019         ret = libc_recvmsg(s, &msg, flags);
7020
7021 #ifdef HAVE_STRUCT_MSGHDR_MSG_CONTROL
7022         msg_ctrllen_filled += msg.msg_controllen;
7023         msg_ctrllen_left -= msg.msg_controllen;
7024
7025         if (omsg->msg_control != NULL) {
7026                 uint8_t *p;
7027
7028                 p = omsg->msg_control;
7029                 p += msg_ctrllen_filled;
7030
7031                 msg.msg_control = p;
7032                 msg.msg_controllen = msg_ctrllen_left;
7033         } else {
7034                 msg.msg_control = NULL;
7035                 msg.msg_controllen = 0;
7036         }
7037 #endif
7038
7039         /*
7040          * We convert the unix address to a IP address so we need a buffer
7041          * which can store the address in case of SOCK_DGRAM, see below.
7042          */
7043         msg.msg_name = &convert_addr.sa;
7044         msg.msg_namelen = convert_addr.sa_socklen;
7045
7046         rc = swrap_recvmsg_after(s,
7047                                  si,
7048                                  &msg,
7049                                  &from_addr.sa.un,
7050                                  from_addr.sa_socklen,
7051                                  ret);
7052         if (rc != 0) {
7053                 return rc;
7054         }
7055
7056 #ifdef HAVE_STRUCT_MSGHDR_MSG_CONTROL
7057         if (omsg->msg_control != NULL) {
7058                 /* msg.msg_controllen = space left */
7059                 msg_ctrllen_left = msg.msg_controllen;
7060                 msg_ctrllen_filled = omsg->msg_controllen - msg_ctrllen_left;
7061         }
7062
7063         /* Update the original message length */
7064         omsg->msg_controllen = msg_ctrllen_filled;
7065         omsg->msg_flags = msg.msg_flags;
7066 #endif
7067         omsg->msg_iovlen = msg.msg_iovlen;
7068
7069         SWRAP_LOCK_SI(si);
7070
7071         /*
7072          * From the manpage:
7073          *
7074          * The  msg_name  field  points  to a caller-allocated buffer that is
7075          * used to return the source address if the socket is unconnected.  The
7076          * caller should set msg_namelen to the size of this buffer before this
7077          * call; upon return from a successful call, msg_name will contain the
7078          * length of the returned address.  If the application  does  not  need
7079          * to know the source address, msg_name can be specified as NULL.
7080          */
7081         if (si->type == SOCK_STREAM) {
7082                 omsg->msg_namelen = 0;
7083         } else if (omsg->msg_name != NULL &&
7084                    omsg->msg_namelen != 0 &&
7085                    omsg->msg_namelen >= msg.msg_namelen) {
7086                 memcpy(omsg->msg_name, msg.msg_name, msg.msg_namelen);
7087                 omsg->msg_namelen = msg.msg_namelen;
7088         }
7089
7090         SWRAP_UNLOCK_SI(si);
7091
7092         return ret;
7093 }
7094
7095 ssize_t recvmsg(int sockfd, struct msghdr *msg, int flags)
7096 {
7097         return swrap_recvmsg(sockfd, msg, flags);
7098 }
7099
7100 /****************************************************************************
7101  *   SENDMSG
7102  ***************************************************************************/
7103
7104 static ssize_t swrap_sendmsg(int s, const struct msghdr *omsg, int flags)
7105 {
7106         struct msghdr msg;
7107         struct iovec tmp;
7108         struct sockaddr_un un_addr;
7109         const struct sockaddr_un *to_un = NULL;
7110         const struct sockaddr *to = NULL;
7111         ssize_t ret;
7112         int rc;
7113         struct socket_info *si = find_socket_info(s);
7114         int bcast = 0;
7115
7116         if (!si) {
7117                 int scm_rights_pipe_fd = -1;
7118
7119                 rc = swrap_sendmsg_before_unix(omsg, &msg,
7120                                                &scm_rights_pipe_fd);
7121                 if (rc < 0) {
7122                         return rc;
7123                 }
7124                 ret = libc_sendmsg(s, &msg, flags);
7125                 return swrap_sendmsg_after_unix(&msg, ret, scm_rights_pipe_fd);
7126         }
7127
7128         ZERO_STRUCT(un_addr);
7129
7130         tmp.iov_base = NULL;
7131         tmp.iov_len = 0;
7132
7133         ZERO_STRUCT(msg);
7134
7135         SWRAP_LOCK_SI(si);
7136
7137         if (si->connected == 0) {
7138                 msg.msg_name = omsg->msg_name;             /* optional address */
7139                 msg.msg_namelen = omsg->msg_namelen;       /* size of address */
7140         }
7141         msg.msg_iov = omsg->msg_iov;               /* scatter/gather array */
7142         msg.msg_iovlen = omsg->msg_iovlen;         /* # elements in msg_iov */
7143
7144         SWRAP_UNLOCK_SI(si);
7145
7146 #ifdef HAVE_STRUCT_MSGHDR_MSG_CONTROL
7147         if (omsg != NULL && omsg->msg_controllen > 0 && omsg->msg_control != NULL) {
7148                 uint8_t *cmbuf = NULL;
7149                 size_t cmlen = 0;
7150
7151                 rc = swrap_sendmsg_filter_cmsghdr(omsg, &cmbuf, &cmlen);
7152                 if (rc < 0) {
7153                         return rc;
7154                 }
7155
7156                 if (cmlen == 0) {
7157                         msg.msg_controllen = 0;
7158                         msg.msg_control = NULL;
7159                 } else {
7160                         msg.msg_control = cmbuf;
7161                         msg.msg_controllen = cmlen;
7162                 }
7163         }
7164         msg.msg_flags = omsg->msg_flags;           /* flags on received message */
7165 #endif
7166         rc = swrap_sendmsg_before(s, si, &msg, &tmp, &un_addr, &to_un, &to, &bcast);
7167         if (rc < 0) {
7168                 int saved_errno = errno;
7169 #ifdef HAVE_STRUCT_MSGHDR_MSG_CONTROL
7170                 SAFE_FREE(msg.msg_control);
7171 #endif
7172                 errno = saved_errno;
7173                 return -1;
7174         }
7175
7176         if (bcast) {
7177                 struct stat st;
7178                 unsigned int iface;
7179                 unsigned int prt = ntohs(((const struct sockaddr_in *)(const void *)to)->sin_port);
7180                 char type;
7181                 size_t i, len = 0;
7182                 uint8_t *buf;
7183                 off_t ofs = 0;
7184                 size_t avail = 0;
7185                 size_t remain;
7186                 char *swrap_dir = NULL;
7187
7188                 for (i = 0; i < (size_t)msg.msg_iovlen; i++) {
7189                         avail += msg.msg_iov[i].iov_len;
7190                 }
7191
7192                 len = avail;
7193                 remain = avail;
7194
7195                 /* we capture it as one single packet */
7196                 buf = (uint8_t *)malloc(remain);
7197                 if (!buf) {
7198                         int saved_errno = errno;
7199 #ifdef HAVE_STRUCT_MSGHDR_MSG_CONTROL
7200                         SAFE_FREE(msg.msg_control);
7201 #endif
7202                         errno = saved_errno;
7203                         return -1;
7204                 }
7205
7206                 for (i = 0; i < (size_t)msg.msg_iovlen; i++) {
7207                         size_t this_time = MIN(remain, (size_t)msg.msg_iov[i].iov_len);
7208                         memcpy(buf + ofs,
7209                                msg.msg_iov[i].iov_base,
7210                                this_time);
7211                         ofs += this_time;
7212                         remain -= this_time;
7213                 }
7214
7215                 type = SOCKET_TYPE_CHAR_UDP;
7216
7217                 swrap_dir = socket_wrapper_dir();
7218                 if (swrap_dir == NULL) {
7219                         int saved_errno = errno;
7220 #ifdef HAVE_STRUCT_MSGHDR_MSG_CONTROL
7221                         SAFE_FREE(msg.msg_control);
7222 #endif
7223                         SAFE_FREE(buf);
7224                         errno = saved_errno;
7225                         return -1;
7226                 }
7227
7228                 for(iface=0; iface <= MAX_WRAPPED_INTERFACES; iface++) {
7229                         swrap_un_path(&un_addr, swrap_dir, type, iface, prt);
7230                         if (stat(un_addr.sun_path, &st) != 0) continue;
7231
7232                         msg.msg_name = &un_addr;           /* optional address */
7233                         msg.msg_namelen = sizeof(un_addr); /* size of address */
7234
7235                         /* ignore the any errors in broadcast sends */
7236                         libc_sendmsg(s, &msg, flags);
7237                 }
7238
7239                 SAFE_FREE(swrap_dir);
7240
7241                 SWRAP_LOCK_SI(si);
7242
7243                 swrap_pcap_dump_packet(si, to, SWRAP_SENDTO, buf, len);
7244                 free(buf);
7245
7246                 SWRAP_UNLOCK_SI(si);
7247
7248                 return len;
7249         }
7250
7251         ret = libc_sendmsg(s, &msg, flags);
7252
7253         swrap_sendmsg_after(s, si, &msg, to, ret);
7254
7255 #ifdef HAVE_STRUCT_MSGHDR_MSG_CONTROL
7256         {
7257                 int saved_errno = errno;
7258                 SAFE_FREE(msg.msg_control);
7259                 errno = saved_errno;
7260         }
7261 #endif
7262
7263         return ret;
7264 }
7265
7266 ssize_t sendmsg(int s, const struct msghdr *omsg, int flags)
7267 {
7268         return swrap_sendmsg(s, omsg, flags);
7269 }
7270
7271 /****************************************************************************
7272  *   READV
7273  ***************************************************************************/
7274
7275 static ssize_t swrap_readv(int s, const struct iovec *vector, int count)
7276 {
7277         struct socket_info *si;
7278         struct msghdr msg;
7279         struct iovec tmp;
7280         struct swrap_address saddr = {
7281                 .sa_socklen = sizeof(struct sockaddr_storage)
7282         };
7283         ssize_t ret;
7284         int rc;
7285
7286         si = find_socket_info(s);
7287         if (si == NULL) {
7288                 return libc_readv(s, vector, count);
7289         }
7290
7291         tmp.iov_base = NULL;
7292         tmp.iov_len = 0;
7293
7294         ZERO_STRUCT(msg);
7295         msg.msg_name = &saddr.sa.s; /* optional address */
7296         msg.msg_namelen = saddr.sa_socklen;      /* size of address */
7297         msg.msg_iov = discard_const_p(struct iovec, vector); /* scatter/gather array */
7298         msg.msg_iovlen = count;        /* # elements in msg_iov */
7299 #ifdef HAVE_STRUCT_MSGHDR_MSG_CONTROL
7300         msg.msg_control = NULL;        /* ancillary data, see below */
7301         msg.msg_controllen = 0;        /* ancillary data buffer len */
7302         msg.msg_flags = 0;             /* flags on received message */
7303 #endif
7304
7305         rc = swrap_recvmsg_before(s, si, &msg, &tmp);
7306         if (rc < 0) {
7307                 if (rc == -ENOTSOCK) {
7308                         return libc_readv(s, vector, count);
7309                 }
7310                 return -1;
7311         }
7312
7313         ret = libc_readv(s, msg.msg_iov, msg.msg_iovlen);
7314
7315         rc = swrap_recvmsg_after(s, si, &msg, NULL, 0, ret);
7316         if (rc != 0) {
7317                 return rc;
7318         }
7319
7320         return ret;
7321 }
7322
7323 ssize_t readv(int s, const struct iovec *vector, int count)
7324 {
7325         return swrap_readv(s, vector, count);
7326 }
7327
7328 /****************************************************************************
7329  *   WRITEV
7330  ***************************************************************************/
7331
7332 static ssize_t swrap_writev(int s, const struct iovec *vector, int count)
7333 {
7334         struct msghdr msg;
7335         struct iovec tmp;
7336         struct sockaddr_un un_addr;
7337         ssize_t ret;
7338         int rc;
7339         struct socket_info *si = find_socket_info(s);
7340
7341         if (!si) {
7342                 return libc_writev(s, vector, count);
7343         }
7344
7345         tmp.iov_base = NULL;
7346         tmp.iov_len = 0;
7347
7348         ZERO_STRUCT(msg);
7349         msg.msg_name = NULL;           /* optional address */
7350         msg.msg_namelen = 0;           /* size of address */
7351         msg.msg_iov = discard_const_p(struct iovec, vector); /* scatter/gather array */
7352         msg.msg_iovlen = count;        /* # elements in msg_iov */
7353 #ifdef HAVE_STRUCT_MSGHDR_MSG_CONTROL
7354         msg.msg_control = NULL;        /* ancillary data, see below */
7355         msg.msg_controllen = 0;        /* ancillary data buffer len */
7356         msg.msg_flags = 0;             /* flags on received message */
7357 #endif
7358
7359         rc = swrap_sendmsg_before(s, si, &msg, &tmp, &un_addr, NULL, NULL, NULL);
7360         if (rc < 0) {
7361                 if (rc == -ENOTSOCK) {
7362                         return libc_readv(s, vector, count);
7363                 }
7364                 return -1;
7365         }
7366
7367         ret = libc_writev(s, msg.msg_iov, msg.msg_iovlen);
7368
7369         swrap_sendmsg_after(s, si, &msg, NULL, ret);
7370
7371         return ret;
7372 }
7373
7374 ssize_t writev(int s, const struct iovec *vector, int count)
7375 {
7376         return swrap_writev(s, vector, count);
7377 }
7378
7379 /****************************
7380  * CLOSE
7381  ***************************/
7382
7383 static int swrap_close(int fd)
7384 {
7385         struct socket_info *si = NULL;
7386         int si_index;
7387         int ret;
7388
7389         swrap_mutex_lock(&socket_reset_mutex);
7390
7391         si_index = find_socket_info_index(fd);
7392         if (si_index == -1) {
7393                 swrap_mutex_unlock(&socket_reset_mutex);
7394                 return libc_close(fd);
7395         }
7396
7397         SWRAP_LOG(SWRAP_LOG_TRACE, "Close wrapper for fd=%d", fd);
7398         reset_socket_info_index(fd);
7399
7400         si = swrap_get_socket_info(si_index);
7401
7402         swrap_mutex_lock(&first_free_mutex);
7403         SWRAP_LOCK_SI(si);
7404
7405         ret = libc_close(fd);
7406
7407         swrap_dec_refcount(si);
7408
7409         if (swrap_get_refcount(si) > 0) {
7410                 /* there are still references left */
7411                 goto out;
7412         }
7413
7414         if (si->fd_passed) {
7415                 goto set_next_free;
7416         }
7417
7418         if (si->myname.sa_socklen > 0 && si->peername.sa_socklen > 0) {
7419                 swrap_pcap_dump_packet(si, NULL, SWRAP_CLOSE_SEND, NULL, 0);
7420         }
7421
7422         if (si->myname.sa_socklen > 0 && si->peername.sa_socklen > 0) {
7423                 swrap_pcap_dump_packet(si, NULL, SWRAP_CLOSE_RECV, NULL, 0);
7424                 swrap_pcap_dump_packet(si, NULL, SWRAP_CLOSE_ACK, NULL, 0);
7425         }
7426
7427         if (si->un_addr.sun_path[0] != '\0') {
7428                 unlink(si->un_addr.sun_path);
7429         }
7430
7431 set_next_free:
7432         swrap_set_next_free(si, first_free);
7433         first_free = si_index;
7434
7435 out:
7436         SWRAP_UNLOCK_SI(si);
7437         swrap_mutex_unlock(&first_free_mutex);
7438         swrap_mutex_unlock(&socket_reset_mutex);
7439
7440         return ret;
7441 }
7442
7443 int close(int fd)
7444 {
7445         return swrap_close(fd);
7446 }
7447
7448 /****************************
7449  * DUP
7450  ***************************/
7451
7452 static int swrap_dup(int fd)
7453 {
7454         struct socket_info *si;
7455         int dup_fd, idx;
7456
7457         idx = find_socket_info_index(fd);
7458         if (idx == -1) {
7459                 return libc_dup(fd);
7460         }
7461
7462         si = swrap_get_socket_info(idx);
7463
7464         dup_fd = libc_dup(fd);
7465         if (dup_fd == -1) {
7466                 int saved_errno = errno;
7467                 errno = saved_errno;
7468                 return -1;
7469         }
7470
7471         if ((size_t)dup_fd >= socket_fds_max) {
7472                 SWRAP_LOG(SWRAP_LOG_ERROR,
7473                           "The max socket index limit of %zu has been reached, "
7474                           "trying to add %d",
7475                           socket_fds_max,
7476                           dup_fd);
7477                 libc_close(dup_fd);
7478                 errno = EMFILE;
7479                 return -1;
7480         }
7481
7482         SWRAP_LOCK_SI(si);
7483
7484         swrap_inc_refcount(si);
7485
7486         SWRAP_UNLOCK_SI(si);
7487
7488         /* Make sure we don't have an entry for the fd */
7489         swrap_remove_stale(dup_fd);
7490
7491         set_socket_info_index(dup_fd, idx);
7492
7493         return dup_fd;
7494 }
7495
7496 int dup(int fd)
7497 {
7498         return swrap_dup(fd);
7499 }
7500
7501 /****************************
7502  * DUP2
7503  ***************************/
7504
7505 static int swrap_dup2(int fd, int newfd)
7506 {
7507         struct socket_info *si;
7508         int dup_fd, idx;
7509
7510         idx = find_socket_info_index(fd);
7511         if (idx == -1) {
7512                 return libc_dup2(fd, newfd);
7513         }
7514
7515         si = swrap_get_socket_info(idx);
7516
7517         if (fd == newfd) {
7518                 /*
7519                  * According to the manpage:
7520                  *
7521                  * "If oldfd is a valid file descriptor, and newfd has the same
7522                  * value as oldfd, then dup2() does nothing, and returns newfd."
7523                  */
7524                 return newfd;
7525         }
7526
7527         if ((size_t)newfd >= socket_fds_max) {
7528                 SWRAP_LOG(SWRAP_LOG_ERROR,
7529                           "The max socket index limit of %zu has been reached, "
7530                           "trying to add %d",
7531                           socket_fds_max,
7532                           newfd);
7533                 errno = EMFILE;
7534                 return -1;
7535         }
7536
7537         if (find_socket_info(newfd)) {
7538                 /* dup2() does an implicit close of newfd, which we
7539                  * need to emulate */
7540                 swrap_close(newfd);
7541         }
7542
7543         dup_fd = libc_dup2(fd, newfd);
7544         if (dup_fd == -1) {
7545                 int saved_errno = errno;
7546                 errno = saved_errno;
7547                 return -1;
7548         }
7549
7550         SWRAP_LOCK_SI(si);
7551
7552         swrap_inc_refcount(si);
7553
7554         SWRAP_UNLOCK_SI(si);
7555
7556         /* Make sure we don't have an entry for the fd */
7557         swrap_remove_stale(dup_fd);
7558
7559         set_socket_info_index(dup_fd, idx);
7560
7561         return dup_fd;
7562 }
7563
7564 int dup2(int fd, int newfd)
7565 {
7566         return swrap_dup2(fd, newfd);
7567 }
7568
7569 /****************************
7570  * FCNTL
7571  ***************************/
7572
7573 static int swrap_vfcntl(int fd, int cmd, va_list va)
7574 {
7575         struct socket_info *si;
7576         int rc, dup_fd, idx;
7577
7578         idx = find_socket_info_index(fd);
7579         if (idx == -1) {
7580                 return libc_vfcntl(fd, cmd, va);
7581         }
7582
7583         si = swrap_get_socket_info(idx);
7584
7585         switch (cmd) {
7586         case F_DUPFD:
7587                 dup_fd = libc_vfcntl(fd, cmd, va);
7588                 if (dup_fd == -1) {
7589                         int saved_errno = errno;
7590                         errno = saved_errno;
7591                         return -1;
7592                 }
7593
7594                 /* Make sure we don't have an entry for the fd */
7595                 swrap_remove_stale(dup_fd);
7596
7597                 if ((size_t)dup_fd >= socket_fds_max) {
7598                         SWRAP_LOG(SWRAP_LOG_ERROR,
7599                           "The max socket index limit of %zu has been reached, "
7600                           "trying to add %d",
7601                           socket_fds_max,
7602                           dup_fd);
7603                         libc_close(dup_fd);
7604                         errno = EMFILE;
7605                         return -1;
7606                 }
7607
7608                 SWRAP_LOCK_SI(si);
7609
7610                 swrap_inc_refcount(si);
7611
7612                 SWRAP_UNLOCK_SI(si);
7613
7614
7615                 set_socket_info_index(dup_fd, idx);
7616
7617                 rc = dup_fd;
7618                 break;
7619         default:
7620                 rc = libc_vfcntl(fd, cmd, va);
7621                 break;
7622         }
7623
7624         return rc;
7625 }
7626
7627 int fcntl(int fd, int cmd, ...)
7628 {
7629         va_list va;
7630         int rc;
7631
7632         va_start(va, cmd);
7633
7634         rc = swrap_vfcntl(fd, cmd, va);
7635
7636         va_end(va);
7637
7638         return rc;
7639 }
7640
7641 /****************************
7642  * EVENTFD
7643  ***************************/
7644
7645 #ifdef HAVE_EVENTFD
7646 static int swrap_eventfd(int count, int flags)
7647 {
7648         int fd;
7649
7650         fd = libc_eventfd(count, flags);
7651         if (fd != -1) {
7652                 swrap_remove_stale(fd);
7653         }
7654
7655         return fd;
7656 }
7657
7658 #ifdef HAVE_EVENTFD_UNSIGNED_INT
7659 int eventfd(unsigned int count, int flags)
7660 #else
7661 int eventfd(int count, int flags)
7662 #endif
7663 {
7664         return swrap_eventfd(count, flags);
7665 }
7666 #endif
7667
7668 #ifdef HAVE_PLEDGE
7669 int pledge(const char *promises, const char *paths[])
7670 {
7671         (void)promises; /* unused */
7672         (void)paths; /* unused */
7673
7674         return 0;
7675 }
7676 #endif /* HAVE_PLEDGE */
7677
7678 static void swrap_thread_prepare(void)
7679 {
7680         /*
7681          * This function should only be called here!!
7682          *
7683          * We bind all symobls to avoid deadlocks of the fork is
7684          * interrupted by a signal handler using a symbol of this
7685          * library.
7686          */
7687         swrap_bind_symbol_all();
7688
7689         SWRAP_LOCK_ALL;
7690 }
7691
7692 static void swrap_thread_parent(void)
7693 {
7694         SWRAP_UNLOCK_ALL;
7695 }
7696
7697 static void swrap_thread_child(void)
7698 {
7699         SWRAP_REINIT_ALL;
7700 }
7701
7702 /****************************
7703  * CONSTRUCTOR
7704  ***************************/
7705 void swrap_constructor(void)
7706 {
7707         if (PIPE_BUF < sizeof(struct swrap_unix_scm_rights)) {
7708                 SWRAP_LOG(SWRAP_LOG_ERROR,
7709                           "PIPE_BUF=%zu < "
7710                           "sizeof(struct swrap_unix_scm_rights)=%zu\n"
7711                           "sizeof(struct swrap_unix_scm_rights_payload)=%zu "
7712                           "sizeof(struct socket_info)=%zu",
7713                           (size_t)PIPE_BUF,
7714                           sizeof(struct swrap_unix_scm_rights),
7715                           sizeof(struct swrap_unix_scm_rights_payload),
7716                           sizeof(struct socket_info));
7717                 exit(-1);
7718         }
7719
7720         SWRAP_REINIT_ALL;
7721
7722         /*
7723         * If we hold a lock and the application forks, then the child
7724         * is not able to unlock the mutex and we are in a deadlock.
7725         * This should prevent such deadlocks.
7726         */
7727         pthread_atfork(&swrap_thread_prepare,
7728                        &swrap_thread_parent,
7729                        &swrap_thread_child);
7730 }
7731
7732 /****************************
7733  * DESTRUCTOR
7734  ***************************/
7735
7736 /*
7737  * This function is called when the library is unloaded and makes sure that
7738  * sockets get closed and the unix file for the socket are unlinked.
7739  */
7740 void swrap_destructor(void)
7741 {
7742         size_t i;
7743
7744         if (socket_fds_idx != NULL) {
7745                 for (i = 0; i < socket_fds_max; ++i) {
7746                         if (socket_fds_idx[i] != -1) {
7747                                 swrap_close(i);
7748                         }
7749                 }
7750                 SAFE_FREE(socket_fds_idx);
7751         }
7752
7753         SAFE_FREE(sockets);
7754
7755         if (swrap.libc.handle != NULL) {
7756                 dlclose(swrap.libc.handle);
7757         }
7758         if (swrap.libc.socket_handle) {
7759                 dlclose(swrap.libc.socket_handle);
7760         }
7761 }
7762
7763 #if defined(HAVE__SOCKET) && defined(HAVE__CLOSE)
7764 /*
7765  * On FreeBSD 12 (and maybe other platforms)
7766  * system libraries like libresolv prefix there
7767  * syscalls with '_' in order to always use
7768  * the symbols from libc.
7769  *
7770  * In the interaction with resolv_wrapper,
7771  * we need to inject socket wrapper into libresolv,
7772  * which means we need to private all socket
7773  * related syscalls also with the '_' prefix.
7774  *
7775  * This is tested in Samba's 'make test',
7776  * there we noticed that providing '_read'
7777  * and '_open' would cause errors, which
7778  * means we skip '_read', '_write' and
7779  * all non socket related calls without
7780  * further analyzing the problem.
7781  */
7782 #define SWRAP_SYMBOL_ALIAS(__sym, __aliassym) \
7783         extern typeof(__sym) __aliassym __attribute__ ((alias(#__sym)))
7784
7785 #ifdef HAVE_ACCEPT4
7786 SWRAP_SYMBOL_ALIAS(accept4, _accept4);
7787 #endif
7788 SWRAP_SYMBOL_ALIAS(accept, _accept);
7789 SWRAP_SYMBOL_ALIAS(bind, _bind);
7790 SWRAP_SYMBOL_ALIAS(close, _close);
7791 SWRAP_SYMBOL_ALIAS(connect, _connect);
7792 SWRAP_SYMBOL_ALIAS(dup, _dup);
7793 SWRAP_SYMBOL_ALIAS(dup2, _dup2);
7794 SWRAP_SYMBOL_ALIAS(fcntl, _fcntl);
7795 SWRAP_SYMBOL_ALIAS(getpeername, _getpeername);
7796 SWRAP_SYMBOL_ALIAS(getsockname, _getsockname);
7797 SWRAP_SYMBOL_ALIAS(getsockopt, _getsockopt);
7798 SWRAP_SYMBOL_ALIAS(ioctl, _ioctl);
7799 SWRAP_SYMBOL_ALIAS(listen, _listen);
7800 SWRAP_SYMBOL_ALIAS(readv, _readv);
7801 SWRAP_SYMBOL_ALIAS(recv, _recv);
7802 SWRAP_SYMBOL_ALIAS(recvfrom, _recvfrom);
7803 SWRAP_SYMBOL_ALIAS(recvmsg, _recvmsg);
7804 SWRAP_SYMBOL_ALIAS(send, _send);
7805 SWRAP_SYMBOL_ALIAS(sendmsg, _sendmsg);
7806 SWRAP_SYMBOL_ALIAS(sendto, _sendto);
7807 SWRAP_SYMBOL_ALIAS(setsockopt, _setsockopt);
7808 SWRAP_SYMBOL_ALIAS(socket, _socket);
7809 SWRAP_SYMBOL_ALIAS(socketpair, _socketpair);
7810 SWRAP_SYMBOL_ALIAS(writev, _writev);
7811
7812 #endif /* SOCKET_WRAPPER_EXPORT_UNDERSCORE_SYMBOLS */