LCOV - code coverage report
Current view: top level - third_party/socket_wrapper - socket_wrapper.c (source / functions) Hit Total Coverage
Test: coverage report for master 2f515e9b Lines: 2671 3908 68.3 %
Date: 2024-04-21 15:09:00 Functions: 147 171 86.0 %

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

Generated by: LCOV version 1.14