LCOV - code coverage report
Current view: top level - third_party/socket_wrapper - socket_wrapper.c (source / functions) Hit Total Coverage
Test: coverage report for recycleplus df22b230 Lines: 2300 3525 65.2 %
Date: 2024-02-14 10:14:15 Functions: 139 163 85.3 %

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

Generated by: LCOV version 1.14