2006-10-09 00:48:34 +04:00
/*
2018-05-02 16:57:38 +03:00
* BSD 3 - Clause License
2006-10-09 00:48:34 +04:00
*
2018-05-02 16:57:38 +03:00
* Copyright ( c ) 2005 - 2008 , Jelmer Vernooij < jelmer @ samba . org >
2021-02-17 14:57:01 +03:00
* Copyright ( c ) 2006 - 2021 , Stefan Metzmacher < metze @ samba . org >
* Copyright ( c ) 2013 - 2021 , Andreas Schneider < asn @ samba . org >
2018-05-02 16:57:38 +03:00
* Copyright ( c ) 2014 - 2017 , Michael Adam < obnox @ samba . org >
* Copyright ( c ) 2016 - 2018 , Anoop C S < anoopcs @ redhat . com >
2006-10-09 00:48:34 +04:00
* All rights reserved .
2014-04-07 18:12:21 +04:00
*
2006-10-09 00:48:34 +04:00
* Redistribution and use in source and binary forms , with or without
* modification , are permitted provided that the following conditions
* are met :
2014-04-07 18:12:21 +04:00
*
2006-10-09 00:48:34 +04:00
* 1. Redistributions of source code must retain the above copyright
* notice , this list of conditions and the following disclaimer .
2014-04-07 18:12:21 +04:00
*
2006-10-09 00:48:34 +04:00
* 2. Redistributions in binary form must reproduce the above copyright
* notice , this list of conditions and the following disclaimer in the
* documentation and / or other materials provided with the distribution .
2014-04-07 18:12:21 +04:00
*
2006-10-09 00:48:34 +04:00
* 3. Neither the name of the author nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission .
2014-04-07 18:12:21 +04:00
*
2006-10-09 00:48:34 +04:00
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ` ` AS IS ' ' AND
* ANY EXPRESS OR IMPLIED WARRANTIES , INCLUDING , BUT NOT LIMITED TO , THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED . IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT , INDIRECT , INCIDENTAL , SPECIAL , EXEMPLARY , OR CONSEQUENTIAL
* DAMAGES ( INCLUDING , BUT NOT LIMITED TO , PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES ; LOSS OF USE , DATA , OR PROFITS ; OR BUSINESS INTERRUPTION )
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY , WHETHER IN CONTRACT , STRICT
* LIABILITY , OR TORT ( INCLUDING NEGLIGENCE OR OTHERWISE ) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE , EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE .
*/
/*
Socket wrapper library . Passes all socket communication over
unix domain sockets if the environment variable SOCKET_WRAPPER_DIR
2005-03-28 05:00:39 +04:00
is set .
*/
2011-11-21 02:45:05 +04:00
# include "config.h"
2005-03-28 05:00:39 +04:00
# include <sys/types.h>
2006-10-19 08:56:21 +04:00
# include <sys/time.h>
2005-06-10 16:21:46 +04:00
# include <sys/stat.h>
2005-03-28 05:00:39 +04:00
# include <sys/socket.h>
2006-10-09 01:45:07 +04:00
# include <sys/ioctl.h>
2013-11-22 08:15:13 +04:00
# ifdef HAVE_SYS_FILIO_H
2006-10-17 13:35:45 +04:00
# include <sys/filio.h>
2013-11-22 08:15:13 +04:00
# endif
2014-04-07 18:12:21 +04:00
# ifdef HAVE_SYS_SIGNALFD_H
# include <sys/signalfd.h>
# endif
# ifdef HAVE_SYS_EVENTFD_H
# include <sys/eventfd.h>
# endif
# ifdef HAVE_SYS_TIMERFD_H
# include <sys/timerfd.h>
# endif
# include <sys/uio.h>
2005-03-28 05:00:39 +04:00
# include <errno.h>
# include <sys/un.h>
# include <netinet/in.h>
2005-03-31 03:28:15 +04:00
# include <netinet/tcp.h>
2020-06-08 15:18:00 +03:00
# ifdef HAVE_NETINET_TCP_FSM_H
# include <netinet/tcp_fsm.h>
# endif
2014-04-07 18:12:21 +04:00
# include <arpa/inet.h>
2006-10-09 01:45:07 +04:00
# include <fcntl.h>
2005-03-28 05:00:39 +04:00
# include <stdlib.h>
# include <string.h>
# include <stdio.h>
2008-03-17 16:08:57 +03:00
# include <stdint.h>
2014-04-07 18:12:21 +04:00
# include <stdarg.h>
# include <stdbool.h>
# include <unistd.h>
2014-06-03 16:50:05 +04:00
# ifdef HAVE_GNU_LIB_NAMES_H
# include <gnu/lib-names.h>
# endif
2014-06-03 17:11:46 +04:00
# ifdef HAVE_RPC_RPC_H
# include <rpc/rpc.h>
# endif
2017-11-07 14:29:51 +03:00
# include <pthread.h>
2013-11-22 08:15:13 +04:00
2021-02-17 14:57:01 +03:00
# include "socket_wrapper.h"
2014-04-07 18:12:21 +04:00
enum swrap_dbglvl_e {
SWRAP_LOG_ERROR = 0 ,
SWRAP_LOG_WARN ,
SWRAP_LOG_DEBUG ,
SWRAP_LOG_TRACE
} ;
/* GCC have printf type attribute check. */
# ifdef HAVE_FUNCTION_ATTRIBUTE_FORMAT
# define PRINTF_ATTRIBUTE(a,b) __attribute__ ((__format__ (__printf__, a, b)))
# else
# define PRINTF_ATTRIBUTE(a,b)
# endif /* HAVE_FUNCTION_ATTRIBUTE_FORMAT */
2017-11-07 14:29:51 +03:00
# ifdef HAVE_CONSTRUCTOR_ATTRIBUTE
# define CONSTRUCTOR_ATTRIBUTE __attribute__ ((constructor))
# else
# define CONSTRUCTOR_ATTRIBUTE
# endif /* HAVE_CONSTRUCTOR_ATTRIBUTE */
2014-04-07 18:12:21 +04:00
# ifdef HAVE_DESTRUCTOR_ATTRIBUTE
# define DESTRUCTOR_ATTRIBUTE __attribute__ ((destructor))
# else
# define DESTRUCTOR_ATTRIBUTE
2013-11-22 08:15:13 +04:00
# endif
2017-11-07 14:29:51 +03:00
# ifndef FALL_THROUGH
# ifdef HAVE_FALLTHROUGH_ATTRIBUTE
# define FALL_THROUGH __attribute__ ((fallthrough))
# else /* HAVE_FALLTHROUGH_ATTRIBUTE */
2018-05-02 16:57:38 +03:00
# define FALL_THROUGH ((void)0)
2017-11-07 14:29:51 +03:00
# endif /* HAVE_FALLTHROUGH_ATTRIBUTE */
# endif /* FALL_THROUGH */
2015-02-23 19:16:00 +03:00
# ifdef HAVE_ADDRESS_SANITIZER_ATTRIBUTE
# define DO_NOT_SANITIZE_ADDRESS_ATTRIBUTE __attribute__((no_sanitize_address))
# else
# define DO_NOT_SANITIZE_ADDRESS_ATTRIBUTE
# endif
2014-04-07 18:12:21 +04:00
# ifdef HAVE_GCC_THREAD_LOCAL_STORAGE
# define SWRAP_THREAD __thread
# else
# define SWRAP_THREAD
# endif
# ifndef MIN
# define MIN(a,b) ((a)<(b)?(a):(b))
2013-11-22 08:15:13 +04:00
# endif
# ifndef ZERO_STRUCT
# define ZERO_STRUCT(x) memset((char *)&(x), 0, sizeof(x))
# endif
2006-09-17 09:11:57 +04:00
2014-06-03 17:10:19 +04:00
# ifndef ZERO_STRUCTP
# define ZERO_STRUCTP(x) do { \
if ( ( x ) ! = NULL ) \
memset ( ( char * ) ( x ) , 0 , sizeof ( * ( x ) ) ) ; \
} while ( 0 )
# endif
2018-05-02 16:57:38 +03:00
# ifndef SAFE_FREE
# define SAFE_FREE(x) do { if ((x) != NULL) {free(x); (x)=NULL;} } while(0)
# endif
2014-04-07 18:12:21 +04:00
# ifndef discard_const
# define discard_const(ptr) ((void *)((uintptr_t)(ptr)))
# endif
2013-11-22 08:15:13 +04:00
2014-04-07 18:12:21 +04:00
# ifndef discard_const_p
# define discard_const_p(type, ptr) ((type *)discard_const(ptr))
2005-03-28 05:00:39 +04:00
# endif
2017-11-07 14:29:51 +03:00
# define UNUSED(x) (void)(x)
2014-06-03 16:54:28 +04:00
# ifdef IPV6_PKTINFO
# ifndef IPV6_RECVPKTINFO
# define IPV6_RECVPKTINFO IPV6_PKTINFO
# endif /* IPV6_RECVPKTINFO */
# endif /* IPV6_PKTINFO */
2014-06-03 17:02:17 +04:00
/*
* On BSD IP_PKTINFO has a different name because during
* the time when they implemented it , there was no RFC .
* The name for IPv6 is the same as on Linux .
*/
# ifndef IP_PKTINFO
# ifdef IP_RECVDSTADDR
# define IP_PKTINFO IP_RECVDSTADDR
# endif
# endif
2021-02-09 10:56:42 +03:00
# define socket_wrapper_init_mutex(m) \
_socket_wrapper_init_mutex ( m , # m )
2017-11-07 14:29:51 +03:00
/* Add new global locks here please */
2021-02-09 10:56:42 +03:00
# define SWRAP_REINIT_ALL do { \
int ret ; \
ret = socket_wrapper_init_mutex ( & sockets_mutex ) ; \
if ( ret ! = 0 ) exit ( - 1 ) ; \
ret = socket_wrapper_init_mutex ( & socket_reset_mutex ) ; \
if ( ret ! = 0 ) exit ( - 1 ) ; \
ret = socket_wrapper_init_mutex ( & first_free_mutex ) ; \
if ( ret ! = 0 ) exit ( - 1 ) ; \
ret = socket_wrapper_init_mutex ( & sockets_si_global ) ; \
if ( ret ! = 0 ) exit ( - 1 ) ; \
ret = socket_wrapper_init_mutex ( & autobind_start_mutex ) ; \
if ( ret ! = 0 ) exit ( - 1 ) ; \
ret = socket_wrapper_init_mutex ( & pcap_dump_mutex ) ; \
if ( ret ! = 0 ) exit ( - 1 ) ; \
ret = socket_wrapper_init_mutex ( & mtu_update_mutex ) ; \
if ( ret ! = 0 ) exit ( - 1 ) ; \
} while ( 0 )
# define SWRAP_LOCK_ALL do { \
swrap_mutex_lock ( & sockets_mutex ) ; \
swrap_mutex_lock ( & socket_reset_mutex ) ; \
swrap_mutex_lock ( & first_free_mutex ) ; \
swrap_mutex_lock ( & sockets_si_global ) ; \
swrap_mutex_lock ( & autobind_start_mutex ) ; \
swrap_mutex_lock ( & pcap_dump_mutex ) ; \
swrap_mutex_lock ( & mtu_update_mutex ) ; \
} while ( 0 )
2017-11-07 14:29:51 +03:00
2021-02-09 10:56:42 +03:00
# define SWRAP_UNLOCK_ALL do { \
swrap_mutex_unlock ( & mtu_update_mutex ) ; \
swrap_mutex_unlock ( & pcap_dump_mutex ) ; \
swrap_mutex_unlock ( & autobind_start_mutex ) ; \
swrap_mutex_unlock ( & sockets_si_global ) ; \
swrap_mutex_unlock ( & first_free_mutex ) ; \
swrap_mutex_unlock ( & socket_reset_mutex ) ; \
swrap_mutex_unlock ( & sockets_mutex ) ; \
} while ( 0 )
2018-05-02 16:57:38 +03:00
# define SOCKET_INFO_CONTAINER(si) \
( struct socket_info_container * ) ( si )
# define SWRAP_LOCK_SI(si) do { \
struct socket_info_container * sic = SOCKET_INFO_CONTAINER ( si ) ; \
2021-02-09 10:56:42 +03:00
if ( sic ! = NULL ) { \
swrap_mutex_lock ( & sockets_si_global ) ; \
} else { \
abort ( ) ; \
} \
2018-05-02 16:57:38 +03:00
} while ( 0 )
# define SWRAP_UNLOCK_SI(si) do { \
struct socket_info_container * sic = SOCKET_INFO_CONTAINER ( si ) ; \
2021-02-09 10:56:42 +03:00
if ( sic ! = NULL ) { \
swrap_mutex_unlock ( & sockets_si_global ) ; \
} else { \
abort ( ) ; \
} \
2018-05-02 16:57:38 +03:00
} while ( 0 )
2017-11-07 14:29:51 +03:00
2014-04-07 18:12:21 +04:00
# if defined(HAVE_GETTIMEOFDAY_TZ) || defined(HAVE_GETTIMEOFDAY_TZ_VOID)
2006-10-05 15:39:59 +04:00
# define swrapGetTimeOfDay(tval) gettimeofday(tval,NULL)
# else
# define swrapGetTimeOfDay(tval) gettimeofday(tval)
# endif
2005-07-21 12:42:17 +04:00
/* we need to use a very terse format here as IRIX 6.4 silently
truncates names to 16 chars , so if we use a longer name then we
2014-04-07 18:12:21 +04:00
can ' t tell which port a packet came from with recvfrom ( )
2005-07-21 12:42:17 +04:00
with this format we have 8 chars left for the directory name
*/
2005-11-07 18:36:51 +03:00
# define SOCKET_FORMAT "%c%02X%04X"
# define SOCKET_TYPE_CHAR_TCP 'T'
# define SOCKET_TYPE_CHAR_UDP 'U'
2007-04-16 08:59:47 +04:00
# define SOCKET_TYPE_CHAR_TCP_V6 'X'
# define SOCKET_TYPE_CHAR_UDP_V6 'Y'
2005-07-21 12:42:17 +04:00
2014-04-07 18:12:21 +04:00
/*
2015-08-25 18:20:20 +03:00
* Set the packet MTU to 1500 bytes for stream sockets to make it it easier to
* format PCAP capture files ( as the caller will simply continue from here ) .
2014-04-07 18:12:21 +04:00
*/
2015-08-25 18:20:20 +03:00
# define SOCKET_WRAPPER_MTU_DEFAULT 1500
# define SOCKET_WRAPPER_MTU_MIN 512
# define SOCKET_WRAPPER_MTU_MAX 32768
2014-04-07 18:12:21 +04:00
# define SOCKET_MAX_SOCKETS 1024
2017-11-07 14:29:51 +03:00
/*
* Maximum number of socket_info structures that can
* be used . Can be overriden by the environment variable
* SOCKET_WRAPPER_MAX_SOCKETS .
*/
# define SOCKET_WRAPPER_MAX_SOCKETS_DEFAULT 65535
2018-05-02 16:57:38 +03:00
# define SOCKET_WRAPPER_MAX_SOCKETS_LIMIT 262140
2017-11-07 14:29:51 +03:00
2011-04-19 04:02:55 +04:00
/* This limit is to avoid broadcast sendto() needing to stat too many
* files . It may be raised ( with a performance cost ) to up to 254
* without changing the format above */
2017-11-07 14:29:51 +03:00
# define MAX_WRAPPED_INTERFACES 64
2006-09-26 15:31:14 +04:00
2014-10-02 09:09:33 +04:00
struct swrap_address {
socklen_t sa_socklen ;
union {
struct sockaddr s ;
struct sockaddr_in in ;
# ifdef HAVE_IPV6
struct sockaddr_in6 in6 ;
# endif
struct sockaddr_un un ;
struct sockaddr_storage ss ;
} sa ;
} ;
2021-02-09 10:56:42 +03:00
static int first_free ;
2017-11-07 14:29:51 +03:00
2014-04-07 18:12:21 +04:00
struct socket_info
{
2021-02-09 10:56:42 +03:00
/*
* Remember to update swrap_unix_scm_right_magic
* on any change .
*/
2014-04-07 18:12:21 +04:00
int family ;
int type ;
int protocol ;
int bound ;
int bcast ;
int is_server ;
int connected ;
int defer_connect ;
2014-06-03 16:54:28 +04:00
int pktinfo ;
2016-03-15 17:47:08 +03:00
int tcp_nodelay ;
2020-06-08 15:18:00 +03:00
int listening ;
2021-02-09 10:56:42 +03:00
int fd_passed ;
2014-04-07 18:12:21 +04:00
2014-10-02 09:16:25 +04:00
/* The unix path so we can unlink it on close() */
struct sockaddr_un un_addr ;
2014-04-07 18:12:21 +04:00
2014-10-02 09:17:10 +04:00
struct swrap_address bindname ;
struct swrap_address myname ;
struct swrap_address peername ;
2014-04-07 18:12:21 +04:00
struct {
unsigned long pck_snd ;
unsigned long pck_rcv ;
} io ;
} ;
2018-05-02 16:57:38 +03:00
struct socket_info_meta
{
unsigned int refcount ;
int next_free ;
2021-02-09 10:56:42 +03:00
/*
* As long as we don ' t use shared memory
* for the sockets array , we use
* sockets_si_global as a single mutex .
*
* pthread_mutex_t mutex ;
*/
2018-05-02 16:57:38 +03:00
} ;
struct socket_info_container
{
struct socket_info info ;
struct socket_info_meta meta ;
} ;
static struct socket_info_container * sockets ;
static size_t socket_info_max = 0 ;
2017-11-07 14:29:51 +03:00
2014-04-07 18:12:21 +04:00
/*
2018-05-02 16:57:38 +03:00
* Allocate the socket array always on the limit value . We want it to be
* at least bigger than the default so if we reach the limit we can
* still deal with duplicate fds pointing to the same socket_info .
2014-04-07 18:12:21 +04:00
*/
2018-05-02 16:57:38 +03:00
static size_t socket_fds_max = SOCKET_WRAPPER_MAX_SOCKETS_LIMIT ;
/* Hash table to map fds to corresponding socket_info index */
static int * socket_fds_idx ;
2017-11-07 14:29:51 +03:00
2018-05-02 16:57:38 +03:00
/* Mutex for syncronizing port selection during swrap_auto_bind() */
2021-02-09 10:56:42 +03:00
static pthread_mutex_t autobind_start_mutex = PTHREAD_MUTEX_INITIALIZER ;
2018-05-02 16:57:38 +03:00
/* Mutex to guard the initialization of array of socket_info structures */
2021-02-09 10:56:42 +03:00
static pthread_mutex_t sockets_mutex = PTHREAD_MUTEX_INITIALIZER ;
2018-05-02 16:57:38 +03:00
2021-02-17 14:57:01 +03:00
/* Mutex to guard the socket reset in swrap_remove_wrapper() */
2021-02-09 10:56:42 +03:00
static pthread_mutex_t socket_reset_mutex = PTHREAD_MUTEX_INITIALIZER ;
2018-05-02 16:57:38 +03:00
/* Mutex to synchronize access to first free index in socket_info array */
2021-02-09 10:56:42 +03:00
static pthread_mutex_t first_free_mutex = PTHREAD_MUTEX_INITIALIZER ;
/*
* Mutex to synchronize access to to socket_info structures
* We use a single global mutex in order to avoid leaking
* ~ 38 M copy on write memory per fork .
* max_sockets = 65535 * sizeof ( struct socket_info_container ) = 592 = 38796720
*/
static pthread_mutex_t sockets_si_global = PTHREAD_MUTEX_INITIALIZER ;
2018-05-02 16:57:38 +03:00
/* Mutex to synchronize access to packet capture dump file */
2021-02-09 10:56:42 +03:00
static pthread_mutex_t pcap_dump_mutex = PTHREAD_MUTEX_INITIALIZER ;
2018-05-02 16:57:38 +03:00
/* Mutex for synchronizing mtu value fetch*/
2021-02-09 10:56:42 +03:00
static pthread_mutex_t mtu_update_mutex = PTHREAD_MUTEX_INITIALIZER ;
2018-05-02 16:57:38 +03:00
2014-04-07 18:12:21 +04:00
/* Function prototypes */
2021-02-09 10:56:42 +03:00
# if ! defined(HAVE_CONSTRUCTOR_ATTRIBUTE) && defined(HAVE_PRAGMA_INIT)
/* xlC and other oldschool compilers support (only) this */
# pragma init (swrap_constructor)
# endif
2017-11-07 14:29:51 +03:00
void swrap_constructor ( void ) CONSTRUCTOR_ATTRIBUTE ;
2021-02-09 10:56:42 +03:00
# if ! defined(HAVE_DESTRUCTOR_ATTRIBUTE) && defined(HAVE_PRAGMA_FINI)
# pragma fini (swrap_destructor)
# endif
2017-11-07 14:29:51 +03:00
void swrap_destructor ( void ) DESTRUCTOR_ATTRIBUTE ;
2014-04-07 18:12:21 +04:00
2018-05-02 16:57:38 +03:00
# ifndef HAVE_GETPROGNAME
static const char * getprogname ( void )
{
# if defined(HAVE_PROGRAM_INVOCATION_SHORT_NAME)
return program_invocation_short_name ;
# elif defined(HAVE_GETEXECNAME)
return getexecname ( ) ;
# else
return NULL ;
# endif /* HAVE_PROGRAM_INVOCATION_SHORT_NAME */
}
# endif /* HAVE_GETPROGNAME */
2014-10-02 09:23:53 +04:00
static void swrap_log ( enum swrap_dbglvl_e dbglvl , const char * func , const char * format , . . . ) PRINTF_ATTRIBUTE ( 3 , 4 ) ;
# define SWRAP_LOG(dbglvl, ...) swrap_log((dbglvl), __func__, __VA_ARGS__)
2014-04-07 18:12:21 +04:00
2014-10-02 09:23:53 +04:00
static void swrap_log ( enum swrap_dbglvl_e dbglvl ,
const char * func ,
const char * format , . . . )
2014-04-07 18:12:21 +04:00
{
char buffer [ 1024 ] ;
va_list va ;
const char * d ;
unsigned int lvl = 0 ;
2017-11-07 14:29:51 +03:00
const char * prefix = " SWRAP " ;
2018-05-02 16:57:38 +03:00
const char * progname = getprogname ( ) ;
2014-04-07 18:12:21 +04:00
d = getenv ( " SOCKET_WRAPPER_DEBUGLEVEL " ) ;
if ( d ! = NULL ) {
lvl = atoi ( d ) ;
}
2017-11-07 14:29:51 +03:00
if ( lvl < dbglvl ) {
return ;
}
2014-04-07 18:12:21 +04:00
va_start ( va , format ) ;
vsnprintf ( buffer , sizeof ( buffer ) , format , va ) ;
va_end ( va ) ;
2017-11-07 14:29:51 +03:00
switch ( dbglvl ) {
case SWRAP_LOG_ERROR :
prefix = " SWRAP_ERROR " ;
break ;
case SWRAP_LOG_WARN :
prefix = " SWRAP_WARN " ;
break ;
case SWRAP_LOG_DEBUG :
prefix = " SWRAP_DEBUG " ;
break ;
case SWRAP_LOG_TRACE :
prefix = " SWRAP_TRACE " ;
break ;
2014-04-07 18:12:21 +04:00
}
2017-11-07 14:29:51 +03:00
2018-05-02 16:57:38 +03:00
if ( progname = = NULL ) {
progname = " <unknown> " ;
}
2017-11-07 14:29:51 +03:00
fprintf ( stderr ,
2018-05-02 16:57:38 +03:00
" %s[%s (%u)] - %s: %s \n " ,
prefix ,
progname ,
( unsigned int ) getpid ( ) ,
func ,
buffer ) ;
2014-04-07 18:12:21 +04:00
}
/*********************************************************
* SWRAP LOADING LIBC FUNCTIONS
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
# include <dlfcn.h>
2016-05-20 11:20:28 +03:00
# ifdef HAVE_ACCEPT4
2017-11-07 14:29:51 +03:00
typedef int ( * __libc_accept4 ) ( int sockfd ,
struct sockaddr * addr ,
socklen_t * addrlen ,
int flags ) ;
2016-05-20 11:20:28 +03:00
# else
2017-11-07 14:29:51 +03:00
typedef int ( * __libc_accept ) ( int sockfd ,
struct sockaddr * addr ,
socklen_t * addrlen ) ;
# endif
typedef int ( * __libc_bind ) ( int sockfd ,
const struct sockaddr * addr ,
socklen_t addrlen ) ;
typedef int ( * __libc_close ) ( int fd ) ;
2021-02-17 14:57:01 +03:00
# ifdef HAVE___CLOSE_NOCANCEL
typedef int ( * __libc___close_nocancel ) ( int fd ) ;
# endif
2017-11-07 14:29:51 +03:00
typedef int ( * __libc_connect ) ( int sockfd ,
const struct sockaddr * addr ,
socklen_t addrlen ) ;
typedef int ( * __libc_dup ) ( int fd ) ;
typedef int ( * __libc_dup2 ) ( int oldfd , int newfd ) ;
typedef int ( * __libc_fcntl ) ( int fd , int cmd , . . . ) ;
typedef FILE * ( * __libc_fopen ) ( const char * name , const char * mode ) ;
# ifdef HAVE_FOPEN64
typedef FILE * ( * __libc_fopen64 ) ( const char * name , const char * mode ) ;
2016-05-20 11:20:28 +03:00
# endif
2014-04-07 18:12:21 +04:00
# ifdef HAVE_EVENTFD
2017-11-07 14:29:51 +03:00
typedef int ( * __libc_eventfd ) ( int count , int flags ) ;
2014-04-07 18:12:21 +04:00
# endif
2017-11-07 14:29:51 +03:00
typedef int ( * __libc_getpeername ) ( int sockfd ,
struct sockaddr * addr ,
socklen_t * addrlen ) ;
typedef int ( * __libc_getsockname ) ( int sockfd ,
struct sockaddr * addr ,
socklen_t * addrlen ) ;
typedef int ( * __libc_getsockopt ) ( int sockfd ,
2014-04-07 18:12:21 +04:00
int level ,
int optname ,
void * optval ,
socklen_t * optlen ) ;
2017-11-07 14:29:51 +03:00
typedef int ( * __libc_ioctl ) ( int d , unsigned long int request , . . . ) ;
typedef int ( * __libc_listen ) ( int sockfd , int backlog ) ;
typedef int ( * __libc_open ) ( const char * pathname , int flags , . . . ) ;
# ifdef HAVE_OPEN64
typedef int ( * __libc_open64 ) ( const char * pathname , int flags , . . . ) ;
# endif /* HAVE_OPEN64 */
typedef int ( * __libc_openat ) ( int dirfd , const char * path , int flags , . . . ) ;
typedef int ( * __libc_pipe ) ( int pipefd [ 2 ] ) ;
typedef int ( * __libc_read ) ( int fd , void * buf , size_t count ) ;
typedef ssize_t ( * __libc_readv ) ( int fd , const struct iovec * iov , int iovcnt ) ;
typedef int ( * __libc_recv ) ( int sockfd , void * buf , size_t len , int flags ) ;
typedef int ( * __libc_recvfrom ) ( int sockfd ,
2014-04-07 18:12:21 +04:00
void * buf ,
size_t len ,
int flags ,
struct sockaddr * src_addr ,
socklen_t * addrlen ) ;
2017-11-07 14:29:51 +03:00
typedef int ( * __libc_recvmsg ) ( int sockfd , const struct msghdr * msg , int flags ) ;
typedef int ( * __libc_send ) ( int sockfd , const void * buf , size_t len , int flags ) ;
typedef int ( * __libc_sendmsg ) ( int sockfd , const struct msghdr * msg , int flags ) ;
typedef int ( * __libc_sendto ) ( int sockfd ,
2014-04-07 18:12:21 +04:00
const void * buf ,
size_t len ,
int flags ,
const struct sockaddr * dst_addr ,
socklen_t addrlen ) ;
2017-11-07 14:29:51 +03:00
typedef int ( * __libc_setsockopt ) ( int sockfd ,
2014-04-07 18:12:21 +04:00
int level ,
int optname ,
const void * optval ,
socklen_t optlen ) ;
# ifdef HAVE_SIGNALFD
2017-11-07 14:29:51 +03:00
typedef int ( * __libc_signalfd ) ( int fd , const sigset_t * mask , int flags ) ;
2014-04-07 18:12:21 +04:00
# endif
2017-11-07 14:29:51 +03:00
typedef int ( * __libc_socket ) ( int domain , int type , int protocol ) ;
typedef int ( * __libc_socketpair ) ( int domain , int type , int protocol , int sv [ 2 ] ) ;
2014-04-07 18:12:21 +04:00
# ifdef HAVE_TIMERFD_CREATE
2017-11-07 14:29:51 +03:00
typedef int ( * __libc_timerfd_create ) ( int clockid , int flags ) ;
2014-04-07 18:12:21 +04:00
# endif
2017-11-07 14:29:51 +03:00
typedef ssize_t ( * __libc_write ) ( int fd , const void * buf , size_t count ) ;
typedef ssize_t ( * __libc_writev ) ( int fd , const struct iovec * iov , int iovcnt ) ;
2014-04-07 18:12:21 +04:00
2017-11-07 14:29:51 +03:00
# define SWRAP_SYMBOL_ENTRY(i) \
union { \
__libc_ # # i f ; \
void * obj ; \
} _libc_ # # i
2014-04-07 18:12:21 +04:00
2017-11-07 14:29:51 +03:00
struct swrap_libc_symbols {
# ifdef HAVE_ACCEPT4
SWRAP_SYMBOL_ENTRY ( accept4 ) ;
# else
SWRAP_SYMBOL_ENTRY ( accept ) ;
# endif
SWRAP_SYMBOL_ENTRY ( bind ) ;
SWRAP_SYMBOL_ENTRY ( close ) ;
2021-02-17 14:57:01 +03:00
# ifdef HAVE___CLOSE_NOCANCEL
SWRAP_SYMBOL_ENTRY ( __close_nocancel ) ;
# endif
2017-11-07 14:29:51 +03:00
SWRAP_SYMBOL_ENTRY ( connect ) ;
SWRAP_SYMBOL_ENTRY ( dup ) ;
SWRAP_SYMBOL_ENTRY ( dup2 ) ;
SWRAP_SYMBOL_ENTRY ( fcntl ) ;
SWRAP_SYMBOL_ENTRY ( fopen ) ;
# ifdef HAVE_FOPEN64
SWRAP_SYMBOL_ENTRY ( fopen64 ) ;
# endif
# ifdef HAVE_EVENTFD
SWRAP_SYMBOL_ENTRY ( eventfd ) ;
# endif
SWRAP_SYMBOL_ENTRY ( getpeername ) ;
SWRAP_SYMBOL_ENTRY ( getsockname ) ;
SWRAP_SYMBOL_ENTRY ( getsockopt ) ;
SWRAP_SYMBOL_ENTRY ( ioctl ) ;
SWRAP_SYMBOL_ENTRY ( listen ) ;
SWRAP_SYMBOL_ENTRY ( open ) ;
# ifdef HAVE_OPEN64
SWRAP_SYMBOL_ENTRY ( open64 ) ;
# endif
SWRAP_SYMBOL_ENTRY ( openat ) ;
SWRAP_SYMBOL_ENTRY ( pipe ) ;
SWRAP_SYMBOL_ENTRY ( read ) ;
SWRAP_SYMBOL_ENTRY ( readv ) ;
SWRAP_SYMBOL_ENTRY ( recv ) ;
SWRAP_SYMBOL_ENTRY ( recvfrom ) ;
SWRAP_SYMBOL_ENTRY ( recvmsg ) ;
SWRAP_SYMBOL_ENTRY ( send ) ;
SWRAP_SYMBOL_ENTRY ( sendmsg ) ;
SWRAP_SYMBOL_ENTRY ( sendto ) ;
SWRAP_SYMBOL_ENTRY ( setsockopt ) ;
# ifdef HAVE_SIGNALFD
SWRAP_SYMBOL_ENTRY ( signalfd ) ;
# endif
SWRAP_SYMBOL_ENTRY ( socket ) ;
SWRAP_SYMBOL_ENTRY ( socketpair ) ;
# ifdef HAVE_TIMERFD_CREATE
SWRAP_SYMBOL_ENTRY ( timerfd_create ) ;
# endif
SWRAP_SYMBOL_ENTRY ( write ) ;
SWRAP_SYMBOL_ENTRY ( writev ) ;
} ;
2014-04-07 18:12:21 +04:00
2017-11-07 14:29:51 +03:00
struct swrap {
struct {
void * handle ;
void * socket_handle ;
struct swrap_libc_symbols symbols ;
} libc ;
2014-04-07 18:12:21 +04:00
} ;
static struct swrap swrap ;
/* prototypes */
2019-03-21 12:02:54 +03:00
static char * socket_wrapper_dir ( void ) ;
2014-04-07 18:12:21 +04:00
# define LIBC_NAME "libc.so"
enum swrap_lib {
SWRAP_LIBC ,
SWRAP_LIBSOCKET ,
} ;
static const char * swrap_str_lib ( enum swrap_lib lib )
{
switch ( lib ) {
case SWRAP_LIBC :
return " libc " ;
case SWRAP_LIBSOCKET :
return " libsocket " ;
}
/* Compiler would warn us about unhandled enum value if we get here */
return " unknown " ;
}
static void * swrap_load_lib_handle ( enum swrap_lib lib )
{
int flags = RTLD_LAZY ;
void * handle = NULL ;
int i ;
# ifdef RTLD_DEEPBIND
2019-03-21 12:02:54 +03:00
const char * env_preload = getenv ( " LD_PRELOAD " ) ;
const char * env_deepbind = getenv ( " SOCKET_WRAPPER_DISABLE_DEEPBIND " ) ;
bool enable_deepbind = true ;
2018-05-02 16:57:38 +03:00
/* Don't do a deepbind if we run with libasan */
2019-03-21 12:02:54 +03:00
if ( env_preload ! = NULL & & strlen ( env_preload ) < 1024 ) {
const char * p = strstr ( env_preload , " libasan.so " ) ;
if ( p ! = NULL ) {
enable_deepbind = false ;
2018-05-02 16:57:38 +03:00
}
}
2019-03-21 12:02:54 +03:00
if ( env_deepbind ! = NULL & & strlen ( env_deepbind ) > = 1 ) {
enable_deepbind = false ;
}
if ( enable_deepbind ) {
flags | = RTLD_DEEPBIND ;
}
2014-04-07 18:12:21 +04:00
# endif
switch ( lib ) {
case SWRAP_LIBSOCKET :
# ifdef HAVE_LIBSOCKET
2017-11-07 14:29:51 +03:00
handle = swrap . libc . socket_handle ;
2014-04-07 18:12:21 +04:00
if ( handle = = NULL ) {
2015-02-23 19:15:12 +03:00
for ( i = 10 ; i > = 0 ; i - - ) {
2014-04-07 18:12:21 +04:00
char soname [ 256 ] = { 0 } ;
snprintf ( soname , sizeof ( soname ) , " libsocket.so.%d " , i ) ;
handle = dlopen ( soname , flags ) ;
2015-02-23 19:15:12 +03:00
if ( handle ! = NULL ) {
break ;
}
2014-04-07 18:12:21 +04:00
}
2017-11-07 14:29:51 +03:00
swrap . libc . socket_handle = handle ;
2014-04-07 18:12:21 +04:00
}
break ;
# endif
case SWRAP_LIBC :
2017-11-07 14:29:51 +03:00
handle = swrap . libc . handle ;
2014-06-03 16:50:05 +04:00
# ifdef LIBC_SO
if ( handle = = NULL ) {
handle = dlopen ( LIBC_SO , flags ) ;
2014-06-03 16:59:21 +04:00
2017-11-07 14:29:51 +03:00
swrap . libc . handle = handle ;
2014-06-03 16:50:05 +04:00
}
# endif
2014-04-07 18:12:21 +04:00
if ( handle = = NULL ) {
2015-02-23 19:15:12 +03:00
for ( i = 10 ; i > = 0 ; i - - ) {
2014-04-07 18:12:21 +04:00
char soname [ 256 ] = { 0 } ;
snprintf ( soname , sizeof ( soname ) , " libc.so.%d " , i ) ;
handle = dlopen ( soname , flags ) ;
2015-02-23 19:15:12 +03:00
if ( handle ! = NULL ) {
break ;
}
2014-04-07 18:12:21 +04:00
}
2017-11-07 14:29:51 +03:00
swrap . libc . handle = handle ;
2014-04-07 18:12:21 +04:00
}
break ;
}
if ( handle = = NULL ) {
2014-05-08 16:07:16 +04:00
# ifdef RTLD_NEXT
2017-11-07 14:29:51 +03:00
handle = swrap . libc . handle = swrap . libc . socket_handle = RTLD_NEXT ;
2014-05-08 16:07:16 +04:00
# else
2014-04-07 18:12:21 +04:00
SWRAP_LOG ( SWRAP_LOG_ERROR ,
2020-06-08 15:18:00 +03:00
" Failed to dlopen library: %s " ,
2014-04-07 18:12:21 +04:00
dlerror ( ) ) ;
exit ( - 1 ) ;
2014-05-08 16:07:16 +04:00
# endif
2014-04-07 18:12:21 +04:00
}
return handle ;
}
2017-11-07 14:29:51 +03:00
static void * _swrap_bind_symbol ( enum swrap_lib lib , const char * fn_name )
2014-04-07 18:12:21 +04:00
{
void * handle ;
void * func ;
handle = swrap_load_lib_handle ( lib ) ;
func = dlsym ( handle , fn_name ) ;
if ( func = = NULL ) {
SWRAP_LOG ( SWRAP_LOG_ERROR ,
2020-06-08 15:18:00 +03:00
" Failed to find %s: %s " ,
2017-11-07 14:29:51 +03:00
fn_name ,
dlerror ( ) ) ;
2014-04-07 18:12:21 +04:00
exit ( - 1 ) ;
}
SWRAP_LOG ( SWRAP_LOG_TRACE ,
2017-11-07 14:29:51 +03:00
" Loaded %s from %s " ,
fn_name ,
swrap_str_lib ( lib ) ) ;
2014-04-07 18:12:21 +04:00
return func ;
}
2021-02-09 10:56:42 +03:00
# define swrap_mutex_lock(m) _swrap_mutex_lock(m, #m, __func__, __LINE__)
static void _swrap_mutex_lock ( pthread_mutex_t * mutex , const char * name , const char * caller , unsigned line )
2018-05-02 16:57:38 +03:00
{
int ret ;
ret = pthread_mutex_lock ( mutex ) ;
if ( ret ! = 0 ) {
2021-02-09 10:56:42 +03:00
SWRAP_LOG ( SWRAP_LOG_ERROR , " PID(%d):PPID(%d): %s(%u): Couldn't lock pthread mutex(%s) - %s " ,
getpid ( ) , getppid ( ) , caller , line , name , strerror ( ret ) ) ;
abort ( ) ;
2018-05-02 16:57:38 +03:00
}
}
2021-02-09 10:56:42 +03:00
# define swrap_mutex_unlock(m) _swrap_mutex_unlock(m, #m, __func__, __LINE__)
static void _swrap_mutex_unlock ( pthread_mutex_t * mutex , const char * name , const char * caller , unsigned line )
2018-05-02 16:57:38 +03:00
{
int ret ;
ret = pthread_mutex_unlock ( mutex ) ;
if ( ret ! = 0 ) {
2021-02-09 10:56:42 +03:00
SWRAP_LOG ( SWRAP_LOG_ERROR , " PID(%d):PPID(%d): %s(%u): Couldn't unlock pthread mutex(%s) - %s " ,
getpid ( ) , getppid ( ) , caller , line , name , strerror ( ret ) ) ;
abort ( ) ;
2018-05-02 16:57:38 +03:00
}
}
/*
* These macros have a thread race condition on purpose !
*
* This is an optimization to avoid locking each time we check if the symbol is
* bound .
*/
2021-02-09 10:56:42 +03:00
# define _swrap_bind_symbol_generic(lib, sym_name) do { \
swrap . libc . symbols . _libc_ # # sym_name . obj = \
_swrap_bind_symbol ( lib , # sym_name ) ; \
} while ( 0 ) ;
2017-11-07 14:29:51 +03:00
# define swrap_bind_symbol_libc(sym_name) \
2021-02-09 10:56:42 +03:00
_swrap_bind_symbol_generic ( SWRAP_LIBC , sym_name )
2014-04-07 18:12:21 +04:00
2017-11-07 14:29:51 +03:00
# define swrap_bind_symbol_libsocket(sym_name) \
2021-02-09 10:56:42 +03:00
_swrap_bind_symbol_generic ( SWRAP_LIBSOCKET , sym_name )
2014-04-07 18:12:21 +04:00
2021-02-09 10:56:42 +03:00
static void swrap_bind_symbol_all ( void ) ;
2017-11-07 14:29:51 +03:00
/****************************************************************************
* IMPORTANT
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
2014-04-07 18:12:21 +04:00
*
2017-11-07 14:29:51 +03:00
* Functions especially from libc need to be loaded individually , you can ' t
* load all at once or gdb will segfault at startup . The same applies to
* valgrind and has probably something todo with with the linker . So we need
* load each function at the point it is called the first time .
*
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2016-05-20 11:20:28 +03:00
# ifdef HAVE_ACCEPT4
static int libc_accept4 ( int sockfd ,
struct sockaddr * addr ,
socklen_t * addrlen ,
int flags )
{
2021-02-09 10:56:42 +03:00
swrap_bind_symbol_all ( ) ;
2016-05-20 11:20:28 +03:00
2017-11-07 14:29:51 +03:00
return swrap . libc . symbols . _libc_accept4 . f ( sockfd , addr , addrlen , flags ) ;
2016-05-20 11:20:28 +03:00
}
# else /* HAVE_ACCEPT4 */
2014-04-07 18:12:21 +04:00
static int libc_accept ( int sockfd , struct sockaddr * addr , socklen_t * addrlen )
{
2021-02-09 10:56:42 +03:00
swrap_bind_symbol_all ( ) ;
2014-04-07 18:12:21 +04:00
2017-11-07 14:29:51 +03:00
return swrap . libc . symbols . _libc_accept . f ( sockfd , addr , addrlen ) ;
2014-04-07 18:12:21 +04:00
}
2016-05-20 11:20:28 +03:00
# endif /* HAVE_ACCEPT4 */
2014-04-07 18:12:21 +04:00
static int libc_bind ( int sockfd ,
const struct sockaddr * addr ,
socklen_t addrlen )
{
2021-02-09 10:56:42 +03:00
swrap_bind_symbol_all ( ) ;
2014-04-07 18:12:21 +04:00
2017-11-07 14:29:51 +03:00
return swrap . libc . symbols . _libc_bind . f ( sockfd , addr , addrlen ) ;
2014-04-07 18:12:21 +04:00
}
static int libc_close ( int fd )
{
2021-02-09 10:56:42 +03:00
swrap_bind_symbol_all ( ) ;
2014-04-07 18:12:21 +04:00
2017-11-07 14:29:51 +03:00
return swrap . libc . symbols . _libc_close . f ( fd ) ;
2014-04-07 18:12:21 +04:00
}
2021-02-17 14:57:01 +03:00
# ifdef HAVE___CLOSE_NOCANCEL
static int libc___close_nocancel ( int fd )
{
swrap_bind_symbol_all ( ) ;
return swrap . libc . symbols . _libc___close_nocancel . f ( fd ) ;
}
# endif /* HAVE___CLOSE_NOCANCEL */
2014-04-07 18:12:21 +04:00
static int libc_connect ( int sockfd ,
const struct sockaddr * addr ,
socklen_t addrlen )
{
2021-02-09 10:56:42 +03:00
swrap_bind_symbol_all ( ) ;
2014-04-07 18:12:21 +04:00
2017-11-07 14:29:51 +03:00
return swrap . libc . symbols . _libc_connect . f ( sockfd , addr , addrlen ) ;
2014-04-07 18:12:21 +04:00
}
static int libc_dup ( int fd )
{
2021-02-09 10:56:42 +03:00
swrap_bind_symbol_all ( ) ;
2014-04-07 18:12:21 +04:00
2017-11-07 14:29:51 +03:00
return swrap . libc . symbols . _libc_dup . f ( fd ) ;
2014-04-07 18:12:21 +04:00
}
static int libc_dup2 ( int oldfd , int newfd )
{
2021-02-09 10:56:42 +03:00
swrap_bind_symbol_all ( ) ;
2014-04-07 18:12:21 +04:00
2017-11-07 14:29:51 +03:00
return swrap . libc . symbols . _libc_dup2 . f ( oldfd , newfd ) ;
2014-04-07 18:12:21 +04:00
}
# ifdef HAVE_EVENTFD
static int libc_eventfd ( int count , int flags )
{
2021-02-09 10:56:42 +03:00
swrap_bind_symbol_all ( ) ;
2014-04-07 18:12:21 +04:00
2017-11-07 14:29:51 +03:00
return swrap . libc . symbols . _libc_eventfd . f ( count , flags ) ;
2014-04-07 18:12:21 +04:00
}
# endif
2015-02-23 19:16:00 +03:00
DO_NOT_SANITIZE_ADDRESS_ATTRIBUTE
2014-10-02 09:24:27 +04:00
static int libc_vfcntl ( int fd , int cmd , va_list ap )
{
2017-11-07 14:29:51 +03:00
void * arg ;
2014-10-02 09:24:27 +04:00
int rc ;
2021-02-09 10:56:42 +03:00
swrap_bind_symbol_all ( ) ;
2014-10-02 09:24:27 +04:00
2017-11-07 14:29:51 +03:00
arg = va_arg ( ap , void * ) ;
2014-10-02 09:24:27 +04:00
2017-11-07 14:29:51 +03:00
rc = swrap . libc . symbols . _libc_fcntl . f ( fd , cmd , arg ) ;
2014-10-02 09:24:27 +04:00
return rc ;
}
2014-04-07 18:12:21 +04:00
static int libc_getpeername ( int sockfd ,
struct sockaddr * addr ,
socklen_t * addrlen )
{
2021-02-09 10:56:42 +03:00
swrap_bind_symbol_all ( ) ;
2014-04-07 18:12:21 +04:00
2017-11-07 14:29:51 +03:00
return swrap . libc . symbols . _libc_getpeername . f ( sockfd , addr , addrlen ) ;
2014-04-07 18:12:21 +04:00
}
static int libc_getsockname ( int sockfd ,
struct sockaddr * addr ,
socklen_t * addrlen )
{
2021-02-09 10:56:42 +03:00
swrap_bind_symbol_all ( ) ;
2014-04-07 18:12:21 +04:00
2017-11-07 14:29:51 +03:00
return swrap . libc . symbols . _libc_getsockname . f ( sockfd , addr , addrlen ) ;
2014-04-07 18:12:21 +04:00
}
static int libc_getsockopt ( int sockfd ,
int level ,
int optname ,
void * optval ,
socklen_t * optlen )
{
2021-02-09 10:56:42 +03:00
swrap_bind_symbol_all ( ) ;
2014-04-07 18:12:21 +04:00
2017-11-07 14:29:51 +03:00
return swrap . libc . symbols . _libc_getsockopt . f ( sockfd ,
level ,
optname ,
optval ,
optlen ) ;
2014-04-07 18:12:21 +04:00
}
2015-02-23 19:16:00 +03:00
DO_NOT_SANITIZE_ADDRESS_ATTRIBUTE
2014-04-07 18:12:21 +04:00
static int libc_vioctl ( int d , unsigned long int request , va_list ap )
{
2017-11-07 14:29:51 +03:00
void * arg ;
2014-04-07 18:12:21 +04:00
int rc ;
2021-02-09 10:56:42 +03:00
swrap_bind_symbol_all ( ) ;
2014-04-07 18:12:21 +04:00
2017-11-07 14:29:51 +03:00
arg = va_arg ( ap , void * ) ;
2014-04-07 18:12:21 +04:00
2017-11-07 14:29:51 +03:00
rc = swrap . libc . symbols . _libc_ioctl . f ( d , request , arg ) ;
2014-04-07 18:12:21 +04:00
return rc ;
}
static int libc_listen ( int sockfd , int backlog )
{
2021-02-09 10:56:42 +03:00
swrap_bind_symbol_all ( ) ;
2014-04-07 18:12:21 +04:00
2017-11-07 14:29:51 +03:00
return swrap . libc . symbols . _libc_listen . f ( sockfd , backlog ) ;
2014-04-07 18:12:21 +04:00
}
2014-10-02 09:18:48 +04:00
static FILE * libc_fopen ( const char * name , const char * mode )
{
2021-02-09 10:56:42 +03:00
swrap_bind_symbol_all ( ) ;
2014-10-02 09:18:48 +04:00
2017-11-07 14:29:51 +03:00
return swrap . libc . symbols . _libc_fopen . f ( name , mode ) ;
2014-10-02 09:18:48 +04:00
}
2017-11-07 14:29:51 +03:00
# ifdef HAVE_FOPEN64
static FILE * libc_fopen64 ( const char * name , const char * mode )
{
2021-02-09 10:56:42 +03:00
swrap_bind_symbol_all ( ) ;
2017-11-07 14:29:51 +03:00
return swrap . libc . symbols . _libc_fopen64 . f ( name , mode ) ;
}
# endif /* HAVE_FOPEN64 */
2014-04-07 18:12:21 +04:00
static int libc_vopen ( const char * pathname , int flags , va_list ap )
{
2017-11-07 14:29:51 +03:00
int mode = 0 ;
2014-04-07 18:12:21 +04:00
int fd ;
2021-02-09 10:56:42 +03:00
swrap_bind_symbol_all ( ) ;
2014-04-07 18:12:21 +04:00
2017-11-07 14:29:51 +03:00
if ( flags & O_CREAT ) {
mode = va_arg ( ap , int ) ;
}
fd = swrap . libc . symbols . _libc_open . f ( pathname , flags , ( mode_t ) mode ) ;
2014-04-07 18:12:21 +04:00
return fd ;
}
2014-05-08 16:05:30 +04:00
static int libc_open ( const char * pathname , int flags , . . . )
{
va_list ap ;
int fd ;
va_start ( ap , flags ) ;
fd = libc_vopen ( pathname , flags , ap ) ;
va_end ( ap ) ;
return fd ;
}
2017-11-07 14:29:51 +03:00
# ifdef HAVE_OPEN64
static int libc_vopen64 ( const char * pathname , int flags , va_list ap )
{
int mode = 0 ;
int fd ;
2021-02-09 10:56:42 +03:00
swrap_bind_symbol_all ( ) ;
2017-11-07 14:29:51 +03:00
if ( flags & O_CREAT ) {
mode = va_arg ( ap , int ) ;
}
fd = swrap . libc . symbols . _libc_open64 . f ( pathname , flags , ( mode_t ) mode ) ;
return fd ;
}
# endif /* HAVE_OPEN64 */
static int libc_vopenat ( int dirfd , const char * path , int flags , va_list ap )
{
int mode = 0 ;
int fd ;
2021-02-09 10:56:42 +03:00
swrap_bind_symbol_all ( ) ;
2017-11-07 14:29:51 +03:00
if ( flags & O_CREAT ) {
mode = va_arg ( ap , int ) ;
}
fd = swrap . libc . symbols . _libc_openat . f ( dirfd ,
path ,
flags ,
( mode_t ) mode ) ;
return fd ;
}
#if 0
static int libc_openat ( int dirfd , const char * path , int flags , . . . )
{
va_list ap ;
int fd ;
va_start ( ap , flags ) ;
fd = libc_vopenat ( dirfd , path , flags , ap ) ;
va_end ( ap ) ;
return fd ;
}
# endif
2014-04-07 18:12:21 +04:00
static int libc_pipe ( int pipefd [ 2 ] )
{
2021-02-09 10:56:42 +03:00
swrap_bind_symbol_all ( ) ;
2014-04-07 18:12:21 +04:00
2017-11-07 14:29:51 +03:00
return swrap . libc . symbols . _libc_pipe . f ( pipefd ) ;
2014-04-07 18:12:21 +04:00
}
static int libc_read ( int fd , void * buf , size_t count )
{
2021-02-09 10:56:42 +03:00
swrap_bind_symbol_all ( ) ;
2014-04-07 18:12:21 +04:00
2017-11-07 14:29:51 +03:00
return swrap . libc . symbols . _libc_read . f ( fd , buf , count ) ;
2014-04-07 18:12:21 +04:00
}
static ssize_t libc_readv ( int fd , const struct iovec * iov , int iovcnt )
{
2021-02-09 10:56:42 +03:00
swrap_bind_symbol_all ( ) ;
2014-04-07 18:12:21 +04:00
2017-11-07 14:29:51 +03:00
return swrap . libc . symbols . _libc_readv . f ( fd , iov , iovcnt ) ;
2014-04-07 18:12:21 +04:00
}
static int libc_recv ( int sockfd , void * buf , size_t len , int flags )
{
2021-02-09 10:56:42 +03:00
swrap_bind_symbol_all ( ) ;
2014-04-07 18:12:21 +04:00
2017-11-07 14:29:51 +03:00
return swrap . libc . symbols . _libc_recv . f ( sockfd , buf , len , flags ) ;
2014-04-07 18:12:21 +04:00
}
static int libc_recvfrom ( int sockfd ,
void * buf ,
size_t len ,
int flags ,
struct sockaddr * src_addr ,
socklen_t * addrlen )
{
2021-02-09 10:56:42 +03:00
swrap_bind_symbol_all ( ) ;
2014-04-07 18:12:21 +04:00
2017-11-07 14:29:51 +03:00
return swrap . libc . symbols . _libc_recvfrom . f ( sockfd ,
buf ,
len ,
flags ,
src_addr ,
addrlen ) ;
2014-04-07 18:12:21 +04:00
}
static int libc_recvmsg ( int sockfd , struct msghdr * msg , int flags )
{
2021-02-09 10:56:42 +03:00
swrap_bind_symbol_all ( ) ;
2014-04-07 18:12:21 +04:00
2017-11-07 14:29:51 +03:00
return swrap . libc . symbols . _libc_recvmsg . f ( sockfd , msg , flags ) ;
2014-04-07 18:12:21 +04:00
}
static int libc_send ( int sockfd , const void * buf , size_t len , int flags )
{
2021-02-09 10:56:42 +03:00
swrap_bind_symbol_all ( ) ;
2014-04-07 18:12:21 +04:00
2017-11-07 14:29:51 +03:00
return swrap . libc . symbols . _libc_send . f ( sockfd , buf , len , flags ) ;
2014-04-07 18:12:21 +04:00
}
static int libc_sendmsg ( int sockfd , const struct msghdr * msg , int flags )
{
2021-02-09 10:56:42 +03:00
swrap_bind_symbol_all ( ) ;
2014-04-07 18:12:21 +04:00
2017-11-07 14:29:51 +03:00
return swrap . libc . symbols . _libc_sendmsg . f ( sockfd , msg , flags ) ;
2014-04-07 18:12:21 +04:00
}
static int libc_sendto ( int sockfd ,
const void * buf ,
size_t len ,
int flags ,
const struct sockaddr * dst_addr ,
socklen_t addrlen )
{
2021-02-09 10:56:42 +03:00
swrap_bind_symbol_all ( ) ;
2014-04-07 18:12:21 +04:00
2017-11-07 14:29:51 +03:00
return swrap . libc . symbols . _libc_sendto . f ( sockfd ,
buf ,
len ,
flags ,
dst_addr ,
addrlen ) ;
2014-04-07 18:12:21 +04:00
}
static int libc_setsockopt ( int sockfd ,
int level ,
int optname ,
const void * optval ,
socklen_t optlen )
{
2021-02-09 10:56:42 +03:00
swrap_bind_symbol_all ( ) ;
2014-04-07 18:12:21 +04:00
2017-11-07 14:29:51 +03:00
return swrap . libc . symbols . _libc_setsockopt . f ( sockfd ,
level ,
optname ,
optval ,
optlen ) ;
2014-04-07 18:12:21 +04:00
}
# ifdef HAVE_SIGNALFD
static int libc_signalfd ( int fd , const sigset_t * mask , int flags )
{
2021-02-09 10:56:42 +03:00
swrap_bind_symbol_all ( ) ;
2014-04-07 18:12:21 +04:00
2017-11-07 14:29:51 +03:00
return swrap . libc . symbols . _libc_signalfd . f ( fd , mask , flags ) ;
2014-04-07 18:12:21 +04:00
}
# endif
static int libc_socket ( int domain , int type , int protocol )
{
2021-02-09 10:56:42 +03:00
swrap_bind_symbol_all ( ) ;
2014-04-07 18:12:21 +04:00
2017-11-07 14:29:51 +03:00
return swrap . libc . symbols . _libc_socket . f ( domain , type , protocol ) ;
2014-04-07 18:12:21 +04:00
}
static int libc_socketpair ( int domain , int type , int protocol , int sv [ 2 ] )
{
2021-02-09 10:56:42 +03:00
swrap_bind_symbol_all ( ) ;
2014-04-07 18:12:21 +04:00
2017-11-07 14:29:51 +03:00
return swrap . libc . symbols . _libc_socketpair . f ( domain , type , protocol , sv ) ;
2014-04-07 18:12:21 +04:00
}
# ifdef HAVE_TIMERFD_CREATE
static int libc_timerfd_create ( int clockid , int flags )
{
2021-02-09 10:56:42 +03:00
swrap_bind_symbol_all ( ) ;
2014-04-07 18:12:21 +04:00
2017-11-07 14:29:51 +03:00
return swrap . libc . symbols . _libc_timerfd_create . f ( clockid , flags ) ;
2014-04-07 18:12:21 +04:00
}
# endif
2016-03-15 17:47:08 +03:00
static ssize_t libc_write ( int fd , const void * buf , size_t count )
{
2021-02-09 10:56:42 +03:00
swrap_bind_symbol_all ( ) ;
2016-03-15 17:47:08 +03:00
2017-11-07 14:29:51 +03:00
return swrap . libc . symbols . _libc_write . f ( fd , buf , count ) ;
2016-03-15 17:47:08 +03:00
}
2014-04-07 18:12:21 +04:00
static ssize_t libc_writev ( int fd , const struct iovec * iov , int iovcnt )
{
2021-02-09 10:56:42 +03:00
swrap_bind_symbol_all ( ) ;
2017-11-07 14:29:51 +03:00
return swrap . libc . symbols . _libc_writev . f ( fd , iov , iovcnt ) ;
}
2014-04-07 18:12:21 +04:00
2017-11-07 14:29:51 +03:00
/* DO NOT call this function during library initialization! */
2021-02-09 10:56:42 +03:00
static void __swrap_bind_symbol_all_once ( void )
2017-11-07 14:29:51 +03:00
{
# ifdef HAVE_ACCEPT4
swrap_bind_symbol_libsocket ( accept4 ) ;
# else
swrap_bind_symbol_libsocket ( accept ) ;
# endif
swrap_bind_symbol_libsocket ( bind ) ;
swrap_bind_symbol_libc ( close ) ;
2021-02-17 14:57:01 +03:00
# ifdef HAVE___CLOSE_NOCANCEL
swrap_bind_symbol_libc ( __close_nocancel ) ;
# endif
2017-11-07 14:29:51 +03:00
swrap_bind_symbol_libsocket ( connect ) ;
swrap_bind_symbol_libc ( dup ) ;
swrap_bind_symbol_libc ( dup2 ) ;
swrap_bind_symbol_libc ( fcntl ) ;
swrap_bind_symbol_libc ( fopen ) ;
# ifdef HAVE_FOPEN64
swrap_bind_symbol_libc ( fopen64 ) ;
# endif
# ifdef HAVE_EVENTFD
swrap_bind_symbol_libc ( eventfd ) ;
# endif
swrap_bind_symbol_libsocket ( getpeername ) ;
swrap_bind_symbol_libsocket ( getsockname ) ;
swrap_bind_symbol_libsocket ( getsockopt ) ;
swrap_bind_symbol_libc ( ioctl ) ;
swrap_bind_symbol_libsocket ( listen ) ;
swrap_bind_symbol_libc ( open ) ;
# ifdef HAVE_OPEN64
swrap_bind_symbol_libc ( open64 ) ;
# endif
swrap_bind_symbol_libc ( openat ) ;
swrap_bind_symbol_libsocket ( pipe ) ;
swrap_bind_symbol_libc ( read ) ;
swrap_bind_symbol_libsocket ( readv ) ;
swrap_bind_symbol_libsocket ( recv ) ;
swrap_bind_symbol_libsocket ( recvfrom ) ;
swrap_bind_symbol_libsocket ( recvmsg ) ;
swrap_bind_symbol_libsocket ( send ) ;
swrap_bind_symbol_libsocket ( sendmsg ) ;
swrap_bind_symbol_libsocket ( sendto ) ;
swrap_bind_symbol_libsocket ( setsockopt ) ;
# ifdef HAVE_SIGNALFD
swrap_bind_symbol_libsocket ( signalfd ) ;
# endif
swrap_bind_symbol_libsocket ( socket ) ;
swrap_bind_symbol_libsocket ( socketpair ) ;
# ifdef HAVE_TIMERFD_CREATE
swrap_bind_symbol_libc ( timerfd_create ) ;
# endif
swrap_bind_symbol_libc ( write ) ;
swrap_bind_symbol_libsocket ( writev ) ;
2014-04-07 18:12:21 +04:00
}
2021-02-09 10:56:42 +03:00
static void swrap_bind_symbol_all ( void )
{
static pthread_once_t all_symbol_binding_once = PTHREAD_ONCE_INIT ;
pthread_once ( & all_symbol_binding_once , __swrap_bind_symbol_all_once ) ;
}
2014-04-07 18:12:21 +04:00
/*********************************************************
* SWRAP HELPER FUNCTIONS
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2020-03-10 15:27:27 +03:00
/*
* We return 127.0 .0 .0 ( default ) or 10.53 .57 .0 .
*
* This can be controlled by :
* SOCKET_WRAPPER_IPV4_NETWORK = 127.0 .0 .0 ( default )
* or
* SOCKET_WRAPPER_IPV4_NETWORK = 10.53 .57 .0
*/
static in_addr_t swrap_ipv4_net ( void )
{
static int initialized ;
static in_addr_t hv ;
const char * net_str = NULL ;
struct in_addr nv ;
int ret ;
if ( initialized ) {
return hv ;
}
initialized = 1 ;
net_str = getenv ( " SOCKET_WRAPPER_IPV4_NETWORK " ) ;
if ( net_str = = NULL ) {
net_str = " 127.0.0.0 " ;
}
ret = inet_pton ( AF_INET , net_str , & nv ) ;
if ( ret < = 0 ) {
SWRAP_LOG ( SWRAP_LOG_ERROR ,
2020-06-08 15:18:00 +03:00
" INVALID IPv4 Network [%s] " ,
2020-03-10 15:27:27 +03:00
net_str ) ;
abort ( ) ;
}
hv = ntohl ( nv . s_addr ) ;
switch ( hv ) {
case 0x7f000000 :
/* 127.0.0.0 */
break ;
case 0x0a353900 :
/* 10.53.57.0 */
break ;
default :
SWRAP_LOG ( SWRAP_LOG_ERROR ,
" INVALID IPv4 Network [%s][0x%x] should be "
2020-06-08 15:18:00 +03:00
" 127.0.0.0 or 10.53.57.0 " ,
2020-03-10 15:27:27 +03:00
net_str , ( unsigned ) hv ) ;
abort ( ) ;
}
return hv ;
}
/*
* This returns 127.255 .255 .255 or 10.255 .255 .255
*/
static in_addr_t swrap_ipv4_bcast ( void )
{
in_addr_t hv ;
hv = swrap_ipv4_net ( ) ;
hv | = IN_CLASSA_HOST ;
return hv ;
}
/*
* This returns 127.0 .0 . $ { iface } or 10.53 .57 . $ { iface }
*/
static in_addr_t swrap_ipv4_iface ( unsigned int iface )
{
in_addr_t hv ;
if ( iface = = 0 | | iface > MAX_WRAPPED_INTERFACES ) {
SWRAP_LOG ( SWRAP_LOG_ERROR ,
2020-06-08 15:18:00 +03:00
" swrap_ipv4_iface(%u) invalid! " ,
2020-03-10 15:27:27 +03:00
iface ) ;
abort ( ) ;
return - 1 ;
}
hv = swrap_ipv4_net ( ) ;
hv | = iface ;
return hv ;
}
2009-03-03 18:45:41 +03:00
# ifdef HAVE_IPV6
/*
* FD00 : : 5357 : 5F XX
*/
2009-03-09 11:24:45 +03:00
static const struct in6_addr * swrap_ipv6 ( void )
{
static struct in6_addr v ;
static int initialized ;
int ret ;
if ( initialized ) {
return & v ;
}
initialized = 1 ;
ret = inet_pton ( AF_INET6 , " FD00::5357:5F00 " , & v ) ;
if ( ret < = 0 ) {
abort ( ) ;
}
return & v ;
}
2009-03-03 18:45:41 +03:00
# endif
2007-04-16 08:59:47 +04:00
2014-10-02 09:17:10 +04:00
static void set_port ( int family , int prt , struct swrap_address * addr )
2007-04-16 08:59:47 +04:00
{
switch ( family ) {
case AF_INET :
2014-10-02 09:17:10 +04:00
addr - > sa . in . sin_port = htons ( prt ) ;
2007-04-16 08:59:47 +04:00
break ;
# ifdef HAVE_IPV6
case AF_INET6 :
2014-10-02 09:17:10 +04:00
addr - > sa . in6 . sin6_port = htons ( prt ) ;
2007-04-16 08:59:47 +04:00
break ;
# endif
}
}
2007-06-11 18:41:14 +04:00
static size_t socket_length ( int family )
2007-04-16 08:59:47 +04:00
{
switch ( family ) {
case AF_INET :
return sizeof ( struct sockaddr_in ) ;
# ifdef HAVE_IPV6
case AF_INET6 :
return sizeof ( struct sockaddr_in6 ) ;
# endif
}
2007-06-11 18:41:14 +04:00
return 0 ;
2007-04-16 08:59:47 +04:00
}
2018-05-02 16:57:38 +03:00
static struct socket_info * swrap_get_socket_info ( int si_index )
{
return ( struct socket_info * ) ( & ( sockets [ si_index ] . info ) ) ;
}
static int swrap_get_refcount ( struct socket_info * si )
{
struct socket_info_container * sic = SOCKET_INFO_CONTAINER ( si ) ;
return sic - > meta . refcount ;
}
static void swrap_inc_refcount ( struct socket_info * si )
{
struct socket_info_container * sic = SOCKET_INFO_CONTAINER ( si ) ;
sic - > meta . refcount + = 1 ;
}
static void swrap_dec_refcount ( struct socket_info * si )
{
struct socket_info_container * sic = SOCKET_INFO_CONTAINER ( si ) ;
sic - > meta . refcount - = 1 ;
}
static int swrap_get_next_free ( struct socket_info * si )
{
struct socket_info_container * sic = SOCKET_INFO_CONTAINER ( si ) ;
return sic - > meta . next_free ;
}
static void swrap_set_next_free ( struct socket_info * si , int next_free )
{
struct socket_info_container * sic = SOCKET_INFO_CONTAINER ( si ) ;
sic - > meta . next_free = next_free ;
}
2020-06-08 15:18:00 +03:00
static int swrap_un_path ( struct sockaddr_un * un ,
const char * swrap_dir ,
char type ,
unsigned int iface ,
unsigned int prt )
{
int ret ;
ret = snprintf ( un - > sun_path ,
sizeof ( un - > sun_path ) ,
" %s/ " SOCKET_FORMAT ,
swrap_dir ,
type ,
iface ,
prt ) ;
if ( ( size_t ) ret > = sizeof ( un - > sun_path ) ) {
return ENAMETOOLONG ;
}
return 0 ;
}
static int swrap_un_path_EINVAL ( struct sockaddr_un * un ,
const char * swrap_dir )
{
int ret ;
ret = snprintf ( un - > sun_path ,
sizeof ( un - > sun_path ) ,
" %s/EINVAL " ,
swrap_dir ) ;
if ( ( size_t ) ret > = sizeof ( un - > sun_path ) ) {
return ENAMETOOLONG ;
}
return 0 ;
}
static bool swrap_dir_usable ( const char * swrap_dir )
{
struct sockaddr_un un ;
int ret ;
ret = swrap_un_path ( & un , swrap_dir , SOCKET_TYPE_CHAR_TCP , 0 , 0 ) ;
if ( ret = = 0 ) {
return true ;
}
ret = swrap_un_path_EINVAL ( & un , swrap_dir ) ;
if ( ret = = 0 ) {
return true ;
}
return false ;
}
2019-03-21 12:02:54 +03:00
static char * socket_wrapper_dir ( void )
2005-07-21 17:45:07 +04:00
{
2019-03-21 12:02:54 +03:00
char * swrap_dir = NULL ;
char * s = getenv ( " SOCKET_WRAPPER_DIR " ) ;
2020-06-08 15:18:00 +03:00
char * t ;
bool ok ;
2019-03-21 12:02:54 +03:00
2021-02-09 10:56:42 +03:00
if ( s = = NULL | | s [ 0 ] = = ' \0 ' ) {
2020-06-08 15:18:00 +03:00
SWRAP_LOG ( SWRAP_LOG_WARN , " SOCKET_WRAPPER_DIR not set " ) ;
2005-07-21 17:45:07 +04:00
return NULL ;
}
2019-03-21 12:02:54 +03:00
swrap_dir = realpath ( s , NULL ) ;
if ( swrap_dir = = NULL ) {
SWRAP_LOG ( SWRAP_LOG_ERROR ,
2021-02-09 10:56:42 +03:00
" Unable to resolve socket_wrapper dir path: %s - %s " ,
s ,
2019-03-21 12:02:54 +03:00
strerror ( errno ) ) ;
2020-06-08 15:18:00 +03:00
abort ( ) ;
}
ok = swrap_dir_usable ( swrap_dir ) ;
if ( ok ) {
goto done ;
}
free ( swrap_dir ) ;
ok = swrap_dir_usable ( s ) ;
if ( ! ok ) {
SWRAP_LOG ( SWRAP_LOG_ERROR , " SOCKET_WRAPPER_DIR is too long " ) ;
abort ( ) ;
}
t = getenv ( " SOCKET_WRAPPER_DIR_ALLOW_ORIG " ) ;
if ( t = = NULL ) {
SWRAP_LOG ( SWRAP_LOG_ERROR ,
" realpath(SOCKET_WRAPPER_DIR) too long and "
" SOCKET_WRAPPER_DIR_ALLOW_ORIG not set " ) ;
abort ( ) ;
2005-07-21 17:45:07 +04:00
}
2014-04-07 18:12:21 +04:00
2020-06-08 15:18:00 +03:00
swrap_dir = strdup ( s ) ;
if ( swrap_dir = = NULL ) {
SWRAP_LOG ( SWRAP_LOG_ERROR ,
" Unable to duplicate socket_wrapper dir path " ) ;
abort ( ) ;
}
SWRAP_LOG ( SWRAP_LOG_WARN ,
" realpath(SOCKET_WRAPPER_DIR) too long, "
" using original SOCKET_WRAPPER_DIR \n " ) ;
done :
2019-03-21 12:02:54 +03:00
SWRAP_LOG ( SWRAP_LOG_TRACE , " socket_wrapper_dir: %s " , swrap_dir ) ;
return swrap_dir ;
2005-07-21 17:45:07 +04:00
}
2015-08-25 18:20:20 +03:00
static unsigned int socket_wrapper_mtu ( void )
{
static unsigned int max_mtu = 0 ;
unsigned int tmp ;
const char * s ;
char * endp ;
2018-05-02 16:57:38 +03:00
swrap_mutex_lock ( & mtu_update_mutex ) ;
2015-08-25 18:20:20 +03:00
if ( max_mtu ! = 0 ) {
2018-05-02 16:57:38 +03:00
goto done ;
2015-08-25 18:20:20 +03:00
}
max_mtu = SOCKET_WRAPPER_MTU_DEFAULT ;
s = getenv ( " SOCKET_WRAPPER_MTU " ) ;
if ( s = = NULL ) {
goto done ;
}
tmp = strtol ( s , & endp , 10 ) ;
if ( s = = endp ) {
goto done ;
}
if ( tmp < SOCKET_WRAPPER_MTU_MIN | | tmp > SOCKET_WRAPPER_MTU_MAX ) {
goto done ;
}
max_mtu = tmp ;
done :
2018-05-02 16:57:38 +03:00
swrap_mutex_unlock ( & mtu_update_mutex ) ;
2015-08-25 18:20:20 +03:00
return max_mtu ;
}
2021-02-09 10:56:42 +03:00
static int _socket_wrapper_init_mutex ( pthread_mutex_t * m , const char * name )
2018-05-02 16:57:38 +03:00
{
pthread_mutexattr_t ma ;
2021-02-09 10:56:42 +03:00
bool need_destroy = false ;
int ret = 0 ;
# define __CHECK(cmd) do { \
ret = cmd ; \
if ( ret ! = 0 ) { \
SWRAP_LOG ( SWRAP_LOG_ERROR , \
" %s: %s - failed %d " , \
name , # cmd , ret ) ; \
goto done ; \
} \
} while ( 0 )
2018-05-02 16:57:38 +03:00
2021-02-09 10:56:42 +03:00
* m = ( pthread_mutex_t ) PTHREAD_MUTEX_INITIALIZER ;
__CHECK ( pthread_mutexattr_init ( & ma ) ) ;
need_destroy = true ;
__CHECK ( pthread_mutexattr_settype ( & ma , PTHREAD_MUTEX_ERRORCHECK ) ) ;
__CHECK ( pthread_mutex_init ( m , & ma ) ) ;
2018-05-02 16:57:38 +03:00
done :
2021-02-09 10:56:42 +03:00
if ( need_destroy ) {
pthread_mutexattr_destroy ( & ma ) ;
}
2018-05-02 16:57:38 +03:00
return ret ;
}
2017-11-07 14:29:51 +03:00
static size_t socket_wrapper_max_sockets ( void )
{
const char * s ;
2018-05-02 16:57:38 +03:00
size_t tmp ;
2017-11-07 14:29:51 +03:00
char * endp ;
2018-05-02 16:57:38 +03:00
if ( socket_info_max ! = 0 ) {
return socket_info_max ;
2017-11-07 14:29:51 +03:00
}
2018-05-02 16:57:38 +03:00
socket_info_max = SOCKET_WRAPPER_MAX_SOCKETS_DEFAULT ;
2017-11-07 14:29:51 +03:00
s = getenv ( " SOCKET_WRAPPER_MAX_SOCKETS " ) ;
if ( s = = NULL | | s [ 0 ] = = ' \0 ' ) {
goto done ;
}
tmp = strtoul ( s , & endp , 10 ) ;
if ( s = = endp ) {
goto done ;
}
2018-05-02 16:57:38 +03:00
if ( tmp = = 0 ) {
tmp = SOCKET_WRAPPER_MAX_SOCKETS_DEFAULT ;
2017-11-07 14:29:51 +03:00
SWRAP_LOG ( SWRAP_LOG_ERROR ,
2018-05-02 16:57:38 +03:00
" Invalid number of sockets specified, "
" using default (%zu) " ,
tmp ) ;
}
if ( tmp > SOCKET_WRAPPER_MAX_SOCKETS_LIMIT ) {
tmp = SOCKET_WRAPPER_MAX_SOCKETS_LIMIT ;
SWRAP_LOG ( SWRAP_LOG_ERROR ,
" Invalid number of sockets specified, "
" using maximum (%zu). " ,
tmp ) ;
2017-11-07 14:29:51 +03:00
}
2018-05-02 16:57:38 +03:00
socket_info_max = tmp ;
2017-11-07 14:29:51 +03:00
done :
2018-05-02 16:57:38 +03:00
return socket_info_max ;
}
static void socket_wrapper_init_fds_idx ( void )
{
int * tmp = NULL ;
size_t i ;
if ( socket_fds_idx ! = NULL ) {
return ;
}
tmp = ( int * ) calloc ( socket_fds_max , sizeof ( int ) ) ;
if ( tmp = = NULL ) {
SWRAP_LOG ( SWRAP_LOG_ERROR ,
" Failed to allocate socket fds index array: %s " ,
strerror ( errno ) ) ;
exit ( - 1 ) ;
}
for ( i = 0 ; i < socket_fds_max ; i + + ) {
tmp [ i ] = - 1 ;
}
socket_fds_idx = tmp ;
2017-11-07 14:29:51 +03:00
}
static void socket_wrapper_init_sockets ( void )
{
2018-05-02 16:57:38 +03:00
size_t max_sockets ;
2017-11-07 14:29:51 +03:00
size_t i ;
2021-02-09 10:56:42 +03:00
int ret = 0 ;
swrap_bind_symbol_all ( ) ;
2018-05-02 16:57:38 +03:00
swrap_mutex_lock ( & sockets_mutex ) ;
2017-11-07 14:29:51 +03:00
if ( sockets ! = NULL ) {
2018-05-02 16:57:38 +03:00
swrap_mutex_unlock ( & sockets_mutex ) ;
2017-11-07 14:29:51 +03:00
return ;
}
2021-02-09 10:56:42 +03:00
SWRAP_LOG ( SWRAP_LOG_DEBUG ,
" SOCKET_WRAPPER_PACKAGE[%s] SOCKET_WRAPPER_VERSION[%s] " ,
SOCKET_WRAPPER_PACKAGE , SOCKET_WRAPPER_VERSION ) ;
2020-03-10 15:27:27 +03:00
/*
* Intialize the static cache early before
* any thread is able to start .
*/
( void ) swrap_ipv4_net ( ) ;
2018-05-02 16:57:38 +03:00
socket_wrapper_init_fds_idx ( ) ;
/* Needs to be called inside the sockets_mutex lock here. */
2017-11-07 14:29:51 +03:00
max_sockets = socket_wrapper_max_sockets ( ) ;
2018-05-02 16:57:38 +03:00
sockets = ( struct socket_info_container * ) calloc ( max_sockets ,
sizeof ( struct socket_info_container ) ) ;
2017-11-07 14:29:51 +03:00
if ( sockets = = NULL ) {
SWRAP_LOG ( SWRAP_LOG_ERROR ,
2018-05-02 16:57:38 +03:00
" Failed to allocate sockets array: %s " ,
strerror ( errno ) ) ;
swrap_mutex_unlock ( & sockets_mutex ) ;
2017-11-07 14:29:51 +03:00
exit ( - 1 ) ;
}
2018-05-02 16:57:38 +03:00
swrap_mutex_lock ( & first_free_mutex ) ;
2021-02-09 10:56:42 +03:00
swrap_mutex_lock ( & sockets_si_global ) ;
2018-05-02 16:57:38 +03:00
2017-11-07 14:29:51 +03:00
first_free = 0 ;
for ( i = 0 ; i < max_sockets ; i + + ) {
2018-05-02 16:57:38 +03:00
swrap_set_next_free ( & sockets [ i ] . info , i + 1 ) ;
}
/* mark the end of the free list */
swrap_set_next_free ( & sockets [ max_sockets - 1 ] . info , - 1 ) ;
2021-02-09 10:56:42 +03:00
swrap_mutex_unlock ( & sockets_si_global ) ;
2018-05-02 16:57:38 +03:00
swrap_mutex_unlock ( & first_free_mutex ) ;
swrap_mutex_unlock ( & sockets_mutex ) ;
if ( ret ! = 0 ) {
exit ( - 1 ) ;
}
2017-11-07 14:29:51 +03:00
}
2014-04-07 18:12:21 +04:00
bool socket_wrapper_enabled ( void )
{
2019-03-21 12:02:54 +03:00
char * s = socket_wrapper_dir ( ) ;
2014-04-07 18:12:21 +04:00
2017-11-07 14:29:51 +03:00
if ( s = = NULL ) {
return false ;
}
2019-03-21 12:02:54 +03:00
SAFE_FREE ( s ) ;
2017-11-07 14:29:51 +03:00
socket_wrapper_init_sockets ( ) ;
return true ;
2014-04-07 18:12:21 +04:00
}
static unsigned int socket_wrapper_default_iface ( void )
2005-11-07 18:36:51 +03:00
{
const char * s = getenv ( " SOCKET_WRAPPER_DEFAULT_IFACE " ) ;
if ( s ) {
unsigned int iface ;
2007-04-16 08:59:47 +04:00
if ( sscanf ( s , " %u " , & iface ) = = 1 ) {
if ( iface > = 1 & & iface < = MAX_WRAPPED_INTERFACES ) {
return iface ;
}
2005-11-07 18:36:51 +03:00
}
}
return 1 ; /* 127.0.0.1 */
}
2018-05-02 16:57:38 +03:00
static void set_socket_info_index ( int fd , int idx )
2017-11-07 14:29:51 +03:00
{
2020-03-10 15:27:27 +03:00
SWRAP_LOG ( SWRAP_LOG_TRACE ,
2020-06-08 15:18:00 +03:00
" fd=%d idx=%d " ,
2020-03-10 15:27:27 +03:00
fd , idx ) ;
2018-05-02 16:57:38 +03:00
socket_fds_idx [ fd ] = idx ;
/* This builtin issues a full memory barrier. */
__sync_synchronize ( ) ;
}
static void reset_socket_info_index ( int fd )
{
2020-03-10 15:27:27 +03:00
SWRAP_LOG ( SWRAP_LOG_TRACE ,
2020-06-08 15:18:00 +03:00
" fd=%d idx=%d " ,
2020-03-10 15:27:27 +03:00
fd , - 1 ) ;
2018-05-02 16:57:38 +03:00
set_socket_info_index ( fd , - 1 ) ;
}
static int find_socket_info_index ( int fd )
{
if ( fd < 0 ) {
return - 1 ;
}
if ( socket_fds_idx = = NULL ) {
return - 1 ;
}
2017-11-07 14:29:51 +03:00
2018-05-02 16:57:38 +03:00
if ( ( size_t ) fd > = socket_fds_max ) {
/*
* Do not add a log here as some applications do stupid things
* like :
*
* for ( fd = 0 ; fd < = getdtablesize ( ) ; fd + + ) {
* close ( fd )
* } ;
*
* This would produce millions of lines of debug messages .
*/
#if 0
SWRAP_LOG ( SWRAP_LOG_ERROR ,
" Looking for a socket info for the fd %d is over the "
" max socket index limit of %zu. " ,
fd ,
socket_fds_max ) ;
# endif
return - 1 ;
}
/* This builtin issues a full memory barrier. */
__sync_synchronize ( ) ;
return socket_fds_idx [ fd ] ;
}
2021-02-09 10:56:42 +03:00
static int swrap_add_socket_info ( const struct socket_info * si_input )
2018-05-02 16:57:38 +03:00
{
struct socket_info * si = NULL ;
int si_index = - 1 ;
if ( si_input = = NULL ) {
errno = EINVAL ;
return - 1 ;
}
swrap_mutex_lock ( & first_free_mutex ) ;
2017-11-07 14:29:51 +03:00
if ( first_free = = - 1 ) {
2018-05-02 16:57:38 +03:00
errno = ENFILE ;
goto out ;
}
si_index = first_free ;
si = swrap_get_socket_info ( si_index ) ;
SWRAP_LOCK_SI ( si ) ;
first_free = swrap_get_next_free ( si ) ;
* si = * si_input ;
swrap_inc_refcount ( si ) ;
SWRAP_UNLOCK_SI ( si ) ;
out :
swrap_mutex_unlock ( & first_free_mutex ) ;
return si_index ;
}
static int swrap_create_socket ( struct socket_info * si , int fd )
{
int idx ;
if ( ( size_t ) fd > = socket_fds_max ) {
SWRAP_LOG ( SWRAP_LOG_ERROR ,
" The max socket index limit of %zu has been reached, "
" trying to add %d " ,
socket_fds_max ,
fd ) ;
2021-02-09 10:56:42 +03:00
errno = EMFILE ;
2018-05-02 16:57:38 +03:00
return - 1 ;
}
idx = swrap_add_socket_info ( si ) ;
if ( idx = = - 1 ) {
2017-11-07 14:29:51 +03:00
return - 1 ;
}
2018-05-02 16:57:38 +03:00
set_socket_info_index ( fd , idx ) ;
2017-11-07 14:29:51 +03:00
2018-05-02 16:57:38 +03:00
return idx ;
2017-11-07 14:29:51 +03:00
}
2007-04-16 08:59:47 +04:00
static int convert_un_in ( const struct sockaddr_un * un , struct sockaddr * in , socklen_t * len )
2005-03-28 05:00:39 +04:00
{
2005-11-07 18:36:51 +03:00
unsigned int iface ;
2005-03-28 05:00:39 +04:00
unsigned int prt ;
const char * p ;
2005-11-07 18:36:51 +03:00
char type ;
2005-03-28 05:00:39 +04:00
2005-06-10 16:21:46 +04:00
p = strrchr ( un - > sun_path , ' / ' ) ;
2005-03-28 05:00:39 +04:00
if ( p ) p + + ; else p = un - > sun_path ;
2005-11-07 18:36:51 +03:00
if ( sscanf ( p , SOCKET_FORMAT , & type , & iface , & prt ) ! = 3 ) {
2021-02-09 10:56:42 +03:00
SWRAP_LOG ( SWRAP_LOG_ERROR , " sun_path[%s] p[%s] " ,
un - > sun_path , p ) ;
2005-11-07 18:36:51 +03:00
errno = EINVAL ;
return - 1 ;
}
2007-04-16 08:59:47 +04:00
if ( iface = = 0 | | iface > MAX_WRAPPED_INTERFACES ) {
2021-02-09 10:56:42 +03:00
SWRAP_LOG ( SWRAP_LOG_ERROR , " type %c iface %u port %u " ,
type , iface , prt ) ;
2005-11-07 18:36:51 +03:00
errno = EINVAL ;
return - 1 ;
}
2007-04-16 08:59:47 +04:00
if ( prt > 0xFFFF ) {
2021-02-09 10:56:42 +03:00
SWRAP_LOG ( SWRAP_LOG_ERROR , " type %c iface %u port %u " ,
type , iface , prt ) ;
2005-11-07 18:36:51 +03:00
errno = EINVAL ;
return - 1 ;
}
2021-02-09 10:56:42 +03:00
SWRAP_LOG ( SWRAP_LOG_TRACE , " type %c iface %u port %u " ,
type , iface , prt ) ;
2007-04-16 08:59:47 +04:00
switch ( type ) {
case SOCKET_TYPE_CHAR_TCP :
case SOCKET_TYPE_CHAR_UDP : {
2011-03-02 22:46:45 +03:00
struct sockaddr_in * in2 = ( struct sockaddr_in * ) ( void * ) in ;
2011-02-12 14:18:16 +03:00
2007-04-16 08:59:47 +04:00
if ( ( * len ) < sizeof ( * in2 ) ) {
2021-02-09 10:56:42 +03:00
SWRAP_LOG ( SWRAP_LOG_ERROR ,
" V4: *len(%zu) < sizeof(*in2)=%zu " ,
( size_t ) * len , sizeof ( * in2 ) ) ;
errno = EINVAL ;
return - 1 ;
2007-04-16 08:59:47 +04:00
}
memset ( in2 , 0 , sizeof ( * in2 ) ) ;
in2 - > sin_family = AF_INET ;
2020-03-10 15:27:27 +03:00
in2 - > sin_addr . s_addr = htonl ( swrap_ipv4_iface ( iface ) ) ;
2007-04-16 08:59:47 +04:00
in2 - > sin_port = htons ( prt ) ;
* len = sizeof ( * in2 ) ;
break ;
}
# ifdef HAVE_IPV6
case SOCKET_TYPE_CHAR_TCP_V6 :
case SOCKET_TYPE_CHAR_UDP_V6 : {
2011-03-02 22:46:45 +03:00
struct sockaddr_in6 * in2 = ( struct sockaddr_in6 * ) ( void * ) in ;
2011-02-12 14:18:16 +03:00
2007-04-16 08:59:47 +04:00
if ( ( * len ) < sizeof ( * in2 ) ) {
2021-02-09 10:56:42 +03:00
SWRAP_LOG ( SWRAP_LOG_ERROR ,
" V6: *len(%zu) < sizeof(*in2)=%zu " ,
( size_t ) * len , sizeof ( * in2 ) ) ;
SWRAP_LOG ( SWRAP_LOG_ERROR , " LINE:%d " , __LINE__ ) ;
2007-04-16 08:59:47 +04:00
errno = EINVAL ;
return - 1 ;
}
memset ( in2 , 0 , sizeof ( * in2 ) ) ;
in2 - > sin6_family = AF_INET6 ;
2009-03-09 11:24:45 +03:00
in2 - > sin6_addr = * swrap_ipv6 ( ) ;
2009-03-03 18:45:41 +03:00
in2 - > sin6_addr . s6_addr [ 15 ] = iface ;
2007-04-16 08:59:47 +04:00
in2 - > sin6_port = htons ( prt ) ;
* len = sizeof ( * in2 ) ;
break ;
}
# endif
default :
2021-02-09 10:56:42 +03:00
SWRAP_LOG ( SWRAP_LOG_ERROR , " type %c iface %u port %u " ,
type , iface , prt ) ;
2005-11-07 18:36:51 +03:00
errno = EINVAL ;
return - 1 ;
2005-03-28 05:00:39 +04:00
}
2005-11-07 18:36:51 +03:00
2005-03-28 05:00:39 +04:00
return 0 ;
}
2007-04-16 08:59:47 +04:00
static int convert_in_un_remote ( struct socket_info * si , const struct sockaddr * inaddr , struct sockaddr_un * un ,
2005-11-07 18:36:51 +03:00
int * bcast )
2005-03-28 05:00:39 +04:00
{
2005-11-07 18:36:51 +03:00
char type = ' \0 ' ;
2007-04-16 08:59:47 +04:00
unsigned int prt ;
2005-11-07 18:36:51 +03:00
unsigned int iface ;
int is_bcast = 0 ;
2019-03-21 12:02:54 +03:00
char * swrap_dir = NULL ;
2005-11-07 18:36:51 +03:00
if ( bcast ) * bcast = 0 ;
2009-06-09 07:33:09 +04:00
switch ( inaddr - > sa_family ) {
2007-04-16 08:59:47 +04:00
case AF_INET : {
2014-10-02 09:20:53 +04:00
const struct sockaddr_in * in =
2011-03-02 22:46:45 +03:00
( const struct sockaddr_in * ) ( const void * ) inaddr ;
2007-04-16 08:59:47 +04:00
unsigned int addr = ntohl ( in - > sin_addr . s_addr ) ;
char u_type = ' \0 ' ;
char b_type = ' \0 ' ;
char a_type = ' \0 ' ;
2020-03-10 15:27:27 +03:00
const unsigned int sw_net_addr = swrap_ipv4_net ( ) ;
const unsigned int sw_bcast_addr = swrap_ipv4_bcast ( ) ;
2005-11-07 18:36:51 +03:00
2007-04-16 08:59:47 +04:00
switch ( si - > type ) {
case SOCK_STREAM :
u_type = SOCKET_TYPE_CHAR_TCP ;
break ;
case SOCK_DGRAM :
u_type = SOCKET_TYPE_CHAR_UDP ;
a_type = SOCKET_TYPE_CHAR_UDP ;
b_type = SOCKET_TYPE_CHAR_UDP ;
break ;
2014-04-07 18:12:21 +04:00
default :
2020-06-08 15:18:00 +03:00
SWRAP_LOG ( SWRAP_LOG_ERROR , " Unknown socket type! " ) ;
2014-04-07 18:12:21 +04:00
errno = ESOCKTNOSUPPORT ;
return - 1 ;
2007-04-16 08:59:47 +04:00
}
prt = ntohs ( in - > sin_port ) ;
if ( a_type & & addr = = 0xFFFFFFFF ) {
/* 255.255.255.255 only udp */
is_bcast = 2 ;
type = a_type ;
iface = socket_wrapper_default_iface ( ) ;
2020-03-10 15:27:27 +03:00
} else if ( b_type & & addr = = sw_bcast_addr ) {
/*
* 127.255 .255 .255
* or
* 10.255 .255 .255
* only udp
*/
2007-04-16 08:59:47 +04:00
is_bcast = 1 ;
type = b_type ;
iface = socket_wrapper_default_iface ( ) ;
2020-03-10 15:27:27 +03:00
} else if ( ( addr & 0xFFFFFF00 ) = = sw_net_addr ) {
/* 127.0.0.X or 10.53.57.X */
2007-04-16 08:59:47 +04:00
is_bcast = 0 ;
type = u_type ;
iface = ( addr & 0x000000FF ) ;
} else {
2021-02-17 14:57:01 +03:00
char str [ 256 ] = { 0 , } ;
inet_ntop ( inaddr - > sa_family ,
& in - > sin_addr ,
str , sizeof ( str ) ) ;
SWRAP_LOG ( SWRAP_LOG_WARN ,
" str[%s] prt[%u] " ,
str , ( unsigned ) prt ) ;
2007-04-16 08:59:47 +04:00
errno = ENETUNREACH ;
return - 1 ;
}
if ( bcast ) * bcast = is_bcast ;
2005-11-07 18:36:51 +03:00
break ;
}
2007-04-16 08:59:47 +04:00
# ifdef HAVE_IPV6
case AF_INET6 : {
2014-10-02 09:20:53 +04:00
const struct sockaddr_in6 * in =
2011-03-02 22:46:45 +03:00
( const struct sockaddr_in6 * ) ( const void * ) inaddr ;
struct in6_addr cmp1 , cmp2 ;
2005-11-07 18:36:51 +03:00
2007-04-16 08:59:47 +04:00
switch ( si - > type ) {
case SOCK_STREAM :
type = SOCKET_TYPE_CHAR_TCP_V6 ;
break ;
case SOCK_DGRAM :
type = SOCKET_TYPE_CHAR_UDP_V6 ;
break ;
2014-04-07 18:12:21 +04:00
default :
2020-06-08 15:18:00 +03:00
SWRAP_LOG ( SWRAP_LOG_ERROR , " Unknown socket type! " ) ;
2014-04-07 18:12:21 +04:00
errno = ESOCKTNOSUPPORT ;
return - 1 ;
2007-04-16 08:59:47 +04:00
}
/* XXX no multicast/broadcast */
prt = ntohs ( in - > sin6_port ) ;
2009-03-03 18:45:41 +03:00
2011-03-02 22:46:45 +03:00
cmp1 = * swrap_ipv6 ( ) ;
cmp2 = in - > sin6_addr ;
cmp2 . s6_addr [ 15 ] = 0 ;
if ( IN6_ARE_ADDR_EQUAL ( & cmp1 , & cmp2 ) ) {
2009-03-03 18:45:41 +03:00
iface = in - > sin6_addr . s6_addr [ 15 ] ;
} else {
2021-02-17 14:57:01 +03:00
char str [ 256 ] = { 0 , } ;
inet_ntop ( inaddr - > sa_family ,
& in - > sin6_addr ,
str , sizeof ( str ) ) ;
SWRAP_LOG ( SWRAP_LOG_WARN ,
" str[%s] prt[%u] " ,
str , ( unsigned ) prt ) ;
2009-03-03 18:45:41 +03:00
errno = ENETUNREACH ;
return - 1 ;
}
2007-04-16 08:59:47 +04:00
break ;
}
# endif
default :
2020-06-08 15:18:00 +03:00
SWRAP_LOG ( SWRAP_LOG_ERROR , " Unknown address family! " ) ;
2005-11-07 18:36:51 +03:00
errno = ENETUNREACH ;
return - 1 ;
}
2007-04-16 08:59:47 +04:00
if ( prt = = 0 ) {
2020-06-08 15:18:00 +03:00
SWRAP_LOG ( SWRAP_LOG_WARN , " Port not set " ) ;
2007-04-16 08:59:47 +04:00
errno = EINVAL ;
return - 1 ;
}
2005-11-07 18:36:51 +03:00
2019-03-21 12:02:54 +03:00
swrap_dir = socket_wrapper_dir ( ) ;
if ( swrap_dir = = NULL ) {
errno = EINVAL ;
return - 1 ;
}
2005-11-07 18:36:51 +03:00
if ( is_bcast ) {
2020-06-08 15:18:00 +03:00
swrap_un_path_EINVAL ( un , swrap_dir ) ;
2014-04-07 18:12:21 +04:00
SWRAP_LOG ( SWRAP_LOG_DEBUG , " un path [%s] " , un - > sun_path ) ;
2019-03-21 12:02:54 +03:00
SAFE_FREE ( swrap_dir ) ;
2005-11-07 18:36:51 +03:00
/* the caller need to do more processing */
return 0 ;
}
2020-06-08 15:18:00 +03:00
swrap_un_path ( un , swrap_dir , type , iface , prt ) ;
2014-04-07 18:12:21 +04:00
SWRAP_LOG ( SWRAP_LOG_DEBUG , " un path [%s] " , un - > sun_path ) ;
2005-11-07 18:36:51 +03:00
2019-03-21 12:02:54 +03:00
SAFE_FREE ( swrap_dir ) ;
2005-11-07 18:36:51 +03:00
return 0 ;
}
2007-04-16 08:59:47 +04:00
static int convert_in_un_alloc ( struct socket_info * si , const struct sockaddr * inaddr , struct sockaddr_un * un ,
2005-11-07 18:36:51 +03:00
int * bcast )
{
char type = ' \0 ' ;
2007-04-16 08:59:47 +04:00
unsigned int prt ;
2005-11-07 18:36:51 +03:00
unsigned int iface ;
struct stat st ;
int is_bcast = 0 ;
2019-03-21 12:02:54 +03:00
char * swrap_dir = NULL ;
2005-11-07 18:36:51 +03:00
if ( bcast ) * bcast = 0 ;
2007-04-16 08:59:47 +04:00
switch ( si - > family ) {
case AF_INET : {
2014-10-02 09:20:53 +04:00
const struct sockaddr_in * in =
2011-03-02 22:46:45 +03:00
( const struct sockaddr_in * ) ( const void * ) inaddr ;
2007-04-16 08:59:47 +04:00
unsigned int addr = ntohl ( in - > sin_addr . s_addr ) ;
char u_type = ' \0 ' ;
char d_type = ' \0 ' ;
char b_type = ' \0 ' ;
char a_type = ' \0 ' ;
2020-03-10 15:27:27 +03:00
const unsigned int sw_net_addr = swrap_ipv4_net ( ) ;
const unsigned int sw_bcast_addr = swrap_ipv4_bcast ( ) ;
2007-04-16 08:59:47 +04:00
prt = ntohs ( in - > sin_port ) ;
switch ( si - > type ) {
case SOCK_STREAM :
u_type = SOCKET_TYPE_CHAR_TCP ;
d_type = SOCKET_TYPE_CHAR_TCP ;
break ;
case SOCK_DGRAM :
u_type = SOCKET_TYPE_CHAR_UDP ;
d_type = SOCKET_TYPE_CHAR_UDP ;
a_type = SOCKET_TYPE_CHAR_UDP ;
b_type = SOCKET_TYPE_CHAR_UDP ;
break ;
2014-04-07 18:12:21 +04:00
default :
2020-06-08 15:18:00 +03:00
SWRAP_LOG ( SWRAP_LOG_ERROR , " Unknown socket type! " ) ;
2014-04-07 18:12:21 +04:00
errno = ESOCKTNOSUPPORT ;
return - 1 ;
2007-04-16 08:59:47 +04:00
}
if ( addr = = 0 ) {
/* 0.0.0.0 */
2017-11-07 12:51:11 +03:00
is_bcast = 0 ;
2007-04-16 08:59:47 +04:00
type = d_type ;
iface = socket_wrapper_default_iface ( ) ;
} else if ( a_type & & addr = = 0xFFFFFFFF ) {
/* 255.255.255.255 only udp */
is_bcast = 2 ;
type = a_type ;
iface = socket_wrapper_default_iface ( ) ;
2020-03-10 15:27:27 +03:00
} else if ( b_type & & addr = = sw_bcast_addr ) {
2007-04-16 08:59:47 +04:00
/* 127.255.255.255 only udp */
is_bcast = 1 ;
type = b_type ;
iface = socket_wrapper_default_iface ( ) ;
2020-03-10 15:27:27 +03:00
} else if ( ( addr & 0xFFFFFF00 ) = = sw_net_addr ) {
2007-04-16 08:59:47 +04:00
/* 127.0.0.X */
is_bcast = 0 ;
type = u_type ;
iface = ( addr & 0x000000FF ) ;
} else {
errno = EADDRNOTAVAIL ;
return - 1 ;
}
2014-06-03 16:50:53 +04:00
/* Store the bind address for connect() */
2014-10-02 09:17:10 +04:00
if ( si - > bindname . sa_socklen = = 0 ) {
2014-06-03 16:50:53 +04:00
struct sockaddr_in bind_in ;
socklen_t blen = sizeof ( struct sockaddr_in ) ;
ZERO_STRUCT ( bind_in ) ;
bind_in . sin_family = in - > sin_family ;
bind_in . sin_port = in - > sin_port ;
2020-03-10 15:27:27 +03:00
bind_in . sin_addr . s_addr = htonl ( swrap_ipv4_iface ( iface ) ) ;
2014-10-02 09:17:10 +04:00
si - > bindname . sa_socklen = blen ;
memcpy ( & si - > bindname . sa . in , & bind_in , blen ) ;
2014-06-03 16:50:53 +04:00
}
2005-11-07 18:36:51 +03:00
break ;
}
2007-04-16 08:59:47 +04:00
# ifdef HAVE_IPV6
case AF_INET6 : {
2014-10-02 09:20:53 +04:00
const struct sockaddr_in6 * in =
2011-03-02 22:46:45 +03:00
( const struct sockaddr_in6 * ) ( const void * ) inaddr ;
struct in6_addr cmp1 , cmp2 ;
2005-11-07 18:36:51 +03:00
2007-04-16 08:59:47 +04:00
switch ( si - > type ) {
case SOCK_STREAM :
type = SOCKET_TYPE_CHAR_TCP_V6 ;
break ;
case SOCK_DGRAM :
type = SOCKET_TYPE_CHAR_UDP_V6 ;
break ;
2014-04-07 18:12:21 +04:00
default :
2020-06-08 15:18:00 +03:00
SWRAP_LOG ( SWRAP_LOG_ERROR , " Unknown socket type! " ) ;
2014-04-07 18:12:21 +04:00
errno = ESOCKTNOSUPPORT ;
return - 1 ;
2007-04-16 08:59:47 +04:00
}
/* XXX no multicast/broadcast */
prt = ntohs ( in - > sin6_port ) ;
2009-03-03 18:45:41 +03:00
2011-03-02 22:46:45 +03:00
cmp1 = * swrap_ipv6 ( ) ;
cmp2 = in - > sin6_addr ;
cmp2 . s6_addr [ 15 ] = 0 ;
2009-03-03 21:40:57 +03:00
if ( IN6_IS_ADDR_UNSPECIFIED ( & in - > sin6_addr ) ) {
iface = socket_wrapper_default_iface ( ) ;
2011-03-02 22:46:45 +03:00
} else if ( IN6_ARE_ADDR_EQUAL ( & cmp1 , & cmp2 ) ) {
2009-03-03 18:45:41 +03:00
iface = in - > sin6_addr . s6_addr [ 15 ] ;
} else {
errno = EADDRNOTAVAIL ;
return - 1 ;
}
2014-06-03 16:50:53 +04:00
/* Store the bind address for connect() */
2014-10-02 09:17:10 +04:00
if ( si - > bindname . sa_socklen = = 0 ) {
2014-06-03 16:50:53 +04:00
struct sockaddr_in6 bind_in ;
socklen_t blen = sizeof ( struct sockaddr_in6 ) ;
ZERO_STRUCT ( bind_in ) ;
bind_in . sin6_family = in - > sin6_family ;
bind_in . sin6_port = in - > sin6_port ;
bind_in . sin6_addr = * swrap_ipv6 ( ) ;
bind_in . sin6_addr . s6_addr [ 15 ] = iface ;
2014-10-02 09:17:10 +04:00
memcpy ( & si - > bindname . sa . in6 , & bind_in , blen ) ;
si - > bindname . sa_socklen = blen ;
2014-06-03 16:50:53 +04:00
}
2007-04-16 08:59:47 +04:00
break ;
}
# endif
default :
2020-06-08 15:18:00 +03:00
SWRAP_LOG ( SWRAP_LOG_ERROR , " Unknown address family " ) ;
2009-03-03 18:45:41 +03:00
errno = EADDRNOTAVAIL ;
2005-11-07 18:36:51 +03:00
return - 1 ;
}
2007-04-16 08:59:47 +04:00
2005-11-07 18:36:51 +03:00
if ( bcast ) * bcast = is_bcast ;
2011-07-10 18:40:37 +04:00
if ( iface = = 0 | | iface > MAX_WRAPPED_INTERFACES ) {
errno = EINVAL ;
return - 1 ;
}
2019-03-21 12:02:54 +03:00
swrap_dir = socket_wrapper_dir ( ) ;
if ( swrap_dir = = NULL ) {
errno = EINVAL ;
return - 1 ;
}
2005-06-10 16:21:46 +04:00
if ( prt = = 0 ) {
/* handle auto-allocation of ephemeral ports */
2005-11-07 18:36:51 +03:00
for ( prt = 5001 ; prt < 10000 ; prt + + ) {
2020-06-08 15:18:00 +03:00
swrap_un_path ( un , swrap_dir , type , iface , prt ) ;
2005-11-07 18:36:51 +03:00
if ( stat ( un - > sun_path , & st ) = = 0 ) continue ;
2014-10-02 09:17:10 +04:00
set_port ( si - > family , prt , & si - > myname ) ;
set_port ( si - > family , prt , & si - > bindname ) ;
2014-06-03 16:50:53 +04:00
2007-04-16 08:59:47 +04:00
break ;
}
2019-03-21 12:02:54 +03:00
2007-04-16 08:59:47 +04:00
if ( prt = = 10000 ) {
errno = ENFILE ;
2019-03-21 12:02:54 +03:00
SAFE_FREE ( swrap_dir ) ;
2007-04-16 08:59:47 +04:00
return - 1 ;
2005-11-07 18:36:51 +03:00
}
}
2020-06-08 15:18:00 +03:00
swrap_un_path ( un , swrap_dir , type , iface , prt ) ;
2014-04-07 18:12:21 +04:00
SWRAP_LOG ( SWRAP_LOG_DEBUG , " un path [%s] " , un - > sun_path ) ;
2019-03-21 12:02:54 +03:00
SAFE_FREE ( swrap_dir ) ;
2005-03-28 05:00:39 +04:00
return 0 ;
}
2017-11-07 14:29:51 +03:00
static struct socket_info * find_socket_info ( int fd )
{
int idx = find_socket_info_index ( fd ) ;
if ( idx = = - 1 ) {
return NULL ;
}
2018-05-02 16:57:38 +03:00
return swrap_get_socket_info ( idx ) ;
2017-11-07 14:29:51 +03:00
}
2014-06-06 01:38:59 +04:00
#if 0 /* FIXME */
2014-06-03 17:13:59 +04:00
static bool check_addr_port_in_use ( const struct sockaddr * sa , socklen_t len )
{
2017-11-07 14:29:51 +03:00
struct socket_info_fd * f ;
const struct socket_info * last_s = NULL ;
2014-06-03 17:13:59 +04:00
/* first catch invalid input */
switch ( sa - > sa_family ) {
case AF_INET :
if ( len < sizeof ( struct sockaddr_in ) ) {
return false ;
}
break ;
2019-03-21 12:02:54 +03:00
# ifdef HAVE_IPV6
2014-06-03 17:13:59 +04:00
case AF_INET6 :
if ( len < sizeof ( struct sockaddr_in6 ) ) {
return false ;
}
break ;
# endif
default :
return false ;
break ;
}
2017-11-07 14:29:51 +03:00
for ( f = socket_fds ; f ; f = f - > next ) {
2018-05-02 16:57:38 +03:00
struct socket_info * s = swrap_get_socket_info ( f - > si_index ) ;
2017-11-07 14:29:51 +03:00
if ( s = = last_s ) {
continue ;
}
last_s = s ;
2014-06-03 17:13:59 +04:00
if ( s - > myname = = NULL ) {
continue ;
}
if ( s - > myname - > sa_family ! = sa - > sa_family ) {
continue ;
}
switch ( s - > myname - > sa_family ) {
case AF_INET : {
struct sockaddr_in * sin1 , * sin2 ;
sin1 = ( struct sockaddr_in * ) s - > myname ;
sin2 = ( struct sockaddr_in * ) sa ;
if ( sin1 - > sin_addr . s_addr = = htonl ( INADDR_ANY ) ) {
continue ;
}
if ( sin1 - > sin_port ! = sin2 - > sin_port ) {
continue ;
}
if ( sin1 - > sin_addr . s_addr ! = sin2 - > sin_addr . s_addr ) {
continue ;
}
/* found */
return true ;
break ;
}
2019-03-21 12:02:54 +03:00
# ifdef HAVE_IPV6
2014-06-03 17:13:59 +04:00
case AF_INET6 : {
struct sockaddr_in6 * sin1 , * sin2 ;
sin1 = ( struct sockaddr_in6 * ) s - > myname ;
sin2 = ( struct sockaddr_in6 * ) sa ;
if ( sin1 - > sin6_port ! = sin2 - > sin6_port ) {
continue ;
}
if ( ! IN6_ARE_ADDR_EQUAL ( & sin1 - > sin6_addr ,
& sin2 - > sin6_addr ) )
{
continue ;
}
/* found */
return true ;
break ;
}
# endif
default :
continue ;
break ;
}
}
return false ;
}
2014-06-06 01:38:59 +04:00
# endif
2014-06-03 17:13:59 +04:00
2021-02-17 14:57:01 +03:00
static void swrap_remove_stale ( int fd ) ;
2014-04-07 18:12:21 +04:00
static int sockaddr_convert_to_un ( struct socket_info * si ,
const struct sockaddr * in_addr ,
socklen_t in_len ,
struct sockaddr_un * out_addr ,
int alloc_sock ,
int * bcast )
2005-03-28 05:00:39 +04:00
{
2010-11-05 11:43:05 +03:00
struct sockaddr * out = ( struct sockaddr * ) ( void * ) out_addr ;
2014-04-07 18:12:21 +04:00
( void ) in_len ; /* unused */
if ( out_addr = = NULL ) {
2005-03-28 05:00:39 +04:00
return 0 ;
2014-04-07 18:12:21 +04:00
}
2005-03-28 05:00:39 +04:00
2010-11-05 11:43:05 +03:00
out - > sa_family = AF_UNIX ;
# ifdef HAVE_STRUCT_SOCKADDR_SA_LEN
out - > sa_len = sizeof ( * out_addr ) ;
# endif
2005-03-31 03:28:15 +04:00
2005-03-28 05:00:39 +04:00
switch ( in_addr - > sa_family ) {
2014-06-03 17:13:02 +04:00
case AF_UNSPEC : {
2014-10-02 09:01:34 +04:00
const struct sockaddr_in * sin ;
2014-06-03 17:13:02 +04:00
if ( si - > family ! = AF_INET ) {
break ;
}
if ( in_len < sizeof ( struct sockaddr_in ) ) {
break ;
}
2014-10-02 09:23:25 +04:00
sin = ( const struct sockaddr_in * ) ( const void * ) in_addr ;
2014-06-03 17:13:02 +04:00
if ( sin - > sin_addr . s_addr ! = htonl ( INADDR_ANY ) ) {
break ;
}
/*
* Note : in the special case of AF_UNSPEC and INADDR_ANY ,
* AF_UNSPEC is mapped to AF_INET and must be treated here .
*/
2017-11-07 14:29:51 +03:00
FALL_THROUGH ;
2014-06-03 17:13:02 +04:00
}
2005-03-28 05:00:39 +04:00
case AF_INET :
2007-04-16 08:59:47 +04:00
# ifdef HAVE_IPV6
case AF_INET6 :
# endif
2005-11-07 18:36:51 +03:00
switch ( si - > type ) {
case SOCK_STREAM :
case SOCK_DGRAM :
break ;
default :
2020-06-08 15:18:00 +03:00
SWRAP_LOG ( SWRAP_LOG_ERROR , " Unknown socket type! " ) ;
2005-11-07 18:36:51 +03:00
errno = ESOCKTNOSUPPORT ;
return - 1 ;
}
if ( alloc_sock ) {
2007-04-16 08:59:47 +04:00
return convert_in_un_alloc ( si , in_addr , out_addr , bcast ) ;
2005-11-07 18:36:51 +03:00
} else {
2007-04-16 08:59:47 +04:00
return convert_in_un_remote ( si , in_addr , out_addr , bcast ) ;
2005-11-07 18:36:51 +03:00
}
2005-03-28 05:00:39 +04:00
default :
break ;
}
2011-02-12 14:18:16 +03:00
2005-03-28 05:00:39 +04:00
errno = EAFNOSUPPORT ;
2020-06-08 15:18:00 +03:00
SWRAP_LOG ( SWRAP_LOG_ERROR , " Unknown address family " ) ;
2005-03-28 05:00:39 +04:00
return - 1 ;
}
2014-10-02 09:20:53 +04:00
static int sockaddr_convert_from_un ( const struct socket_info * si ,
const struct sockaddr_un * in_addr ,
2005-03-31 16:40:12 +04:00
socklen_t un_addrlen ,
int family ,
struct sockaddr * out_addr ,
2007-04-16 08:59:47 +04:00
socklen_t * out_addrlen )
2005-03-28 05:00:39 +04:00
{
2010-11-05 11:43:05 +03:00
int ret ;
2014-10-02 09:20:53 +04:00
if ( out_addr = = NULL | | out_addrlen = = NULL )
2005-03-28 05:00:39 +04:00
return 0 ;
2005-03-31 16:40:12 +04:00
if ( un_addrlen = = 0 ) {
2007-04-16 08:59:47 +04:00
* out_addrlen = 0 ;
2005-03-31 16:40:12 +04:00
return 0 ;
}
2005-03-28 05:00:39 +04:00
switch ( family ) {
case AF_INET :
2007-04-16 08:59:47 +04:00
# ifdef HAVE_IPV6
case AF_INET6 :
# endif
2005-11-07 18:36:51 +03:00
switch ( si - > type ) {
case SOCK_STREAM :
case SOCK_DGRAM :
break ;
default :
2020-06-08 15:18:00 +03:00
SWRAP_LOG ( SWRAP_LOG_ERROR , " Unknown socket type! " ) ;
2005-11-07 18:36:51 +03:00
errno = ESOCKTNOSUPPORT ;
return - 1 ;
}
2010-11-05 11:43:05 +03:00
ret = convert_un_in ( in_addr , out_addr , out_addrlen ) ;
# ifdef HAVE_STRUCT_SOCKADDR_SA_LEN
out_addr - > sa_len = * out_addrlen ;
# endif
return ret ;
2005-03-28 05:00:39 +04:00
default :
break ;
}
2020-06-08 15:18:00 +03:00
SWRAP_LOG ( SWRAP_LOG_ERROR , " Unknown address family " ) ;
2005-03-28 05:00:39 +04:00
errno = EAFNOSUPPORT ;
return - 1 ;
}
2006-09-12 10:19:11 +04:00
enum swrap_packet_type {
2006-09-29 13:31:20 +04:00
SWRAP_CONNECT_SEND ,
SWRAP_CONNECT_UNREACH ,
SWRAP_CONNECT_RECV ,
SWRAP_CONNECT_ACK ,
SWRAP_ACCEPT_SEND ,
SWRAP_ACCEPT_RECV ,
SWRAP_ACCEPT_ACK ,
2006-09-12 10:19:11 +04:00
SWRAP_RECVFROM ,
SWRAP_SENDTO ,
2006-09-29 13:31:20 +04:00
SWRAP_SENDTO_UNREACH ,
SWRAP_PENDING_RST ,
2006-09-12 10:19:11 +04:00
SWRAP_RECV ,
2006-09-29 13:31:20 +04:00
SWRAP_RECV_RST ,
2006-09-12 13:08:55 +04:00
SWRAP_SEND ,
2006-09-29 13:31:20 +04:00
SWRAP_SEND_RST ,
SWRAP_CLOSE_SEND ,
SWRAP_CLOSE_RECV ,
2009-09-08 07:31:01 +04:00
SWRAP_CLOSE_ACK ,
2006-09-12 10:19:11 +04:00
} ;
2006-10-05 15:39:59 +04:00
struct swrap_file_hdr {
2008-03-17 16:08:57 +03:00
uint32_t magic ;
uint16_t version_major ;
uint16_t version_minor ;
int32_t timezone ;
uint32_t sigfigs ;
uint32_t frame_max_len ;
2006-10-05 15:39:59 +04:00
# define SWRAP_FRAME_LENGTH_MAX 0xFFFF
2008-03-17 16:08:57 +03:00
uint32_t link_type ;
2006-10-05 15:39:59 +04:00
} ;
# define SWRAP_FILE_HDR_SIZE 24
2009-03-03 16:58:53 +03:00
struct swrap_packet_frame {
uint32_t seconds ;
uint32_t micro_seconds ;
uint32_t recorded_length ;
uint32_t full_length ;
} ;
# define SWRAP_PACKET_FRAME_SIZE 16
union swrap_packet_ip {
2006-10-05 15:39:59 +04:00
struct {
2009-03-03 16:58:53 +03:00
uint8_t ver_hdrlen ;
uint8_t tos ;
uint16_t packet_length ;
uint16_t identification ;
uint8_t flags ;
uint8_t fragment ;
uint8_t ttl ;
uint8_t protocol ;
uint16_t hdr_checksum ;
uint32_t src_addr ;
uint32_t dest_addr ;
} v4 ;
# define SWRAP_PACKET_IP_V4_SIZE 20
2009-03-03 17:43:22 +03:00
struct {
uint8_t ver_prio ;
uint8_t flow_label_high ;
uint16_t flow_label_low ;
uint16_t payload_length ;
uint8_t next_header ;
uint8_t hop_limit ;
uint8_t src_addr [ 16 ] ;
uint8_t dest_addr [ 16 ] ;
} v6 ;
# define SWRAP_PACKET_IP_V6_SIZE 40
2009-03-03 16:58:53 +03:00
} ;
2009-03-03 17:43:22 +03:00
# define SWRAP_PACKET_IP_SIZE 40
2006-10-05 15:39:59 +04:00
2009-03-03 16:58:53 +03:00
union swrap_packet_payload {
2006-10-05 15:39:59 +04:00
struct {
2009-03-03 16:58:53 +03:00
uint16_t source_port ;
uint16_t dest_port ;
uint32_t seq_num ;
uint32_t ack_num ;
uint8_t hdr_length ;
uint8_t control ;
uint16_t window ;
uint16_t checksum ;
uint16_t urg ;
} tcp ;
# define SWRAP_PACKET_PAYLOAD_TCP_SIZE 20
struct {
uint16_t source_port ;
uint16_t dest_port ;
uint16_t length ;
uint16_t checksum ;
} udp ;
# define SWRAP_PACKET_PAYLOAD_UDP_SIZE 8
struct {
uint8_t type ;
uint8_t code ;
uint16_t checksum ;
uint32_t unused ;
} icmp4 ;
# define SWRAP_PACKET_PAYLOAD_ICMP4_SIZE 8
2009-03-03 17:43:22 +03:00
struct {
uint8_t type ;
uint8_t code ;
uint16_t checksum ;
uint32_t unused ;
} icmp6 ;
# define SWRAP_PACKET_PAYLOAD_ICMP6_SIZE 8
2006-10-05 15:39:59 +04:00
} ;
2009-03-03 16:58:53 +03:00
# define SWRAP_PACKET_PAYLOAD_SIZE 20
# define SWRAP_PACKET_MIN_ALLOC \
( SWRAP_PACKET_FRAME_SIZE + \
SWRAP_PACKET_IP_SIZE + \
SWRAP_PACKET_PAYLOAD_SIZE )
2006-10-05 15:39:59 +04:00
2014-10-02 09:11:49 +04:00
static const char * swrap_pcap_init_file ( void )
2006-10-05 15:39:59 +04:00
{
static int initialized = 0 ;
static const char * s = NULL ;
2009-03-03 16:58:53 +03:00
static const struct swrap_file_hdr h ;
static const struct swrap_packet_frame f ;
static const union swrap_packet_ip i ;
static const union swrap_packet_payload p ;
2006-10-05 15:39:59 +04:00
if ( initialized = = 1 ) {
return s ;
}
initialized = 1 ;
/*
* TODO : don ' t use the structs use plain buffer offsets
* and PUSH_U8 ( ) , PUSH_U16 ( ) and PUSH_U32 ( )
2014-10-02 09:20:53 +04:00
*
2006-10-05 15:39:59 +04:00
* for now make sure we disable PCAP support
* if the struct has alignment !
*/
if ( sizeof ( h ) ! = SWRAP_FILE_HDR_SIZE ) {
return NULL ;
}
2009-03-03 16:58:53 +03:00
if ( sizeof ( f ) ! = SWRAP_PACKET_FRAME_SIZE ) {
2006-10-05 15:39:59 +04:00
return NULL ;
}
2009-03-03 16:58:53 +03:00
if ( sizeof ( i ) ! = SWRAP_PACKET_IP_SIZE ) {
2006-10-05 15:39:59 +04:00
return NULL ;
}
2009-03-03 16:58:53 +03:00
if ( sizeof ( i . v4 ) ! = SWRAP_PACKET_IP_V4_SIZE ) {
2006-10-05 15:39:59 +04:00
return NULL ;
}
2009-03-03 17:43:22 +03:00
if ( sizeof ( i . v6 ) ! = SWRAP_PACKET_IP_V6_SIZE ) {
return NULL ;
}
2009-03-03 16:58:53 +03:00
if ( sizeof ( p ) ! = SWRAP_PACKET_PAYLOAD_SIZE ) {
2006-10-05 15:39:59 +04:00
return NULL ;
}
2009-03-03 16:58:53 +03:00
if ( sizeof ( p . tcp ) ! = SWRAP_PACKET_PAYLOAD_TCP_SIZE ) {
2006-10-05 15:39:59 +04:00
return NULL ;
}
2009-03-03 16:58:53 +03:00
if ( sizeof ( p . udp ) ! = SWRAP_PACKET_PAYLOAD_UDP_SIZE ) {
return NULL ;
}
if ( sizeof ( p . icmp4 ) ! = SWRAP_PACKET_PAYLOAD_ICMP4_SIZE ) {
2006-10-05 15:39:59 +04:00
return NULL ;
}
2009-03-03 17:43:22 +03:00
if ( sizeof ( p . icmp6 ) ! = SWRAP_PACKET_PAYLOAD_ICMP6_SIZE ) {
return NULL ;
}
2006-10-05 15:39:59 +04:00
s = getenv ( " SOCKET_WRAPPER_PCAP_FILE " ) ;
if ( s = = NULL ) {
return NULL ;
}
if ( strncmp ( s , " ./ " , 2 ) = = 0 ) {
s + = 2 ;
}
2020-03-10 15:27:27 +03:00
SWRAP_LOG ( SWRAP_LOG_TRACE , " SOCKET_WRAPPER_PCAP_FILE: %s " , s ) ;
2006-10-05 15:39:59 +04:00
return s ;
}
2014-10-02 09:13:10 +04:00
static uint8_t * swrap_pcap_packet_init ( struct timeval * tval ,
const struct sockaddr * src ,
const struct sockaddr * dest ,
int socket_type ,
const uint8_t * payload ,
size_t payload_len ,
unsigned long tcp_seqno ,
unsigned long tcp_ack ,
unsigned char tcp_ctl ,
int unreachable ,
size_t * _packet_len )
2006-10-05 15:39:59 +04:00
{
2019-03-21 12:02:54 +03:00
uint8_t * base = NULL ;
uint8_t * buf = NULL ;
union {
uint8_t * ptr ;
struct swrap_packet_frame * frame ;
} f ;
union {
uint8_t * ptr ;
union swrap_packet_ip * ip ;
} i ;
2009-03-03 16:58:53 +03:00
union swrap_packet_payload * pay ;
2006-10-05 15:39:59 +04:00
size_t packet_len ;
size_t alloc_len ;
2019-03-21 12:02:54 +03:00
size_t nonwire_len = sizeof ( struct swrap_packet_frame ) ;
2006-10-06 19:16:18 +04:00
size_t wire_hdr_len = 0 ;
size_t wire_len = 0 ;
2009-03-03 17:17:26 +03:00
size_t ip_hdr_len = 0 ;
2006-10-05 15:39:59 +04:00
size_t icmp_hdr_len = 0 ;
size_t icmp_truncate_len = 0 ;
2009-03-03 16:58:53 +03:00
uint8_t protocol = 0 , icmp_protocol = 0 ;
2009-03-04 23:59:16 +03:00
const struct sockaddr_in * src_in = NULL ;
const struct sockaddr_in * dest_in = NULL ;
2009-03-03 17:43:22 +03:00
# ifdef HAVE_IPV6
2009-03-04 23:59:16 +03:00
const struct sockaddr_in6 * src_in6 = NULL ;
const struct sockaddr_in6 * dest_in6 = NULL ;
2009-03-03 17:43:22 +03:00
# endif
2009-03-03 17:17:26 +03:00
uint16_t src_port ;
uint16_t dest_port ;
switch ( src - > sa_family ) {
case AF_INET :
2014-10-02 09:23:25 +04:00
src_in = ( const struct sockaddr_in * ) ( const void * ) src ;
dest_in = ( const struct sockaddr_in * ) ( const void * ) dest ;
2009-03-03 17:17:26 +03:00
src_port = src_in - > sin_port ;
dest_port = dest_in - > sin_port ;
2019-03-21 12:02:54 +03:00
ip_hdr_len = sizeof ( i . ip - > v4 ) ;
2009-03-03 17:17:26 +03:00
break ;
2009-03-03 17:43:22 +03:00
# ifdef HAVE_IPV6
case AF_INET6 :
2014-10-02 09:23:25 +04:00
src_in6 = ( const struct sockaddr_in6 * ) ( const void * ) src ;
dest_in6 = ( const struct sockaddr_in6 * ) ( const void * ) dest ;
2009-03-03 17:43:22 +03:00
src_port = src_in6 - > sin6_port ;
dest_port = dest_in6 - > sin6_port ;
2019-03-21 12:02:54 +03:00
ip_hdr_len = sizeof ( i . ip - > v6 ) ;
2009-03-03 17:43:22 +03:00
break ;
# endif
2009-03-03 17:17:26 +03:00
default :
return NULL ;
}
2006-10-05 15:39:59 +04:00
switch ( socket_type ) {
case SOCK_STREAM :
protocol = 0x06 ; /* TCP */
2009-03-03 16:58:53 +03:00
wire_hdr_len = ip_hdr_len + sizeof ( pay - > tcp ) ;
2006-10-05 15:39:59 +04:00
wire_len = wire_hdr_len + payload_len ;
break ;
case SOCK_DGRAM :
protocol = 0x11 ; /* UDP */
2009-03-03 16:58:53 +03:00
wire_hdr_len = ip_hdr_len + sizeof ( pay - > udp ) ;
2006-10-05 15:39:59 +04:00
wire_len = wire_hdr_len + payload_len ;
break ;
2007-06-11 18:41:14 +04:00
default :
return NULL ;
2006-10-05 15:39:59 +04:00
}
if ( unreachable ) {
icmp_protocol = protocol ;
2009-03-03 17:43:22 +03:00
switch ( src - > sa_family ) {
case AF_INET :
protocol = 0x01 ; /* ICMPv4 */
icmp_hdr_len = ip_hdr_len + sizeof ( pay - > icmp4 ) ;
break ;
# ifdef HAVE_IPV6
case AF_INET6 :
protocol = 0x3A ; /* ICMPv6 */
icmp_hdr_len = ip_hdr_len + sizeof ( pay - > icmp6 ) ;
break ;
# endif
}
2006-10-05 15:39:59 +04:00
if ( wire_len > 64 ) {
icmp_truncate_len = wire_len - 64 ;
}
wire_len + = icmp_hdr_len ;
}
packet_len = nonwire_len + wire_len ;
alloc_len = packet_len ;
2009-03-03 16:58:53 +03:00
if ( alloc_len < SWRAP_PACKET_MIN_ALLOC ) {
alloc_len = SWRAP_PACKET_MIN_ALLOC ;
2006-10-05 15:39:59 +04:00
}
2009-03-03 16:58:53 +03:00
2016-03-15 17:47:08 +03:00
base = ( uint8_t * ) calloc ( 1 , alloc_len ) ;
2014-04-07 18:12:21 +04:00
if ( base = = NULL ) {
return NULL ;
}
2009-03-03 16:58:53 +03:00
buf = base ;
2019-03-21 12:02:54 +03:00
f . ptr = buf ;
f . frame - > seconds = tval - > tv_sec ;
f . frame - > micro_seconds = tval - > tv_usec ;
f . frame - > recorded_length = wire_len - icmp_truncate_len ;
f . frame - > full_length = wire_len - icmp_truncate_len ;
2009-03-03 16:58:53 +03:00
buf + = SWRAP_PACKET_FRAME_SIZE ;
2019-03-21 12:02:54 +03:00
i . ptr = buf ;
2009-03-03 17:17:26 +03:00
switch ( src - > sa_family ) {
case AF_INET :
2019-03-21 12:02:54 +03:00
if ( src_in = = NULL | | dest_in = = NULL ) {
SAFE_FREE ( base ) ;
return NULL ;
}
i . ip - > v4 . ver_hdrlen = 0x45 ; /* version 4 and 5 * 32 bit words */
i . ip - > v4 . tos = 0x00 ;
i . ip - > v4 . packet_length = htons ( wire_len - icmp_truncate_len ) ;
i . ip - > v4 . identification = htons ( 0xFFFF ) ;
i . ip - > v4 . flags = 0x40 ; /* BIT 1 set - means don't fragment */
i . ip - > v4 . fragment = htons ( 0x0000 ) ;
i . ip - > v4 . ttl = 0xFF ;
i . ip - > v4 . protocol = protocol ;
i . ip - > v4 . hdr_checksum = htons ( 0x0000 ) ;
i . ip - > v4 . src_addr = src_in - > sin_addr . s_addr ;
i . ip - > v4 . dest_addr = dest_in - > sin_addr . s_addr ;
2009-03-03 16:58:53 +03:00
buf + = SWRAP_PACKET_IP_V4_SIZE ;
2009-03-03 17:17:26 +03:00
break ;
2009-03-03 17:43:22 +03:00
# ifdef HAVE_IPV6
case AF_INET6 :
2019-03-21 12:02:54 +03:00
if ( src_in6 = = NULL | | dest_in6 = = NULL ) {
SAFE_FREE ( base ) ;
return NULL ;
}
i . ip - > v6 . ver_prio = 0x60 ; /* version 4 and 5 * 32 bit words */
i . ip - > v6 . flow_label_high = 0x00 ;
i . ip - > v6 . flow_label_low = 0x0000 ;
i . ip - > v6 . payload_length = htons ( wire_len - icmp_truncate_len ) ; /* TODO */
i . ip - > v6 . next_header = protocol ;
memcpy ( i . ip - > v6 . src_addr , src_in6 - > sin6_addr . s6_addr , 16 ) ;
memcpy ( i . ip - > v6 . dest_addr , dest_in6 - > sin6_addr . s6_addr , 16 ) ;
2009-03-03 17:43:22 +03:00
buf + = SWRAP_PACKET_IP_V6_SIZE ;
break ;
# endif
2009-03-03 17:17:26 +03:00
}
2006-10-05 15:39:59 +04:00
2009-03-03 17:17:26 +03:00
if ( unreachable ) {
2014-10-02 09:23:25 +04:00
pay = ( union swrap_packet_payload * ) ( void * ) buf ;
2009-03-03 17:17:26 +03:00
switch ( src - > sa_family ) {
case AF_INET :
pay - > icmp4 . type = 0x03 ; /* destination unreachable */
pay - > icmp4 . code = 0x01 ; /* host unreachable */
pay - > icmp4 . checksum = htons ( 0x0000 ) ;
pay - > icmp4 . unused = htonl ( 0x00000000 ) ;
2019-03-21 12:02:54 +03:00
2009-03-03 17:17:26 +03:00
buf + = SWRAP_PACKET_PAYLOAD_ICMP4_SIZE ;
/* set the ip header in the ICMP payload */
2019-03-21 12:02:54 +03:00
i . ptr = buf ;
i . ip - > v4 . ver_hdrlen = 0x45 ; /* version 4 and 5 * 32 bit words */
i . ip - > v4 . tos = 0x00 ;
i . ip - > v4 . packet_length = htons ( wire_len - icmp_hdr_len ) ;
i . ip - > v4 . identification = htons ( 0xFFFF ) ;
i . ip - > v4 . flags = 0x40 ; /* BIT 1 set - means don't fragment */
i . ip - > v4 . fragment = htons ( 0x0000 ) ;
i . ip - > v4 . ttl = 0xFF ;
i . ip - > v4 . protocol = icmp_protocol ;
i . ip - > v4 . hdr_checksum = htons ( 0x0000 ) ;
i . ip - > v4 . src_addr = dest_in - > sin_addr . s_addr ;
i . ip - > v4 . dest_addr = src_in - > sin_addr . s_addr ;
2009-03-03 17:17:26 +03:00
buf + = SWRAP_PACKET_IP_V4_SIZE ;
src_port = dest_in - > sin_port ;
dest_port = src_in - > sin_port ;
break ;
2009-03-03 17:43:22 +03:00
# ifdef HAVE_IPV6
case AF_INET6 :
pay - > icmp6 . type = 0x01 ; /* destination unreachable */
pay - > icmp6 . code = 0x03 ; /* address unreachable */
pay - > icmp6 . checksum = htons ( 0x0000 ) ;
pay - > icmp6 . unused = htonl ( 0x00000000 ) ;
buf + = SWRAP_PACKET_PAYLOAD_ICMP6_SIZE ;
/* set the ip header in the ICMP payload */
2019-03-21 12:02:54 +03:00
i . ptr = buf ;
i . ip - > v6 . ver_prio = 0x60 ; /* version 4 and 5 * 32 bit words */
i . ip - > v6 . flow_label_high = 0x00 ;
i . ip - > v6 . flow_label_low = 0x0000 ;
i . ip - > v6 . payload_length = htons ( wire_len - icmp_truncate_len ) ; /* TODO */
i . ip - > v6 . next_header = protocol ;
memcpy ( i . ip - > v6 . src_addr , dest_in6 - > sin6_addr . s6_addr , 16 ) ;
memcpy ( i . ip - > v6 . dest_addr , src_in6 - > sin6_addr . s6_addr , 16 ) ;
2009-03-03 17:43:22 +03:00
buf + = SWRAP_PACKET_IP_V6_SIZE ;
src_port = dest_in6 - > sin6_port ;
dest_port = src_in6 - > sin6_port ;
break ;
# endif
2009-03-03 17:17:26 +03:00
}
2006-10-05 15:39:59 +04:00
}
2014-10-02 09:23:25 +04:00
pay = ( union swrap_packet_payload * ) ( void * ) buf ;
2009-03-03 16:58:53 +03:00
2006-10-05 15:39:59 +04:00
switch ( socket_type ) {
case SOCK_STREAM :
2009-03-03 16:58:53 +03:00
pay - > tcp . source_port = src_port ;
pay - > tcp . dest_port = dest_port ;
pay - > tcp . seq_num = htonl ( tcp_seqno ) ;
pay - > tcp . ack_num = htonl ( tcp_ack ) ;
pay - > tcp . hdr_length = 0x50 ; /* 5 * 32 bit words */
pay - > tcp . control = tcp_ctl ;
pay - > tcp . window = htons ( 0x7FFF ) ;
pay - > tcp . checksum = htons ( 0x0000 ) ;
pay - > tcp . urg = htons ( 0x0000 ) ;
buf + = SWRAP_PACKET_PAYLOAD_TCP_SIZE ;
2006-10-05 15:39:59 +04:00
break ;
case SOCK_DGRAM :
2009-03-03 17:17:26 +03:00
pay - > udp . source_port = src_port ;
pay - > udp . dest_port = dest_port ;
2009-03-03 16:58:53 +03:00
pay - > udp . length = htons ( 8 + payload_len ) ;
pay - > udp . checksum = htons ( 0x0000 ) ;
buf + = SWRAP_PACKET_PAYLOAD_UDP_SIZE ;
2006-10-05 15:39:59 +04:00
break ;
}
if ( payload & & payload_len > 0 ) {
2009-03-03 16:58:53 +03:00
memcpy ( buf , payload , payload_len ) ;
2006-10-05 15:39:59 +04:00
}
* _packet_len = packet_len - icmp_truncate_len ;
2009-03-03 16:58:53 +03:00
return base ;
2006-10-05 15:39:59 +04:00
}
2014-10-02 09:14:44 +04:00
static int swrap_pcap_get_fd ( const char * fname )
2006-10-05 15:39:59 +04:00
{
static int fd = - 1 ;
2017-11-07 14:29:51 +03:00
if ( fd ! = - 1 ) {
return fd ;
}
2006-10-05 15:39:59 +04:00
2014-05-08 16:05:30 +04:00
fd = libc_open ( fname , O_WRONLY | O_CREAT | O_EXCL | O_APPEND , 0644 ) ;
2006-10-05 15:39:59 +04:00
if ( fd ! = - 1 ) {
struct swrap_file_hdr file_hdr ;
file_hdr . magic = 0xA1B2C3D4 ;
2017-11-07 12:51:11 +03:00
file_hdr . version_major = 0x0002 ;
2006-10-05 15:39:59 +04:00
file_hdr . version_minor = 0x0004 ;
file_hdr . timezone = 0x00000000 ;
file_hdr . sigfigs = 0x00000000 ;
file_hdr . frame_max_len = SWRAP_FRAME_LENGTH_MAX ;
file_hdr . link_type = 0x0065 ; /* 101 RAW IP */
2021-02-17 14:57:01 +03:00
if ( libc_write ( fd , & file_hdr , sizeof ( file_hdr ) ) ! = sizeof ( file_hdr ) ) {
2021-02-09 10:56:42 +03:00
libc_close ( fd ) ;
2009-01-20 02:37:57 +03:00
fd = - 1 ;
2008-12-23 07:08:14 +03:00
}
2006-10-05 15:39:59 +04:00
return fd ;
}
2014-05-08 16:05:30 +04:00
fd = libc_open ( fname , O_WRONLY | O_APPEND , 0644 ) ;
2006-10-05 15:39:59 +04:00
return fd ;
}
2014-10-02 09:14:04 +04:00
static uint8_t * swrap_pcap_marshall_packet ( struct socket_info * si ,
const struct sockaddr * addr ,
enum swrap_packet_type type ,
const void * buf , size_t len ,
size_t * packet_len )
2006-09-12 10:19:11 +04:00
{
2009-03-03 17:17:26 +03:00
const struct sockaddr * src_addr ;
const struct sockaddr * dest_addr ;
2008-10-07 21:56:30 +04:00
unsigned long tcp_seqno = 0 ;
2006-10-05 11:03:41 +04:00
unsigned long tcp_ack = 0 ;
unsigned char tcp_ctl = 0 ;
2006-10-05 10:27:41 +04:00
int unreachable = 0 ;
2006-09-29 13:31:20 +04:00
2008-02-20 01:53:04 +03:00
struct timeval tv ;
2006-09-12 10:19:11 +04:00
2007-04-16 08:59:47 +04:00
switch ( si - > family ) {
case AF_INET :
break ;
2009-04-14 14:45:48 +04:00
# ifdef HAVE_IPV6
2009-03-03 17:43:22 +03:00
case AF_INET6 :
break ;
2009-04-14 14:45:48 +04:00
# endif
2007-04-16 08:59:47 +04:00
default :
2008-02-20 01:53:04 +03:00
return NULL ;
2006-09-29 13:31:20 +04:00
}
2006-10-05 10:27:41 +04:00
switch ( type ) {
case SWRAP_CONNECT_SEND :
2017-11-07 14:29:51 +03:00
if ( si - > type ! = SOCK_STREAM ) {
return NULL ;
}
2006-10-05 10:27:41 +04:00
2014-10-02 09:17:10 +04:00
src_addr = & si - > myname . sa . s ;
2009-03-03 17:17:26 +03:00
dest_addr = addr ;
2006-10-05 10:27:41 +04:00
2008-10-07 21:56:30 +04:00
tcp_seqno = si - > io . pck_snd ;
2006-10-05 10:27:41 +04:00
tcp_ack = si - > io . pck_rcv ;
tcp_ctl = 0x02 ; /* SYN */
si - > io . pck_snd + = 1 ;
break ;
case SWRAP_CONNECT_RECV :
2017-11-07 14:29:51 +03:00
if ( si - > type ! = SOCK_STREAM ) {
return NULL ;
}
2006-10-05 10:27:41 +04:00
2014-10-02 09:17:10 +04:00
dest_addr = & si - > myname . sa . s ;
2009-03-03 17:17:26 +03:00
src_addr = addr ;
2006-10-05 10:27:41 +04:00
2008-10-07 21:56:30 +04:00
tcp_seqno = si - > io . pck_rcv ;
2006-10-05 10:27:41 +04:00
tcp_ack = si - > io . pck_snd ;
tcp_ctl = 0x12 ; /** SYN,ACK */
si - > io . pck_rcv + = 1 ;
break ;
case SWRAP_CONNECT_UNREACH :
2017-11-07 14:29:51 +03:00
if ( si - > type ! = SOCK_STREAM ) {
return NULL ;
}
2006-10-05 10:27:41 +04:00
2014-10-02 09:17:10 +04:00
dest_addr = & si - > myname . sa . s ;
src_addr = addr ;
2006-10-05 10:27:41 +04:00
/* Unreachable: resend the data of SWRAP_CONNECT_SEND */
2008-10-07 21:56:30 +04:00
tcp_seqno = si - > io . pck_snd - 1 ;
2006-10-05 10:27:41 +04:00
tcp_ack = si - > io . pck_rcv ;
tcp_ctl = 0x02 ; /* SYN */
unreachable = 1 ;
break ;
case SWRAP_CONNECT_ACK :
2017-11-07 14:29:51 +03:00
if ( si - > type ! = SOCK_STREAM ) {
return NULL ;
}
2006-10-05 10:27:41 +04:00
2014-10-02 09:17:10 +04:00
src_addr = & si - > myname . sa . s ;
2009-03-03 17:17:26 +03:00
dest_addr = addr ;
2006-10-05 10:27:41 +04:00
2008-10-07 21:56:30 +04:00
tcp_seqno = si - > io . pck_snd ;
2006-10-05 10:27:41 +04:00
tcp_ack = si - > io . pck_rcv ;
tcp_ctl = 0x10 ; /* ACK */
break ;
case SWRAP_ACCEPT_SEND :
2017-11-07 14:29:51 +03:00
if ( si - > type ! = SOCK_STREAM ) {
return NULL ;
}
2006-10-05 10:27:41 +04:00
2014-10-02 09:17:10 +04:00
dest_addr = & si - > myname . sa . s ;
2009-03-03 17:17:26 +03:00
src_addr = addr ;
2006-10-05 10:27:41 +04:00
2008-10-07 21:56:30 +04:00
tcp_seqno = si - > io . pck_rcv ;
2006-10-05 10:27:41 +04:00
tcp_ack = si - > io . pck_snd ;
tcp_ctl = 0x02 ; /* SYN */
si - > io . pck_rcv + = 1 ;
break ;
case SWRAP_ACCEPT_RECV :
2017-11-07 14:29:51 +03:00
if ( si - > type ! = SOCK_STREAM ) {
return NULL ;
}
2006-10-05 10:27:41 +04:00
2014-10-02 09:17:10 +04:00
src_addr = & si - > myname . sa . s ;
2009-03-03 17:17:26 +03:00
dest_addr = addr ;
2006-10-05 10:27:41 +04:00
2008-10-07 21:56:30 +04:00
tcp_seqno = si - > io . pck_snd ;
2006-10-05 10:27:41 +04:00
tcp_ack = si - > io . pck_rcv ;
tcp_ctl = 0x12 ; /* SYN,ACK */
si - > io . pck_snd + = 1 ;
break ;
case SWRAP_ACCEPT_ACK :
2017-11-07 14:29:51 +03:00
if ( si - > type ! = SOCK_STREAM ) {
return NULL ;
}
2006-10-05 10:27:41 +04:00
2014-10-02 09:17:10 +04:00
dest_addr = & si - > myname . sa . s ;
2009-03-03 17:17:26 +03:00
src_addr = addr ;
2006-10-05 10:27:41 +04:00
2008-10-07 21:56:30 +04:00
tcp_seqno = si - > io . pck_rcv ;
2006-10-05 10:27:41 +04:00
tcp_ack = si - > io . pck_snd ;
tcp_ctl = 0x10 ; /* ACK */
break ;
case SWRAP_SEND :
2014-10-02 09:17:10 +04:00
src_addr = & si - > myname . sa . s ;
dest_addr = & si - > peername . sa . s ;
2006-10-05 10:27:41 +04:00
2008-10-07 21:56:30 +04:00
tcp_seqno = si - > io . pck_snd ;
2006-10-05 10:27:41 +04:00
tcp_ack = si - > io . pck_rcv ;
tcp_ctl = 0x18 ; /* PSH,ACK */
si - > io . pck_snd + = len ;
break ;
case SWRAP_SEND_RST :
2014-10-02 09:17:10 +04:00
dest_addr = & si - > myname . sa . s ;
src_addr = & si - > peername . sa . s ;
2006-10-05 10:27:41 +04:00
if ( si - > type = = SOCK_DGRAM ) {
2014-10-02 09:17:10 +04:00
return swrap_pcap_marshall_packet ( si ,
& si - > peername . sa . s ,
SWRAP_SENDTO_UNREACH ,
buf ,
len ,
packet_len ) ;
2006-10-05 10:27:41 +04:00
}
2008-10-07 21:56:30 +04:00
tcp_seqno = si - > io . pck_rcv ;
2006-10-05 10:27:41 +04:00
tcp_ack = si - > io . pck_snd ;
tcp_ctl = 0x14 ; /** RST,ACK */
break ;
case SWRAP_PENDING_RST :
2014-10-02 09:17:10 +04:00
dest_addr = & si - > myname . sa . s ;
src_addr = & si - > peername . sa . s ;
2006-10-05 10:27:41 +04:00
if ( si - > type = = SOCK_DGRAM ) {
2008-02-20 01:53:04 +03:00
return NULL ;
2006-10-05 10:27:41 +04:00
}
2008-10-07 21:56:30 +04:00
tcp_seqno = si - > io . pck_rcv ;
2006-10-05 10:27:41 +04:00
tcp_ack = si - > io . pck_snd ;
tcp_ctl = 0x14 ; /* RST,ACK */
break ;
case SWRAP_RECV :
2014-10-02 09:17:10 +04:00
dest_addr = & si - > myname . sa . s ;
src_addr = & si - > peername . sa . s ;
2006-10-05 10:27:41 +04:00
2008-10-07 21:56:30 +04:00
tcp_seqno = si - > io . pck_rcv ;
2006-10-05 10:27:41 +04:00
tcp_ack = si - > io . pck_snd ;
tcp_ctl = 0x18 ; /* PSH,ACK */
si - > io . pck_rcv + = len ;
break ;
case SWRAP_RECV_RST :
2014-10-02 09:17:10 +04:00
dest_addr = & si - > myname . sa . s ;
src_addr = & si - > peername . sa . s ;
2006-10-05 10:27:41 +04:00
if ( si - > type = = SOCK_DGRAM ) {
2008-02-20 01:53:04 +03:00
return NULL ;
2006-10-05 10:27:41 +04:00
}
2008-10-07 21:56:30 +04:00
tcp_seqno = si - > io . pck_rcv ;
2006-10-05 10:27:41 +04:00
tcp_ack = si - > io . pck_snd ;
tcp_ctl = 0x14 ; /* RST,ACK */
break ;
case SWRAP_SENDTO :
2014-10-02 09:17:10 +04:00
src_addr = & si - > myname . sa . s ;
2009-03-03 17:17:26 +03:00
dest_addr = addr ;
2006-10-05 10:27:41 +04:00
si - > io . pck_snd + = len ;
break ;
case SWRAP_SENDTO_UNREACH :
2014-10-02 09:17:10 +04:00
dest_addr = & si - > myname . sa . s ;
2009-03-03 17:17:26 +03:00
src_addr = addr ;
2006-10-05 10:27:41 +04:00
unreachable = 1 ;
break ;
case SWRAP_RECVFROM :
2014-10-02 09:17:10 +04:00
dest_addr = & si - > myname . sa . s ;
2009-03-03 17:17:26 +03:00
src_addr = addr ;
2006-10-05 10:27:41 +04:00
si - > io . pck_rcv + = len ;
break ;
case SWRAP_CLOSE_SEND :
2017-11-07 14:29:51 +03:00
if ( si - > type ! = SOCK_STREAM ) {
return NULL ;
}
2006-10-05 10:27:41 +04:00
2014-10-02 09:17:10 +04:00
src_addr = & si - > myname . sa . s ;
dest_addr = & si - > peername . sa . s ;
2006-10-05 10:27:41 +04:00
2008-10-07 21:56:30 +04:00
tcp_seqno = si - > io . pck_snd ;
2006-10-05 10:27:41 +04:00
tcp_ack = si - > io . pck_rcv ;
tcp_ctl = 0x11 ; /* FIN, ACK */
si - > io . pck_snd + = 1 ;
break ;
case SWRAP_CLOSE_RECV :
2017-11-07 14:29:51 +03:00
if ( si - > type ! = SOCK_STREAM ) {
return NULL ;
}
2006-10-05 10:27:41 +04:00
2014-10-02 09:17:10 +04:00
dest_addr = & si - > myname . sa . s ;
src_addr = & si - > peername . sa . s ;
2006-10-05 10:27:41 +04:00
2008-10-07 21:56:30 +04:00
tcp_seqno = si - > io . pck_rcv ;
2006-10-05 10:27:41 +04:00
tcp_ack = si - > io . pck_snd ;
tcp_ctl = 0x11 ; /* FIN,ACK */
si - > io . pck_rcv + = 1 ;
break ;
case SWRAP_CLOSE_ACK :
2017-11-07 14:29:51 +03:00
if ( si - > type ! = SOCK_STREAM ) {
return NULL ;
}
2006-10-05 10:27:41 +04:00
2014-10-02 09:17:10 +04:00
src_addr = & si - > myname . sa . s ;
dest_addr = & si - > peername . sa . s ;
2006-10-05 10:27:41 +04:00
2008-10-07 21:56:30 +04:00
tcp_seqno = si - > io . pck_snd ;
2006-10-05 10:27:41 +04:00
tcp_ack = si - > io . pck_rcv ;
tcp_ctl = 0x10 ; /* ACK */
break ;
2006-10-06 19:16:18 +04:00
default :
2008-02-20 01:53:04 +03:00
return NULL ;
2006-10-05 10:27:41 +04:00
}
2006-10-05 15:39:59 +04:00
swrapGetTimeOfDay ( & tv ) ;
2014-10-02 09:13:10 +04:00
return swrap_pcap_packet_init ( & tv ,
src_addr ,
dest_addr ,
si - > type ,
( const uint8_t * ) buf ,
len ,
tcp_seqno ,
tcp_ack ,
tcp_ctl ,
unreachable ,
packet_len ) ;
2008-02-20 01:53:04 +03:00
}
2014-10-02 09:15:38 +04:00
static void swrap_pcap_dump_packet ( struct socket_info * si ,
const struct sockaddr * addr ,
enum swrap_packet_type type ,
const void * buf , size_t len )
2008-02-20 01:53:04 +03:00
{
const char * file_name ;
2009-03-03 16:58:53 +03:00
uint8_t * packet ;
2008-02-20 01:53:04 +03:00
size_t packet_len = 0 ;
int fd ;
2018-05-02 16:57:38 +03:00
swrap_mutex_lock ( & pcap_dump_mutex ) ;
2014-10-02 09:11:49 +04:00
file_name = swrap_pcap_init_file ( ) ;
2008-02-20 01:53:04 +03:00
if ( ! file_name ) {
2018-05-02 16:57:38 +03:00
goto done ;
2008-02-20 01:53:04 +03:00
}
2014-10-02 09:14:04 +04:00
packet = swrap_pcap_marshall_packet ( si ,
addr ,
type ,
buf ,
len ,
& packet_len ) ;
if ( packet = = NULL ) {
2018-05-02 16:57:38 +03:00
goto done ;
2006-10-05 15:39:59 +04:00
}
2014-10-02 09:14:44 +04:00
fd = swrap_pcap_get_fd ( file_name ) ;
2006-10-05 15:39:59 +04:00
if ( fd ! = - 1 ) {
2021-02-17 14:57:01 +03:00
if ( libc_write ( fd , packet , packet_len ) ! = ( ssize_t ) packet_len ) {
2008-12-23 07:08:14 +03:00
free ( packet ) ;
2018-05-02 16:57:38 +03:00
goto done ;
2008-12-23 07:08:14 +03:00
}
2006-10-05 15:39:59 +04:00
}
2014-04-07 18:12:21 +04:00
free ( packet ) ;
2018-05-02 16:57:38 +03:00
done :
swrap_mutex_unlock ( & pcap_dump_mutex ) ;
2014-04-07 18:12:21 +04:00
}
/****************************************************************************
* SIGNALFD
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
# ifdef HAVE_SIGNALFD
static int swrap_signalfd ( int fd , const sigset_t * mask , int flags )
{
int rc ;
rc = libc_signalfd ( fd , mask , flags ) ;
if ( rc ! = - 1 ) {
swrap_remove_stale ( fd ) ;
}
return rc ;
}
int signalfd ( int fd , const sigset_t * mask , int flags )
{
return swrap_signalfd ( fd , mask , flags ) ;
2006-09-12 10:19:11 +04:00
}
2014-04-07 18:12:21 +04:00
# endif
/****************************************************************************
* SOCKET
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2006-09-12 10:19:11 +04:00
2014-04-07 18:12:21 +04:00
static int swrap_socket ( int family , int type , int protocol )
2005-03-28 05:00:39 +04:00
{
2018-05-02 16:57:38 +03:00
struct socket_info * si = NULL ;
struct socket_info _si = { 0 } ;
2005-03-28 05:00:39 +04:00
int fd ;
2018-05-02 16:57:38 +03:00
int ret ;
2009-06-04 08:14:14 +04:00
int real_type = type ;
2014-04-07 18:12:21 +04:00
/*
* Remove possible addition flags passed to socket ( ) so
* do not fail checking the type .
* See https : //lwn.net/Articles/281965/
*/
2009-06-04 08:14:14 +04:00
# ifdef SOCK_CLOEXEC
real_type & = ~ SOCK_CLOEXEC ;
# endif
# ifdef SOCK_NONBLOCK
real_type & = ~ SOCK_NONBLOCK ;
# endif
2005-03-28 05:00:39 +04:00
2014-04-07 18:12:21 +04:00
if ( ! socket_wrapper_enabled ( ) ) {
return libc_socket ( family , type , protocol ) ;
2005-03-28 05:00:39 +04:00
}
2006-09-12 18:44:44 +04:00
2006-09-12 18:59:08 +04:00
switch ( family ) {
2006-09-12 18:44:44 +04:00
case AF_INET :
2007-04-16 08:59:47 +04:00
# ifdef HAVE_IPV6
case AF_INET6 :
# endif
2006-09-12 18:44:44 +04:00
break ;
2016-03-15 17:47:08 +03:00
# ifdef AF_NETLINK
case AF_NETLINK :
# endif /* AF_NETLINK */
2016-05-20 11:20:28 +03:00
# ifdef AF_PACKET
case AF_PACKET :
# endif /* AF_PACKET */
2006-09-12 18:44:44 +04:00
case AF_UNIX :
2020-03-10 15:27:27 +03:00
fd = libc_socket ( family , type , protocol ) ;
if ( fd ! = - 1 ) {
/* Check if we have a stale fd and remove it */
swrap_remove_stale ( fd ) ;
SWRAP_LOG ( SWRAP_LOG_TRACE ,
" Unix socket fd=%d " ,
fd ) ;
}
return fd ;
2006-09-12 18:44:44 +04:00
default :
errno = EAFNOSUPPORT ;
return - 1 ;
}
2006-09-26 17:15:31 +04:00
2009-06-04 08:14:14 +04:00
switch ( real_type ) {
2006-09-26 17:15:31 +04:00
case SOCK_STREAM :
break ;
case SOCK_DGRAM :
break ;
default :
errno = EPROTONOSUPPORT ;
return - 1 ;
}
switch ( protocol ) {
case 0 :
break ;
2007-04-16 08:59:47 +04:00
case 6 :
2009-06-04 08:14:14 +04:00
if ( real_type = = SOCK_STREAM ) {
2007-04-16 08:59:47 +04:00
break ;
}
2017-11-07 14:29:51 +03:00
FALL_THROUGH ;
2007-04-16 08:59:47 +04:00
case 17 :
2009-06-04 08:14:14 +04:00
if ( real_type = = SOCK_DGRAM ) {
2007-04-16 08:59:47 +04:00
break ;
}
2017-11-07 14:29:51 +03:00
FALL_THROUGH ;
2006-09-26 17:15:31 +04:00
default :
errno = EPROTONOSUPPORT ;
return - 1 ;
}
2014-04-07 18:12:21 +04:00
/*
* We must call libc_socket with type , from the caller , not the version
* we removed SOCK_CLOEXEC and SOCK_NONBLOCK from
*/
fd = libc_socket ( AF_UNIX , type , 0 ) ;
if ( fd = = - 1 ) {
return - 1 ;
}
2005-03-28 05:00:39 +04:00
2014-04-07 18:12:21 +04:00
/* Check if we have a stale fd and remove it */
2017-11-07 14:29:51 +03:00
swrap_remove_stale ( fd ) ;
2005-03-28 05:00:39 +04:00
2018-05-02 16:57:38 +03:00
si = & _si ;
2006-09-12 18:59:08 +04:00
si - > family = family ;
2009-06-04 08:14:14 +04:00
/* however, the rest of the socket_wrapper code expects just
* the type , not the flags */
si - > type = real_type ;
2005-03-28 05:00:39 +04:00
si - > protocol = protocol ;
2014-06-03 17:08:07 +04:00
/*
* Setup myname so getsockname ( ) can succeed to find out the socket
* type .
*/
switch ( si - > family ) {
case AF_INET : {
struct sockaddr_in sin = {
. sin_family = AF_INET ,
} ;
2014-10-02 09:17:10 +04:00
si - > myname . sa_socklen = sizeof ( struct sockaddr_in ) ;
memcpy ( & si - > myname . sa . in , & sin , si - > myname . sa_socklen ) ;
2014-06-03 17:08:07 +04:00
break ;
}
2018-05-02 16:57:38 +03:00
# ifdef HAVE_IPV6
2014-06-03 17:08:07 +04:00
case AF_INET6 : {
struct sockaddr_in6 sin6 = {
. sin6_family = AF_INET6 ,
} ;
2014-10-02 09:17:10 +04:00
si - > myname . sa_socklen = sizeof ( struct sockaddr_in6 ) ;
memcpy ( & si - > myname . sa . in6 , & sin6 , si - > myname . sa_socklen ) ;
2014-06-03 17:08:07 +04:00
break ;
}
2018-05-02 16:57:38 +03:00
# endif
2014-06-03 17:08:07 +04:00
default :
errno = EINVAL ;
return - 1 ;
}
2018-05-02 16:57:38 +03:00
ret = swrap_create_socket ( si , fd ) ;
if ( ret = = - 1 ) {
2021-02-09 10:56:42 +03:00
int saved_errno = errno ;
libc_close ( fd ) ;
errno = saved_errno ;
2011-09-29 01:09:49 +04:00
return - 1 ;
}
2014-10-02 09:24:55 +04:00
SWRAP_LOG ( SWRAP_LOG_TRACE ,
2018-05-02 16:57:38 +03:00
" Created %s socket for protocol %s, fd=%d " ,
family = = AF_INET ? " IPv4 " : " IPv6 " ,
real_type = = SOCK_DGRAM ? " UDP " : " TCP " ,
fd ) ;
2014-10-02 09:24:55 +04:00
2011-09-29 01:09:49 +04:00
return fd ;
2005-03-28 05:00:39 +04:00
}
2014-04-07 18:12:21 +04:00
int socket ( int family , int type , int protocol )
{
return swrap_socket ( family , type , protocol ) ;
}
/****************************************************************************
* SOCKETPAIR
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
static int swrap_socketpair ( int family , int type , int protocol , int sv [ 2 ] )
{
int rc ;
rc = libc_socketpair ( family , type , protocol , sv ) ;
if ( rc ! = - 1 ) {
swrap_remove_stale ( sv [ 0 ] ) ;
swrap_remove_stale ( sv [ 1 ] ) ;
}
return rc ;
}
int socketpair ( int family , int type , int protocol , int sv [ 2 ] )
{
return swrap_socketpair ( family , type , protocol , sv ) ;
}
/****************************************************************************
* SOCKETPAIR
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
# ifdef HAVE_TIMERFD_CREATE
static int swrap_timerfd_create ( int clockid , int flags )
{
int fd ;
fd = libc_timerfd_create ( clockid , flags ) ;
if ( fd ! = - 1 ) {
swrap_remove_stale ( fd ) ;
}
return fd ;
}
int timerfd_create ( int clockid , int flags )
{
return swrap_timerfd_create ( clockid , flags ) ;
}
# endif
/****************************************************************************
* PIPE
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
static int swrap_pipe ( int pipefd [ 2 ] )
{
int rc ;
rc = libc_pipe ( pipefd ) ;
if ( rc ! = - 1 ) {
swrap_remove_stale ( pipefd [ 0 ] ) ;
swrap_remove_stale ( pipefd [ 1 ] ) ;
}
return rc ;
}
int pipe ( int pipefd [ 2 ] )
{
return swrap_pipe ( pipefd ) ;
}
/****************************************************************************
* ACCEPT
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2016-05-20 11:20:28 +03:00
static int swrap_accept ( int s ,
struct sockaddr * addr ,
socklen_t * addrlen ,
int flags )
2005-03-28 05:00:39 +04:00
{
struct socket_info * parent_si , * child_si ;
2018-05-02 16:57:38 +03:00
struct socket_info new_si = { 0 } ;
2005-03-28 05:00:39 +04:00
int fd ;
2017-11-07 14:29:51 +03:00
int idx ;
2014-10-02 09:09:33 +04:00
struct swrap_address un_addr = {
. sa_socklen = sizeof ( struct sockaddr_un ) ,
} ;
struct swrap_address un_my_addr = {
. sa_socklen = sizeof ( struct sockaddr_un ) ,
} ;
2014-10-02 09:18:14 +04:00
struct swrap_address in_addr = {
. sa_socklen = sizeof ( struct sockaddr_storage ) ,
} ;
struct swrap_address in_my_addr = {
. sa_socklen = sizeof ( struct sockaddr_storage ) ,
} ;
2005-03-28 05:00:39 +04:00
int ret ;
parent_si = find_socket_info ( s ) ;
if ( ! parent_si ) {
2016-05-20 11:20:28 +03:00
# ifdef HAVE_ACCEPT4
return libc_accept4 ( s , addr , addrlen , flags ) ;
# else
2017-11-07 14:29:51 +03:00
UNUSED ( flags ) ;
2014-04-07 18:12:21 +04:00
return libc_accept ( s , addr , addrlen ) ;
2016-05-20 11:20:28 +03:00
# endif
2005-03-28 05:00:39 +04:00
}
2018-05-02 16:57:38 +03:00
/*
* prevent parent_si from being altered / closed
* while we read it
*/
SWRAP_LOCK_SI ( parent_si ) ;
2014-10-02 09:20:53 +04:00
/*
2007-04-16 08:59:47 +04:00
* assume out sockaddr have the same size as the in parent
* socket family
*/
2014-10-02 09:18:14 +04:00
in_addr . sa_socklen = socket_length ( parent_si - > family ) ;
if ( in_addr . sa_socklen < = 0 ) {
2018-05-02 16:57:38 +03:00
SWRAP_UNLOCK_SI ( parent_si ) ;
2007-04-16 08:59:47 +04:00
errno = EINVAL ;
return - 1 ;
}
2018-05-02 16:57:38 +03:00
SWRAP_UNLOCK_SI ( parent_si ) ;
2016-05-20 11:20:28 +03:00
# ifdef HAVE_ACCEPT4
ret = libc_accept4 ( s , & un_addr . sa . s , & un_addr . sa_socklen , flags ) ;
# else
2017-11-07 14:29:51 +03:00
UNUSED ( flags ) ;
2014-10-02 09:09:33 +04:00
ret = libc_accept ( s , & un_addr . sa . s , & un_addr . sa_socklen ) ;
2016-05-20 11:20:28 +03:00
# endif
2007-04-16 08:59:47 +04:00
if ( ret = = - 1 ) {
2021-02-09 10:56:42 +03:00
int saved_errno = errno ;
if ( saved_errno = = ENOTSOCK ) {
2014-04-07 18:12:21 +04:00
/* Remove stale fds */
swrap_remove_stale ( s ) ;
}
2021-02-09 10:56:42 +03:00
errno = saved_errno ;
2007-04-16 08:59:47 +04:00
return ret ;
}
2005-03-28 05:00:39 +04:00
fd = ret ;
2020-03-10 15:27:27 +03:00
/* Check if we have a stale fd and remove it */
swrap_remove_stale ( fd ) ;
2021-02-09 10:56:42 +03:00
if ( un_addr . sa . un . sun_path [ 0 ] = = ' \0 ' ) {
/*
* FreeBSD seems to have a problem where
* accept4 ( ) on the unix socket doesn ' t
* ECONNABORTED for already disconnected connections .
*
* Let ' s try libc_getpeername ( ) to get the peer address
* as a fallback , but it ' ll likely return ENOTCONN ,
* which we have to map to ECONNABORTED .
*/
un_addr . sa_socklen = sizeof ( struct sockaddr_un ) ,
ret = libc_getpeername ( fd , & un_addr . sa . s , & un_addr . sa_socklen ) ;
if ( ret = = - 1 ) {
int saved_errno = errno ;
libc_close ( fd ) ;
if ( saved_errno = = ENOTCONN ) {
/*
* If the connection is already disconnected
* we should return ECONNABORTED .
*/
saved_errno = ECONNABORTED ;
}
errno = saved_errno ;
return ret ;
}
}
ret = libc_getsockname ( fd ,
& un_my_addr . sa . s ,
& un_my_addr . sa_socklen ) ;
if ( ret = = - 1 ) {
int saved_errno = errno ;
libc_close ( fd ) ;
if ( saved_errno = = ENOTCONN ) {
/*
* If the connection is already disconnected
* we should return ECONNABORTED .
*/
saved_errno = ECONNABORTED ;
}
errno = saved_errno ;
return ret ;
}
2018-05-02 16:57:38 +03:00
SWRAP_LOCK_SI ( parent_si ) ;
2014-10-02 09:09:33 +04:00
ret = sockaddr_convert_from_un ( parent_si ,
& un_addr . sa . un ,
un_addr . sa_socklen ,
parent_si - > family ,
2014-10-02 09:18:14 +04:00
& in_addr . sa . s ,
& in_addr . sa_socklen ) ;
2006-09-16 21:57:50 +04:00
if ( ret = = - 1 ) {
2021-02-09 10:56:42 +03:00
int saved_errno = errno ;
2018-05-02 16:57:38 +03:00
SWRAP_UNLOCK_SI ( parent_si ) ;
2021-02-09 10:56:42 +03:00
libc_close ( fd ) ;
errno = saved_errno ;
2006-09-16 21:57:50 +04:00
return ret ;
}
2005-03-28 05:00:39 +04:00
2018-05-02 16:57:38 +03:00
child_si = & new_si ;
2011-09-29 01:09:49 +04:00
2006-09-12 18:59:08 +04:00
child_si - > family = parent_si - > family ;
2005-12-05 18:26:49 +03:00
child_si - > type = parent_si - > type ;
child_si - > protocol = parent_si - > protocol ;
2005-06-19 16:34:59 +04:00
child_si - > bound = 1 ;
2006-09-29 13:31:20 +04:00
child_si - > is_server = 1 ;
2009-03-08 19:19:50 +03:00
child_si - > connected = 1 ;
2005-03-28 05:00:39 +04:00
2018-05-02 16:57:38 +03:00
SWRAP_UNLOCK_SI ( parent_si ) ;
2014-10-02 09:18:14 +04:00
child_si - > peername = ( struct swrap_address ) {
. sa_socklen = in_addr . sa_socklen ,
} ;
memcpy ( & child_si - > peername . sa . ss , & in_addr . sa . ss , in_addr . sa_socklen ) ;
2007-04-16 08:59:47 +04:00
if ( addr ! = NULL & & addrlen ! = NULL ) {
2014-10-02 09:18:14 +04:00
size_t copy_len = MIN ( * addrlen , in_addr . sa_socklen ) ;
2011-03-09 13:46:34 +03:00
if ( copy_len > 0 ) {
2014-10-02 09:18:14 +04:00
memcpy ( addr , & in_addr . sa . ss , copy_len ) ;
2011-03-09 13:46:34 +03:00
}
2014-10-02 09:18:14 +04:00
* addrlen = in_addr . sa_socklen ;
2007-04-16 08:59:47 +04:00
}
2014-10-02 09:09:33 +04:00
ret = sockaddr_convert_from_un ( child_si ,
& un_my_addr . sa . un ,
un_my_addr . sa_socklen ,
child_si - > family ,
2014-10-02 09:18:14 +04:00
& in_my_addr . sa . s ,
& in_my_addr . sa_socklen ) ;
2006-09-16 21:57:50 +04:00
if ( ret = = - 1 ) {
2021-02-09 10:56:42 +03:00
int saved_errno = errno ;
libc_close ( fd ) ;
errno = saved_errno ;
2006-09-16 21:57:50 +04:00
return ret ;
}
2005-12-05 18:26:49 +03:00
2014-04-07 18:12:21 +04:00
SWRAP_LOG ( SWRAP_LOG_TRACE ,
" accept() path=%s, fd=%d " ,
2014-10-02 09:09:33 +04:00
un_my_addr . sa . un . sun_path , s ) ;
2014-04-07 18:12:21 +04:00
2014-10-02 09:18:14 +04:00
child_si - > myname = ( struct swrap_address ) {
. sa_socklen = in_my_addr . sa_socklen ,
} ;
memcpy ( & child_si - > myname . sa . ss , & in_my_addr . sa . ss , in_my_addr . sa_socklen ) ;
2005-06-10 16:21:46 +04:00
2018-05-02 16:57:38 +03:00
idx = swrap_create_socket ( & new_si , fd ) ;
if ( idx = = - 1 ) {
2021-02-09 10:56:42 +03:00
int saved_errno = errno ;
libc_close ( fd ) ;
errno = saved_errno ;
2018-05-02 16:57:38 +03:00
return - 1 ;
}
2005-06-10 16:21:46 +04:00
2014-04-07 18:12:21 +04:00
if ( addr ! = NULL ) {
2018-05-02 16:57:38 +03:00
struct socket_info * si = swrap_get_socket_info ( idx ) ;
SWRAP_LOCK_SI ( si ) ;
swrap_pcap_dump_packet ( si , addr , SWRAP_ACCEPT_SEND , NULL , 0 ) ;
swrap_pcap_dump_packet ( si , addr , SWRAP_ACCEPT_RECV , NULL , 0 ) ;
swrap_pcap_dump_packet ( si , addr , SWRAP_ACCEPT_ACK , NULL , 0 ) ;
SWRAP_UNLOCK_SI ( si ) ;
2014-04-07 18:12:21 +04:00
}
2006-09-12 13:08:55 +04:00
2005-03-28 05:00:39 +04:00
return fd ;
}
2016-05-20 11:20:28 +03:00
# ifdef HAVE_ACCEPT4
int accept4 ( int s , struct sockaddr * addr , socklen_t * addrlen , int flags )
{
return swrap_accept ( s , addr , ( socklen_t * ) addrlen , flags ) ;
}
# endif
2014-04-07 18:12:21 +04:00
# ifdef HAVE_ACCEPT_PSOCKLEN_T
int accept ( int s , struct sockaddr * addr , Psocklen_t addrlen )
# else
int accept ( int s , struct sockaddr * addr , socklen_t * addrlen )
# endif
{
2016-05-20 11:20:28 +03:00
return swrap_accept ( s , addr , ( socklen_t * ) addrlen , 0 ) ;
2014-04-07 18:12:21 +04:00
}
2006-09-26 17:15:31 +04:00
static int autobind_start_init ;
static int autobind_start ;
2005-06-10 16:21:46 +04:00
/* using sendto() or connect() on an unbound socket would give the
recipient no way to reply , as unlike UDP and TCP , a unix domain
2014-05-08 17:30:09 +04:00
socket can ' t auto - assign ephemeral port numbers , so we need to
2009-03-08 19:20:18 +03:00
assign it here .
Note : this might change the family from ipv6 to ipv4
*/
2011-09-29 01:04:51 +04:00
static int swrap_auto_bind ( int fd , struct socket_info * si , int family )
2005-06-10 16:21:46 +04:00
{
2014-10-02 09:09:33 +04:00
struct swrap_address un_addr = {
. sa_socklen = sizeof ( struct sockaddr_un ) ,
} ;
2005-06-10 16:21:46 +04:00
int i ;
2005-11-07 18:36:51 +03:00
char type ;
int ret ;
2006-09-12 20:25:50 +04:00
int port ;
2005-11-07 18:36:51 +03:00
struct stat st ;
2019-03-21 12:02:54 +03:00
char * swrap_dir = NULL ;
2006-09-26 17:15:31 +04:00
2018-05-02 16:57:38 +03:00
swrap_mutex_lock ( & autobind_start_mutex ) ;
2006-09-26 17:15:31 +04:00
if ( autobind_start_init ! = 1 ) {
autobind_start_init = 1 ;
autobind_start = getpid ( ) ;
autobind_start % = 50000 ;
autobind_start + = 10000 ;
}
2014-10-02 09:09:33 +04:00
un_addr . sa . un . sun_family = AF_UNIX ;
2005-11-07 18:36:51 +03:00
2009-03-08 19:20:18 +03:00
switch ( family ) {
2007-04-16 08:59:47 +04:00
case AF_INET : {
struct sockaddr_in in ;
switch ( si - > type ) {
case SOCK_STREAM :
type = SOCKET_TYPE_CHAR_TCP ;
break ;
case SOCK_DGRAM :
2014-10-02 09:20:53 +04:00
type = SOCKET_TYPE_CHAR_UDP ;
2007-04-16 08:59:47 +04:00
break ;
default :
2017-11-07 14:29:51 +03:00
errno = ESOCKTNOSUPPORT ;
ret = - 1 ;
goto done ;
2007-04-16 08:59:47 +04:00
}
memset ( & in , 0 , sizeof ( in ) ) ;
in . sin_family = AF_INET ;
2020-03-10 15:27:27 +03:00
in . sin_addr . s_addr = htonl ( swrap_ipv4_iface (
socket_wrapper_default_iface ( ) ) ) ;
2007-04-16 08:59:47 +04:00
2014-10-02 09:17:10 +04:00
si - > myname = ( struct swrap_address ) {
. sa_socklen = sizeof ( in ) ,
} ;
memcpy ( & si - > myname . sa . in , & in , si - > myname . sa_socklen ) ;
2005-11-07 18:36:51 +03:00
break ;
2007-04-16 08:59:47 +04:00
}
# ifdef HAVE_IPV6
case AF_INET6 : {
struct sockaddr_in6 in6 ;
2009-03-08 19:20:18 +03:00
if ( si - > family ! = family ) {
errno = ENETUNREACH ;
2017-11-07 14:29:51 +03:00
ret = - 1 ;
goto done ;
2009-03-08 19:20:18 +03:00
}
2007-04-16 08:59:47 +04:00
switch ( si - > type ) {
case SOCK_STREAM :
type = SOCKET_TYPE_CHAR_TCP_V6 ;
break ;
case SOCK_DGRAM :
2014-10-02 09:20:53 +04:00
type = SOCKET_TYPE_CHAR_UDP_V6 ;
2007-04-16 08:59:47 +04:00
break ;
default :
2009-03-03 18:45:41 +03:00
errno = ESOCKTNOSUPPORT ;
2017-11-07 14:29:51 +03:00
ret = - 1 ;
goto done ;
2007-04-16 08:59:47 +04:00
}
memset ( & in6 , 0 , sizeof ( in6 ) ) ;
in6 . sin6_family = AF_INET6 ;
2009-03-09 11:24:45 +03:00
in6 . sin6_addr = * swrap_ipv6 ( ) ;
2009-03-03 18:45:41 +03:00
in6 . sin6_addr . s6_addr [ 15 ] = socket_wrapper_default_iface ( ) ;
2014-10-02 09:17:10 +04:00
si - > myname = ( struct swrap_address ) {
. sa_socklen = sizeof ( in6 ) ,
} ;
memcpy ( & si - > myname . sa . in6 , & in6 , si - > myname . sa_socklen ) ;
2005-11-07 18:36:51 +03:00
break ;
2007-04-16 08:59:47 +04:00
}
# endif
2005-11-07 18:36:51 +03:00
default :
errno = ESOCKTNOSUPPORT ;
2017-11-07 14:29:51 +03:00
ret = - 1 ;
goto done ;
2005-11-07 18:36:51 +03:00
}
2006-09-26 17:15:31 +04:00
if ( autobind_start > 60000 ) {
autobind_start = 10000 ;
}
2019-03-21 12:02:54 +03:00
swrap_dir = socket_wrapper_dir ( ) ;
if ( swrap_dir = = NULL ) {
errno = EINVAL ;
ret = - 1 ;
goto done ;
}
2014-04-07 18:12:21 +04:00
for ( i = 0 ; i < SOCKET_MAX_SOCKETS ; i + + ) {
2006-09-26 17:15:31 +04:00
port = autobind_start + i ;
2020-06-08 15:18:00 +03:00
swrap_un_path ( & un_addr . sa . un ,
swrap_dir ,
type ,
socket_wrapper_default_iface ( ) ,
port ) ;
2014-10-02 09:09:33 +04:00
if ( stat ( un_addr . sa . un . sun_path , & st ) = = 0 ) continue ;
2011-02-12 14:18:16 +03:00
2014-10-02 09:09:33 +04:00
ret = libc_bind ( fd , & un_addr . sa . s , un_addr . sa_socklen ) ;
2017-11-07 14:29:51 +03:00
if ( ret = = - 1 ) {
goto done ;
}
2005-11-07 18:36:51 +03:00
2014-10-02 09:16:25 +04:00
si - > un_addr = un_addr . sa . un ;
2005-11-07 18:36:51 +03:00
si - > bound = 1 ;
2006-09-26 17:15:31 +04:00
autobind_start = port + 1 ;
2005-11-07 18:36:51 +03:00
break ;
2005-06-10 16:21:46 +04:00
}
2014-04-07 18:12:21 +04:00
if ( i = = SOCKET_MAX_SOCKETS ) {
SWRAP_LOG ( SWRAP_LOG_ERROR , " Too many open unix sockets (%u) for "
" interface " SOCKET_FORMAT ,
SOCKET_MAX_SOCKETS ,
type ,
socket_wrapper_default_iface ( ) ,
0 ) ;
2005-11-07 18:36:51 +03:00
errno = ENFILE ;
2017-11-07 14:29:51 +03:00
ret = - 1 ;
goto done ;
2005-06-10 16:21:46 +04:00
}
2006-09-26 17:15:31 +04:00
2009-03-08 19:20:18 +03:00
si - > family = family ;
2014-10-02 09:17:10 +04:00
set_port ( si - > family , port , & si - > myname ) ;
2007-04-16 08:59:47 +04:00
2017-11-07 14:29:51 +03:00
ret = 0 ;
done :
2019-03-21 12:02:54 +03:00
SAFE_FREE ( swrap_dir ) ;
2018-05-02 16:57:38 +03:00
swrap_mutex_unlock ( & autobind_start_mutex ) ;
2017-11-07 14:29:51 +03:00
return ret ;
2005-06-10 16:21:46 +04:00
}
2014-04-07 18:12:21 +04:00
/****************************************************************************
* CONNECT
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2005-06-10 16:21:46 +04:00
2014-04-07 18:12:21 +04:00
static int swrap_connect ( int s , const struct sockaddr * serv_addr ,
socklen_t addrlen )
2005-03-28 05:00:39 +04:00
{
int ret ;
2014-10-02 09:09:33 +04:00
struct swrap_address un_addr = {
. sa_socklen = sizeof ( struct sockaddr_un ) ,
} ;
2005-03-28 05:00:39 +04:00
struct socket_info * si = find_socket_info ( s ) ;
2010-10-30 18:07:31 +04:00
int bcast = 0 ;
2005-03-28 05:00:39 +04:00
if ( ! si ) {
2014-04-07 18:12:21 +04:00
return libc_connect ( s , serv_addr , addrlen ) ;
2005-03-28 05:00:39 +04:00
}
2018-05-02 16:57:38 +03:00
SWRAP_LOCK_SI ( si ) ;
2006-09-12 18:44:44 +04:00
if ( si - > bound = = 0 ) {
2011-09-29 01:04:51 +04:00
ret = swrap_auto_bind ( s , si , serv_addr - > sa_family ) ;
2017-11-07 14:29:51 +03:00
if ( ret = = - 1 ) {
goto done ;
}
2005-06-10 16:21:46 +04:00
}
2007-04-16 08:59:47 +04:00
if ( si - > family ! = serv_addr - > sa_family ) {
2020-03-10 15:27:27 +03:00
SWRAP_LOG ( SWRAP_LOG_ERROR ,
2020-06-08 15:18:00 +03:00
" called for fd=%d (family=%d) called with invalid family=%d " ,
2020-03-10 15:27:27 +03:00
s , si - > family , serv_addr - > sa_family ) ;
2007-04-16 08:59:47 +04:00
errno = EINVAL ;
2017-11-07 14:29:51 +03:00
ret = - 1 ;
goto done ;
2007-04-16 08:59:47 +04:00
}
2011-03-02 22:46:45 +03:00
ret = sockaddr_convert_to_un ( si , serv_addr ,
2014-10-02 09:09:33 +04:00
addrlen , & un_addr . sa . un , 0 , & bcast ) ;
2017-11-07 14:29:51 +03:00
if ( ret = = - 1 ) {
goto done ;
}
2005-03-28 05:00:39 +04:00
2010-10-30 18:07:31 +04:00
if ( bcast ) {
errno = ENETUNREACH ;
2017-11-07 14:29:51 +03:00
ret = - 1 ;
goto done ;
2010-10-30 18:07:31 +04:00
}
2009-03-23 11:16:18 +03:00
if ( si - > type = = SOCK_DGRAM ) {
si - > defer_connect = 1 ;
ret = 0 ;
} else {
2014-10-02 09:15:38 +04:00
swrap_pcap_dump_packet ( si , serv_addr , SWRAP_CONNECT_SEND , NULL , 0 ) ;
2006-09-29 13:31:20 +04:00
2014-04-07 18:12:21 +04:00
ret = libc_connect ( s ,
2014-10-02 09:09:33 +04:00
& un_addr . sa . s ,
un_addr . sa_socklen ) ;
2009-03-23 11:16:18 +03:00
}
2005-03-28 05:00:39 +04:00
2014-04-07 18:12:21 +04:00
SWRAP_LOG ( SWRAP_LOG_TRACE ,
" connect() path=%s, fd=%d " ,
2014-10-02 09:22:13 +04:00
un_addr . sa . un . sun_path , s ) ;
2014-04-07 18:12:21 +04:00
2005-11-07 18:36:51 +03:00
/* to give better errors */
2006-09-12 18:44:44 +04:00
if ( ret = = - 1 & & errno = = ENOENT ) {
errno = EHOSTUNREACH ;
2005-11-07 18:36:51 +03:00
}
2005-03-31 16:40:12 +04:00
if ( ret = = 0 ) {
2014-10-02 09:17:10 +04:00
si - > peername = ( struct swrap_address ) {
. sa_socklen = addrlen ,
} ;
memcpy ( & si - > peername . sa . ss , serv_addr , addrlen ) ;
2009-03-08 19:19:50 +03:00
si - > connected = 1 ;
2005-03-28 05:00:39 +04:00
2014-06-03 16:50:53 +04:00
/*
* When we connect ( ) on a socket than we have to bind the
* outgoing connection on the interface we use for the
* transport . We already bound it on the right interface
* but here we have to update the name so getsockname ( )
* returns correct information .
*/
2014-10-02 09:17:10 +04:00
if ( si - > bindname . sa_socklen > 0 ) {
si - > myname = ( struct swrap_address ) {
. sa_socklen = si - > bindname . sa_socklen ,
} ;
memcpy ( & si - > myname . sa . ss ,
& si - > bindname . sa . ss ,
si - > bindname . sa_socklen ) ;
/* Cleanup bindname */
si - > bindname = ( struct swrap_address ) {
. sa_socklen = 0 ,
} ;
2014-06-03 16:50:53 +04:00
}
2014-10-02 09:15:38 +04:00
swrap_pcap_dump_packet ( si , serv_addr , SWRAP_CONNECT_RECV , NULL , 0 ) ;
swrap_pcap_dump_packet ( si , serv_addr , SWRAP_CONNECT_ACK , NULL , 0 ) ;
2006-09-29 13:31:20 +04:00
} else {
2014-10-02 09:15:38 +04:00
swrap_pcap_dump_packet ( si , serv_addr , SWRAP_CONNECT_UNREACH , NULL , 0 ) ;
2006-09-29 13:31:20 +04:00
}
2006-09-12 13:08:55 +04:00
2017-11-07 14:29:51 +03:00
done :
2018-05-02 16:57:38 +03:00
SWRAP_UNLOCK_SI ( si ) ;
2005-03-28 05:00:39 +04:00
return ret ;
}
2014-04-07 18:12:21 +04:00
int connect ( int s , const struct sockaddr * serv_addr , socklen_t addrlen )
{
return swrap_connect ( s , serv_addr , addrlen ) ;
}
/****************************************************************************
* BIND
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
static int swrap_bind ( int s , const struct sockaddr * myaddr , socklen_t addrlen )
2005-03-28 05:00:39 +04:00
{
int ret ;
2014-10-02 09:09:33 +04:00
struct swrap_address un_addr = {
. sa_socklen = sizeof ( struct sockaddr_un ) ,
} ;
2005-03-28 05:00:39 +04:00
struct socket_info * si = find_socket_info ( s ) ;
2014-06-03 17:12:34 +04:00
int bind_error = 0 ;
2014-06-06 01:38:59 +04:00
#if 0 /* FIXME */
2014-06-03 17:14:44 +04:00
bool in_use ;
2014-06-06 01:38:59 +04:00
# endif
2005-03-28 05:00:39 +04:00
if ( ! si ) {
2014-04-07 18:12:21 +04:00
return libc_bind ( s , myaddr , addrlen ) ;
2005-03-28 05:00:39 +04:00
}
2018-05-02 16:57:38 +03:00
SWRAP_LOCK_SI ( si ) ;
2014-06-03 17:12:34 +04:00
switch ( si - > family ) {
case AF_INET : {
const struct sockaddr_in * sin ;
if ( addrlen < sizeof ( struct sockaddr_in ) ) {
bind_error = EINVAL ;
break ;
}
2014-10-02 09:23:25 +04:00
sin = ( const struct sockaddr_in * ) ( const void * ) myaddr ;
2014-06-03 17:12:34 +04:00
if ( sin - > sin_family ! = AF_INET ) {
bind_error = EAFNOSUPPORT ;
}
/* special case for AF_UNSPEC */
if ( sin - > sin_family = = AF_UNSPEC & &
( sin - > sin_addr . s_addr = = htonl ( INADDR_ANY ) ) )
{
bind_error = 0 ;
}
break ;
}
# ifdef HAVE_IPV6
case AF_INET6 : {
const struct sockaddr_in6 * sin6 ;
if ( addrlen < sizeof ( struct sockaddr_in6 ) ) {
bind_error = EINVAL ;
break ;
}
2014-10-02 09:23:25 +04:00
sin6 = ( const struct sockaddr_in6 * ) ( const void * ) myaddr ;
2014-06-03 17:12:34 +04:00
if ( sin6 - > sin6_family ! = AF_INET6 ) {
bind_error = EAFNOSUPPORT ;
}
break ;
}
# endif
default :
bind_error = EINVAL ;
break ;
}
if ( bind_error ! = 0 ) {
errno = bind_error ;
2018-05-02 16:57:38 +03:00
ret = - 1 ;
goto out ;
2014-06-03 17:08:57 +04:00
}
2014-06-06 01:38:59 +04:00
#if 0 /* FIXME */
2014-06-03 17:14:44 +04:00
in_use = check_addr_port_in_use ( myaddr , addrlen ) ;
if ( in_use ) {
errno = EADDRINUSE ;
2018-05-02 16:57:38 +03:00
ret = - 1 ;
goto out ;
2014-06-03 17:14:44 +04:00
}
2014-06-06 01:38:59 +04:00
# endif
2014-06-03 17:14:44 +04:00
2014-10-02 09:17:10 +04:00
si - > myname . sa_socklen = addrlen ;
memcpy ( & si - > myname . sa . ss , myaddr , addrlen ) ;
2005-06-10 16:21:46 +04:00
2014-10-02 09:09:33 +04:00
ret = sockaddr_convert_to_un ( si ,
myaddr ,
addrlen ,
& un_addr . sa . un ,
1 ,
& si - > bcast ) ;
2017-11-07 14:29:51 +03:00
if ( ret = = - 1 ) {
2018-05-02 16:57:38 +03:00
goto out ;
2017-11-07 14:29:51 +03:00
}
2005-03-28 05:00:39 +04:00
2014-10-02 09:09:33 +04:00
unlink ( un_addr . sa . un . sun_path ) ;
2005-03-28 05:00:39 +04:00
2014-10-02 09:09:33 +04:00
ret = libc_bind ( s , & un_addr . sa . s , un_addr . sa_socklen ) ;
2005-03-28 05:00:39 +04:00
2014-04-07 18:12:21 +04:00
SWRAP_LOG ( SWRAP_LOG_TRACE ,
" bind() path=%s, fd=%d " ,
2014-10-02 09:22:13 +04:00
un_addr . sa . un . sun_path , s ) ;
2014-04-07 18:12:21 +04:00
2005-03-31 16:40:12 +04:00
if ( ret = = 0 ) {
si - > bound = 1 ;
2005-03-28 05:00:39 +04:00
}
2018-05-02 16:57:38 +03:00
out :
SWRAP_UNLOCK_SI ( si ) ;
2005-03-28 05:00:39 +04:00
return ret ;
}
2014-04-07 18:12:21 +04:00
int bind ( int s , const struct sockaddr * myaddr , socklen_t addrlen )
{
return swrap_bind ( s , myaddr , addrlen ) ;
}
2014-06-03 17:10:19 +04:00
/****************************************************************************
* BINDRESVPORT
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
# ifdef HAVE_BINDRESVPORT
static int swrap_getsockname ( int s , struct sockaddr * name , socklen_t * addrlen ) ;
static int swrap_bindresvport_sa ( int sd , struct sockaddr * sa )
{
2014-10-02 09:09:33 +04:00
struct swrap_address myaddr = {
. sa_socklen = sizeof ( struct sockaddr_storage ) ,
} ;
2014-06-03 17:10:19 +04:00
socklen_t salen ;
static uint16_t port ;
uint16_t i ;
int rc = - 1 ;
int af ;
# define SWRAP_STARTPORT 600
# define SWRAP_ENDPORT (IPPORT_RESERVED - 1)
# define SWRAP_NPORTS (SWRAP_ENDPORT - SWRAP_STARTPORT + 1)
if ( port = = 0 ) {
port = ( getpid ( ) % SWRAP_NPORTS ) + SWRAP_STARTPORT ;
}
if ( sa = = NULL ) {
2014-10-02 09:09:33 +04:00
salen = myaddr . sa_socklen ;
sa = & myaddr . sa . s ;
2014-06-03 17:10:19 +04:00
2014-10-02 09:09:33 +04:00
rc = swrap_getsockname ( sd , & myaddr . sa . s , & salen ) ;
2014-06-03 17:10:19 +04:00
if ( rc < 0 ) {
return - 1 ;
}
af = sa - > sa_family ;
2014-10-02 09:09:33 +04:00
memset ( & myaddr . sa . ss , 0 , salen ) ;
2014-06-03 17:10:19 +04:00
} else {
af = sa - > sa_family ;
}
for ( i = 0 ; i < SWRAP_NPORTS ; i + + , port + + ) {
switch ( af ) {
case AF_INET : {
2014-10-02 09:09:33 +04:00
struct sockaddr_in * sinp = ( struct sockaddr_in * ) ( void * ) sa ;
2014-06-03 17:10:19 +04:00
salen = sizeof ( struct sockaddr_in ) ;
sinp - > sin_port = htons ( port ) ;
break ;
}
case AF_INET6 : {
2014-10-02 09:23:25 +04:00
struct sockaddr_in6 * sin6p = ( struct sockaddr_in6 * ) ( void * ) sa ;
2014-06-03 17:10:19 +04:00
salen = sizeof ( struct sockaddr_in6 ) ;
sin6p - > sin6_port = htons ( port ) ;
break ;
}
default :
errno = EAFNOSUPPORT ;
return - 1 ;
}
sa - > sa_family = af ;
if ( port > SWRAP_ENDPORT ) {
port = SWRAP_STARTPORT ;
}
rc = swrap_bind ( sd , ( struct sockaddr * ) sa , salen ) ;
if ( rc = = 0 | | errno ! = EADDRINUSE ) {
break ;
}
}
return rc ;
}
int bindresvport ( int sockfd , struct sockaddr_in * sinp )
{
return swrap_bindresvport_sa ( sockfd , ( struct sockaddr * ) sinp ) ;
}
# endif
2014-04-07 18:12:21 +04:00
/****************************************************************************
* LISTEN
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
static int swrap_listen ( int s , int backlog )
2006-09-27 14:13:45 +04:00
{
int ret ;
struct socket_info * si = find_socket_info ( s ) ;
if ( ! si ) {
2014-04-07 18:12:21 +04:00
return libc_listen ( s , backlog ) ;
2006-09-27 14:13:45 +04:00
}
2018-05-02 16:57:38 +03:00
SWRAP_LOCK_SI ( si ) ;
2016-03-15 17:47:08 +03:00
if ( si - > bound = = 0 ) {
ret = swrap_auto_bind ( s , si , si - > family ) ;
if ( ret = = - 1 ) {
errno = EADDRINUSE ;
2018-05-02 16:57:38 +03:00
goto out ;
2016-03-15 17:47:08 +03:00
}
}
2014-04-07 18:12:21 +04:00
ret = libc_listen ( s , backlog ) ;
2020-06-08 15:18:00 +03:00
if ( ret = = 0 ) {
si - > listening = 1 ;
}
2014-04-07 18:12:21 +04:00
2018-05-02 16:57:38 +03:00
out :
SWRAP_UNLOCK_SI ( si ) ;
2014-04-07 18:12:21 +04:00
return ret ;
}
int listen ( int s , int backlog )
{
return swrap_listen ( s , backlog ) ;
}
2014-10-02 09:18:48 +04:00
/****************************************************************************
* FOPEN
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
static FILE * swrap_fopen ( const char * name , const char * mode )
{
FILE * fp ;
fp = libc_fopen ( name , mode ) ;
if ( fp ! = NULL ) {
int fd = fileno ( fp ) ;
swrap_remove_stale ( fd ) ;
}
return fp ;
}
FILE * fopen ( const char * name , const char * mode )
{
return swrap_fopen ( name , mode ) ;
}
2017-11-07 14:29:51 +03:00
/****************************************************************************
* FOPEN64
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
# ifdef HAVE_FOPEN64
static FILE * swrap_fopen64 ( const char * name , const char * mode )
{
FILE * fp ;
fp = libc_fopen64 ( name , mode ) ;
if ( fp ! = NULL ) {
int fd = fileno ( fp ) ;
swrap_remove_stale ( fd ) ;
}
return fp ;
}
FILE * fopen64 ( const char * name , const char * mode )
{
return swrap_fopen64 ( name , mode ) ;
}
# endif /* HAVE_FOPEN64 */
2014-04-07 18:12:21 +04:00
/****************************************************************************
* OPEN
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
static int swrap_vopen ( const char * pathname , int flags , va_list ap )
{
int ret ;
2006-09-27 14:13:45 +04:00
2014-04-07 18:12:21 +04:00
ret = libc_vopen ( pathname , flags , ap ) ;
if ( ret ! = - 1 ) {
/*
* There are methods for closing descriptors ( libc - internal code
* paths , direct syscalls ) which close descriptors in ways that
* we can ' t intercept , so try to recover when we notice that
* that ' s happened
*/
swrap_remove_stale ( ret ) ;
}
2006-09-27 14:13:45 +04:00
return ret ;
}
2014-04-07 18:12:21 +04:00
int open ( const char * pathname , int flags , . . . )
{
va_list ap ;
int fd ;
va_start ( ap , flags ) ;
fd = swrap_vopen ( pathname , flags , ap ) ;
va_end ( ap ) ;
return fd ;
}
2017-11-07 14:29:51 +03:00
/****************************************************************************
* OPEN64
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
# ifdef HAVE_OPEN64
static int swrap_vopen64 ( const char * pathname , int flags , va_list ap )
{
int ret ;
ret = libc_vopen64 ( pathname , flags , ap ) ;
if ( ret ! = - 1 ) {
/*
* There are methods for closing descriptors ( libc - internal code
* paths , direct syscalls ) which close descriptors in ways that
* we can ' t intercept , so try to recover when we notice that
* that ' s happened
*/
swrap_remove_stale ( ret ) ;
}
return ret ;
}
int open64 ( const char * pathname , int flags , . . . )
{
va_list ap ;
int fd ;
va_start ( ap , flags ) ;
fd = swrap_vopen64 ( pathname , flags , ap ) ;
va_end ( ap ) ;
return fd ;
}
# endif /* HAVE_OPEN64 */
/****************************************************************************
* OPENAT
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
static int swrap_vopenat ( int dirfd , const char * path , int flags , va_list ap )
{
int ret ;
ret = libc_vopenat ( dirfd , path , flags , ap ) ;
if ( ret ! = - 1 ) {
/*
* There are methods for closing descriptors ( libc - internal code
* paths , direct syscalls ) which close descriptors in ways that
* we can ' t intercept , so try to recover when we notice that
* that ' s happened
*/
swrap_remove_stale ( ret ) ;
}
return ret ;
}
int openat ( int dirfd , const char * path , int flags , . . . )
{
va_list ap ;
int fd ;
va_start ( ap , flags ) ;
fd = swrap_vopenat ( dirfd , path , flags , ap ) ;
va_end ( ap ) ;
return fd ;
}
2014-04-07 18:12:21 +04:00
/****************************************************************************
* GETPEERNAME
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
static int swrap_getpeername ( int s , struct sockaddr * name , socklen_t * addrlen )
2005-03-28 05:00:39 +04:00
{
struct socket_info * si = find_socket_info ( s ) ;
2014-06-03 16:58:24 +04:00
socklen_t len ;
2018-05-02 16:57:38 +03:00
int ret = - 1 ;
2005-03-28 05:00:39 +04:00
if ( ! si ) {
2014-04-07 18:12:21 +04:00
return libc_getpeername ( s , name , addrlen ) ;
2005-03-28 05:00:39 +04:00
}
2018-05-02 16:57:38 +03:00
SWRAP_LOCK_SI ( si ) ;
2014-10-02 09:17:10 +04:00
if ( si - > peername . sa_socklen = = 0 )
2005-03-28 05:00:39 +04:00
{
errno = ENOTCONN ;
2018-05-02 16:57:38 +03:00
goto out ;
2005-03-28 05:00:39 +04:00
}
2014-10-02 09:17:10 +04:00
len = MIN ( * addrlen , si - > peername . sa_socklen ) ;
2014-06-03 16:58:24 +04:00
if ( len = = 0 ) {
2018-05-02 16:57:38 +03:00
ret = 0 ;
goto out ;
2014-06-03 16:58:24 +04:00
}
2014-10-02 09:17:10 +04:00
memcpy ( name , & si - > peername . sa . ss , len ) ;
* addrlen = si - > peername . sa_socklen ;
2005-03-28 05:00:39 +04:00
2018-05-02 16:57:38 +03:00
ret = 0 ;
out :
SWRAP_UNLOCK_SI ( si ) ;
return ret ;
2005-03-28 05:00:39 +04:00
}
2014-04-07 18:12:21 +04:00
# ifdef HAVE_ACCEPT_PSOCKLEN_T
int getpeername ( int s , struct sockaddr * name , Psocklen_t addrlen )
# else
int getpeername ( int s , struct sockaddr * name , socklen_t * addrlen )
# endif
{
return swrap_getpeername ( s , name , ( socklen_t * ) addrlen ) ;
}
/****************************************************************************
* GETSOCKNAME
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
static int swrap_getsockname ( int s , struct sockaddr * name , socklen_t * addrlen )
2005-03-28 05:00:39 +04:00
{
struct socket_info * si = find_socket_info ( s ) ;
2014-06-03 16:58:24 +04:00
socklen_t len ;
2018-05-02 16:57:38 +03:00
int ret = - 1 ;
2005-03-28 05:00:39 +04:00
if ( ! si ) {
2014-04-07 18:12:21 +04:00
return libc_getsockname ( s , name , addrlen ) ;
2005-03-28 05:00:39 +04:00
}
2018-05-02 16:57:38 +03:00
SWRAP_LOCK_SI ( si ) ;
2014-10-02 09:17:10 +04:00
len = MIN ( * addrlen , si - > myname . sa_socklen ) ;
2014-06-03 16:58:24 +04:00
if ( len = = 0 ) {
2018-05-02 16:57:38 +03:00
ret = 0 ;
goto out ;
2014-06-03 16:58:24 +04:00
}
2014-10-02 09:17:10 +04:00
memcpy ( name , & si - > myname . sa . ss , len ) ;
* addrlen = si - > myname . sa_socklen ;
2005-03-28 05:00:39 +04:00
2018-05-02 16:57:38 +03:00
ret = 0 ;
out :
SWRAP_UNLOCK_SI ( si ) ;
return ret ;
2005-03-28 05:00:39 +04:00
}
2014-04-07 18:12:21 +04:00
# ifdef HAVE_ACCEPT_PSOCKLEN_T
int getsockname ( int s , struct sockaddr * name , Psocklen_t addrlen )
# else
int getsockname ( int s , struct sockaddr * name , socklen_t * addrlen )
# endif
{
return swrap_getsockname ( s , name , ( socklen_t * ) addrlen ) ;
}
/****************************************************************************
* GETSOCKOPT
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2014-06-03 17:05:56 +04:00
# ifndef SO_PROTOCOL
# ifdef SO_PROTOTYPE /* The Solaris name */
# define SO_PROTOCOL SO_PROTOTYPE
# endif /* SO_PROTOTYPE */
# endif /* SO_PROTOCOL */
2014-04-07 18:12:21 +04:00
static int swrap_getsockopt ( int s , int level , int optname ,
void * optval , socklen_t * optlen )
2005-03-28 05:00:39 +04:00
{
struct socket_info * si = find_socket_info ( s ) ;
2017-11-07 14:29:51 +03:00
int ret ;
2005-03-28 05:00:39 +04:00
if ( ! si ) {
2014-04-07 18:12:21 +04:00
return libc_getsockopt ( s ,
level ,
optname ,
optval ,
optlen ) ;
2005-03-28 05:00:39 +04:00
}
2018-05-02 16:57:38 +03:00
SWRAP_LOCK_SI ( si ) ;
2005-03-31 03:28:15 +04:00
if ( level = = SOL_SOCKET ) {
2014-06-03 17:05:56 +04:00
switch ( optname ) {
# ifdef SO_DOMAIN
case SO_DOMAIN :
if ( optval = = NULL | | optlen = = NULL | |
* optlen < ( socklen_t ) sizeof ( int ) ) {
errno = EINVAL ;
2017-11-07 14:29:51 +03:00
ret = - 1 ;
goto done ;
2014-06-03 17:05:56 +04:00
}
* optlen = sizeof ( int ) ;
* ( int * ) optval = si - > family ;
2017-11-07 14:29:51 +03:00
ret = 0 ;
goto done ;
2014-06-03 17:05:56 +04:00
# endif /* SO_DOMAIN */
2014-10-02 09:04:15 +04:00
# ifdef SO_PROTOCOL
2014-06-03 17:05:56 +04:00
case SO_PROTOCOL :
if ( optval = = NULL | | optlen = = NULL | |
* optlen < ( socklen_t ) sizeof ( int ) ) {
errno = EINVAL ;
2017-11-07 14:29:51 +03:00
ret = - 1 ;
goto done ;
2014-06-03 17:05:56 +04:00
}
* optlen = sizeof ( int ) ;
* ( int * ) optval = si - > protocol ;
2017-11-07 14:29:51 +03:00
ret = 0 ;
goto done ;
2014-10-02 09:04:15 +04:00
# endif /* SO_PROTOCOL */
2014-06-03 17:05:56 +04:00
case SO_TYPE :
if ( optval = = NULL | | optlen = = NULL | |
* optlen < ( socklen_t ) sizeof ( int ) ) {
errno = EINVAL ;
2017-11-07 14:29:51 +03:00
ret = - 1 ;
goto done ;
2014-06-03 17:05:56 +04:00
}
* optlen = sizeof ( int ) ;
* ( int * ) optval = si - > type ;
2017-11-07 14:29:51 +03:00
ret = 0 ;
goto done ;
2014-06-03 17:05:56 +04:00
default :
2017-11-07 14:29:51 +03:00
ret = libc_getsockopt ( s ,
level ,
optname ,
optval ,
optlen ) ;
goto done ;
2014-06-03 17:05:56 +04:00
}
2016-03-15 17:47:08 +03:00
} else if ( level = = IPPROTO_TCP ) {
switch ( optname ) {
# ifdef TCP_NODELAY
case TCP_NODELAY :
/*
* This enables sending packets directly out over TCP .
* As a unix socket is doing that any way , report it as
* enabled .
*/
if ( optval = = NULL | | optlen = = NULL | |
* optlen < ( socklen_t ) sizeof ( int ) ) {
errno = EINVAL ;
2017-11-07 14:29:51 +03:00
ret = - 1 ;
goto done ;
2016-03-15 17:47:08 +03:00
}
* optlen = sizeof ( int ) ;
* ( int * ) optval = si - > tcp_nodelay ;
2017-11-07 14:29:51 +03:00
ret = 0 ;
goto done ;
2016-03-15 17:47:08 +03:00
# endif /* TCP_NODELAY */
2020-06-08 15:18:00 +03:00
# ifdef TCP_INFO
case TCP_INFO : {
struct tcp_info info ;
socklen_t ilen = sizeof ( info ) ;
# ifdef HAVE_NETINET_TCP_FSM_H
/* This is FreeBSD */
# define __TCP_LISTEN TCPS_LISTEN
# define __TCP_ESTABLISHED TCPS_ESTABLISHED
# define __TCP_CLOSE TCPS_CLOSED
# else
/* This is Linux */
# define __TCP_LISTEN TCP_LISTEN
# define __TCP_ESTABLISHED TCP_ESTABLISHED
# define __TCP_CLOSE TCP_CLOSE
# endif
ZERO_STRUCT ( info ) ;
if ( si - > listening ) {
info . tcpi_state = __TCP_LISTEN ;
} else if ( si - > connected ) {
/*
* For now we just fake a few values
* supported both by FreeBSD and Linux
*/
info . tcpi_state = __TCP_ESTABLISHED ;
info . tcpi_rto = 200000 ; /* 200 msec */
info . tcpi_rtt = 5000 ; /* 5 msec */
info . tcpi_rttvar = 5000 ; /* 5 msec */
} else {
info . tcpi_state = __TCP_CLOSE ;
info . tcpi_rto = 1000000 ; /* 1 sec */
info . tcpi_rtt = 0 ;
info . tcpi_rttvar = 250000 ; /* 250 msec */
}
if ( optval = = NULL | | optlen = = NULL | |
* optlen < ( socklen_t ) ilen ) {
errno = EINVAL ;
ret = - 1 ;
goto done ;
}
* optlen = ilen ;
memcpy ( optval , & info , ilen ) ;
ret = 0 ;
goto done ;
}
# endif /* TCP_INFO */
2016-03-15 17:47:08 +03:00
default :
break ;
}
2014-04-07 18:12:21 +04:00
}
2005-03-31 03:28:15 +04:00
2006-09-12 18:59:08 +04:00
errno = ENOPROTOOPT ;
2017-11-07 14:29:51 +03:00
ret = - 1 ;
done :
2018-05-02 16:57:38 +03:00
SWRAP_UNLOCK_SI ( si ) ;
2017-11-07 14:29:51 +03:00
return ret ;
2005-03-28 05:00:39 +04:00
}
2014-04-07 18:12:21 +04:00
# ifdef HAVE_ACCEPT_PSOCKLEN_T
int getsockopt ( int s , int level , int optname , void * optval , Psocklen_t optlen )
# else
int getsockopt ( int s , int level , int optname , void * optval , socklen_t * optlen )
# endif
{
return swrap_getsockopt ( s , level , optname , optval , ( socklen_t * ) optlen ) ;
}
/****************************************************************************
* SETSOCKOPT
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
static int swrap_setsockopt ( int s , int level , int optname ,
const void * optval , socklen_t optlen )
2005-03-28 05:00:39 +04:00
{
struct socket_info * si = find_socket_info ( s ) ;
2017-11-07 14:29:51 +03:00
int ret ;
2005-03-28 05:00:39 +04:00
if ( ! si ) {
2014-04-07 18:12:21 +04:00
return libc_setsockopt ( s ,
level ,
optname ,
optval ,
optlen ) ;
2005-03-28 05:00:39 +04:00
}
2005-03-31 03:28:15 +04:00
if ( level = = SOL_SOCKET ) {
2014-04-07 18:12:21 +04:00
return libc_setsockopt ( s ,
level ,
optname ,
optval ,
optlen ) ;
2018-05-02 16:57:38 +03:00
}
SWRAP_LOCK_SI ( si ) ;
if ( level = = IPPROTO_TCP ) {
2016-03-15 17:47:08 +03:00
switch ( optname ) {
# ifdef TCP_NODELAY
case TCP_NODELAY : {
int i ;
/*
* This enables sending packets directly out over TCP .
* A unix socket is doing that any way .
*/
if ( optval = = NULL | | optlen = = 0 | |
optlen < ( socklen_t ) sizeof ( int ) ) {
errno = EINVAL ;
2017-11-07 14:29:51 +03:00
ret = - 1 ;
goto done ;
2016-03-15 17:47:08 +03:00
}
i = * discard_const_p ( int , optval ) ;
if ( i ! = 0 & & i ! = 1 ) {
errno = EINVAL ;
2017-11-07 14:29:51 +03:00
ret = - 1 ;
goto done ;
2016-03-15 17:47:08 +03:00
}
si - > tcp_nodelay = i ;
2017-11-07 14:29:51 +03:00
ret = 0 ;
goto done ;
2016-03-15 17:47:08 +03:00
}
# endif /* TCP_NODELAY */
default :
break ;
}
2005-03-31 03:28:15 +04:00
}
2006-09-12 18:59:08 +04:00
switch ( si - > family ) {
2005-03-31 03:28:15 +04:00
case AF_INET :
2014-06-03 16:54:28 +04:00
if ( level = = IPPROTO_IP ) {
# ifdef IP_PKTINFO
if ( optname = = IP_PKTINFO ) {
si - > pktinfo = AF_INET ;
}
# endif /* IP_PKTINFO */
}
2017-11-07 14:29:51 +03:00
ret = 0 ;
goto done ;
2010-02-17 11:43:00 +03:00
# ifdef HAVE_IPV6
case AF_INET6 :
2014-06-03 16:54:28 +04:00
if ( level = = IPPROTO_IPV6 ) {
# ifdef IPV6_RECVPKTINFO
if ( optname = = IPV6_RECVPKTINFO ) {
si - > pktinfo = AF_INET6 ;
}
# endif /* IPV6_PKTINFO */
}
2017-11-07 14:29:51 +03:00
ret = 0 ;
goto done ;
2010-02-17 11:43:00 +03:00
# endif
2005-03-31 03:28:15 +04:00
default :
2005-03-28 05:00:39 +04:00
errno = ENOPROTOOPT ;
2017-11-07 14:29:51 +03:00
ret = - 1 ;
goto done ;
2005-03-28 05:00:39 +04:00
}
2017-11-07 14:29:51 +03:00
done :
2018-05-02 16:57:38 +03:00
SWRAP_UNLOCK_SI ( si ) ;
2017-11-07 14:29:51 +03:00
return ret ;
2005-03-28 05:00:39 +04:00
}
2014-04-07 18:12:21 +04:00
int setsockopt ( int s , int level , int optname ,
const void * optval , socklen_t optlen )
{
return swrap_setsockopt ( s , level , optname , optval , optlen ) ;
}
/****************************************************************************
* IOCTL
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
static int swrap_vioctl ( int s , unsigned long int r , va_list va )
2010-10-30 18:19:33 +04:00
{
struct socket_info * si = find_socket_info ( s ) ;
2014-04-07 18:12:21 +04:00
va_list ap ;
2020-06-08 15:18:00 +03:00
int * value_ptr = NULL ;
2014-04-07 18:12:21 +04:00
int rc ;
2010-10-30 18:19:33 +04:00
if ( ! si ) {
2014-04-07 18:12:21 +04:00
return libc_vioctl ( s , r , va ) ;
2010-10-30 18:19:33 +04:00
}
2018-05-02 16:57:38 +03:00
SWRAP_LOCK_SI ( si ) ;
2014-04-07 18:12:21 +04:00
va_copy ( ap , va ) ;
rc = libc_vioctl ( s , r , va ) ;
2010-10-30 18:19:33 +04:00
switch ( r ) {
case FIONREAD :
2020-06-08 15:18:00 +03:00
if ( rc = = 0 ) {
value_ptr = ( ( int * ) va_arg ( ap , int * ) ) ;
}
2014-04-07 18:12:21 +04:00
if ( rc = = - 1 & & errno ! = EAGAIN & & errno ! = ENOBUFS ) {
2014-10-02 09:15:38 +04:00
swrap_pcap_dump_packet ( si , NULL , SWRAP_PENDING_RST , NULL , 0 ) ;
2020-06-08 15:18:00 +03:00
} else if ( value_ptr ! = NULL & & * value_ptr = = 0 ) { /* END OF FILE */
2014-10-02 09:15:38 +04:00
swrap_pcap_dump_packet ( si , NULL , SWRAP_PENDING_RST , NULL , 0 ) ;
2010-10-30 18:19:33 +04:00
}
break ;
2020-06-08 15:18:00 +03:00
# ifdef FIONWRITE
case FIONWRITE :
/* this is FreeBSD */
FALL_THROUGH ; /* to TIOCOUTQ */
# endif /* FIONWRITE */
case TIOCOUTQ : /* same as SIOCOUTQ on Linux */
/*
* This may return more bytes then the application
* sent into the socket , for tcp it should
* return the number of unacked bytes .
*
* On AF_UNIX , all bytes are immediately acked !
*/
if ( rc = = 0 ) {
value_ptr = ( ( int * ) va_arg ( ap , int * ) ) ;
* value_ptr = 0 ;
}
break ;
2010-10-30 18:19:33 +04:00
}
2014-04-07 18:12:21 +04:00
va_end ( ap ) ;
2018-05-02 16:57:38 +03:00
SWRAP_UNLOCK_SI ( si ) ;
2014-04-07 18:12:21 +04:00
return rc ;
}
# ifdef HAVE_IOCTL_INT
int ioctl ( int s , int r , . . . )
# else
int ioctl ( int s , unsigned long int r , . . . )
# endif
{
va_list va ;
int rc ;
va_start ( va , r ) ;
rc = swrap_vioctl ( s , ( unsigned long int ) r , va ) ;
va_end ( va ) ;
return rc ;
2010-10-30 18:19:33 +04:00
}
2014-06-03 16:55:13 +04:00
/*****************
* CMSG
* * * * * * * * * * * * * * * * */
# ifdef HAVE_STRUCT_MSGHDR_MSG_CONTROL
2014-06-03 17:03:41 +04:00
# ifndef CMSG_ALIGN
# ifdef _ALIGN /* BSD */
# define CMSG_ALIGN _ALIGN
# else
2014-10-02 09:05:35 +04:00
# define CMSG_ALIGN(len) (((len) + sizeof(size_t) - 1) & ~(sizeof(size_t) - 1))
2014-06-03 17:03:41 +04:00
# endif /* _ALIGN */
# endif /* CMSG_ALIGN */
2014-06-03 16:55:13 +04:00
/**
* @ brief Add a cmsghdr to a msghdr .
*
* This is an function to add any type of cmsghdr . It will operate on the
* msg - > msg_control and msg - > msg_controllen you pass in by adapting them to
* the buffer position after the added cmsg element . Hence , this function is
* intended to be used with an intermediate msghdr and not on the original
* one handed in by the client .
*
* @ param [ in ] msg The msghdr to which to add the cmsg .
*
* @ param [ in ] level The cmsg level to set .
*
* @ param [ in ] type The cmsg type to set .
*
* @ param [ in ] data The cmsg data to set .
*
* @ param [ in ] len the length of the data to set .
*/
static void swrap_msghdr_add_cmsghdr ( struct msghdr * msg ,
int level ,
int type ,
const void * data ,
size_t len )
{
size_t cmlen = CMSG_LEN ( len ) ;
size_t cmspace = CMSG_SPACE ( len ) ;
uint8_t cmbuf [ cmspace ] ;
2014-10-02 09:09:33 +04:00
void * cast_ptr = ( void * ) cmbuf ;
struct cmsghdr * cm = ( struct cmsghdr * ) cast_ptr ;
2014-06-03 16:55:13 +04:00
uint8_t * p ;
memset ( cmbuf , 0 , cmspace ) ;
if ( msg - > msg_controllen < cmlen ) {
cmlen = msg - > msg_controllen ;
msg - > msg_flags | = MSG_CTRUNC ;
}
if ( msg - > msg_controllen < cmspace ) {
cmspace = msg - > msg_controllen ;
}
/*
* We copy the full input data into an intermediate cmsghdr first
* in order to more easily cope with truncation .
*/
cm - > cmsg_len = cmlen ;
cm - > cmsg_level = level ;
cm - > cmsg_type = type ;
memcpy ( CMSG_DATA ( cm ) , data , len ) ;
/*
* We now copy the possibly truncated buffer .
* We copy cmlen bytes , but consume cmspace bytes ,
* leaving the possible padding uninitialiazed .
*/
p = ( uint8_t * ) msg - > msg_control ;
memcpy ( p , cm , cmlen ) ;
p + = cmspace ;
msg - > msg_control = p ;
msg - > msg_controllen - = cmspace ;
return ;
}
2014-06-03 16:55:49 +04:00
static int swrap_msghdr_add_pktinfo ( struct socket_info * si ,
struct msghdr * msg )
{
/* Add packet info */
switch ( si - > pktinfo ) {
2014-10-02 09:00:44 +04:00
# if defined(IP_PKTINFO) && (defined(HAVE_STRUCT_IN_PKTINFO) || defined(IP_RECVDSTADDR))
2014-06-03 16:55:49 +04:00
case AF_INET : {
struct sockaddr_in * sin ;
2014-06-03 17:02:17 +04:00
# if defined(HAVE_STRUCT_IN_PKTINFO)
2014-06-03 16:55:49 +04:00
struct in_pktinfo pkt ;
2014-06-03 17:02:17 +04:00
# elif defined(IP_RECVDSTADDR)
struct in_addr pkt ;
# endif
2014-06-03 16:55:49 +04:00
2014-10-02 09:17:10 +04:00
if ( si - > bindname . sa_socklen = = sizeof ( struct sockaddr_in ) ) {
sin = & si - > bindname . sa . in ;
2014-06-03 16:55:49 +04:00
} else {
2014-10-02 09:17:10 +04:00
if ( si - > myname . sa_socklen ! = sizeof ( struct sockaddr_in ) ) {
2014-06-03 16:55:49 +04:00
return 0 ;
}
2014-10-02 09:17:10 +04:00
sin = & si - > myname . sa . in ;
2014-06-03 16:55:49 +04:00
}
ZERO_STRUCT ( pkt ) ;
2014-06-03 17:02:17 +04:00
# if defined(HAVE_STRUCT_IN_PKTINFO)
2014-06-03 16:55:49 +04:00
pkt . ipi_ifindex = socket_wrapper_default_iface ( ) ;
pkt . ipi_addr . s_addr = sin - > sin_addr . s_addr ;
2014-06-03 17:02:17 +04:00
# elif defined(IP_RECVDSTADDR)
pkt = sin - > sin_addr ;
# endif
2014-06-03 16:55:49 +04:00
swrap_msghdr_add_cmsghdr ( msg , IPPROTO_IP , IP_PKTINFO ,
& pkt , sizeof ( pkt ) ) ;
break ;
}
# endif /* IP_PKTINFO */
# if defined(HAVE_IPV6)
case AF_INET6 : {
# if defined(IPV6_PKTINFO) && defined(HAVE_STRUCT_IN6_PKTINFO)
struct sockaddr_in6 * sin6 ;
struct in6_pktinfo pkt6 ;
2014-10-02 09:17:10 +04:00
if ( si - > bindname . sa_socklen = = sizeof ( struct sockaddr_in6 ) ) {
sin6 = & si - > bindname . sa . in6 ;
2014-06-03 16:55:49 +04:00
} else {
2014-10-02 09:17:10 +04:00
if ( si - > myname . sa_socklen ! = sizeof ( struct sockaddr_in6 ) ) {
2014-06-03 16:55:49 +04:00
return 0 ;
}
2014-10-02 09:17:10 +04:00
sin6 = & si - > myname . sa . in6 ;
2014-06-03 16:55:49 +04:00
}
ZERO_STRUCT ( pkt6 ) ;
pkt6 . ipi6_ifindex = socket_wrapper_default_iface ( ) ;
pkt6 . ipi6_addr = sin6 - > sin6_addr ;
swrap_msghdr_add_cmsghdr ( msg , IPPROTO_IPV6 , IPV6_PKTINFO ,
& pkt6 , sizeof ( pkt6 ) ) ;
# endif /* HAVE_STRUCT_IN6_PKTINFO */
break ;
}
# endif /* IPV6_PKTINFO */
default :
return - 1 ;
}
return 0 ;
}
2014-06-03 16:56:28 +04:00
static int swrap_msghdr_add_socket_info ( struct socket_info * si ,
struct msghdr * omsg )
{
int rc = 0 ;
if ( si - > pktinfo > 0 ) {
rc = swrap_msghdr_add_pktinfo ( si , omsg ) ;
}
return rc ;
}
2014-06-03 17:03:03 +04:00
2021-02-09 10:56:42 +03:00
static int swrap_sendmsg_copy_cmsg ( const struct cmsghdr * cmsg ,
2014-06-03 17:06:33 +04:00
uint8_t * * cm_data ,
2014-06-03 17:03:41 +04:00
size_t * cm_data_space ) ;
2021-02-09 10:56:42 +03:00
static int swrap_sendmsg_filter_cmsg_ipproto_ip ( const struct cmsghdr * cmsg ,
uint8_t * * cm_data ,
size_t * cm_data_space ) ;
static int swrap_sendmsg_filter_cmsg_sol_socket ( const struct cmsghdr * cmsg ,
uint8_t * * cm_data ,
size_t * cm_data_space ) ;
static int swrap_sendmsg_filter_cmsghdr ( const struct msghdr * _msg ,
2014-06-03 17:06:33 +04:00
uint8_t * * cm_data ,
2021-02-09 10:56:42 +03:00
size_t * cm_data_space )
{
struct msghdr * msg = discard_const_p ( struct msghdr , _msg ) ;
2014-06-03 17:03:03 +04:00
struct cmsghdr * cmsg ;
int rc = - 1 ;
/* Nothing to do */
if ( msg - > msg_controllen = = 0 | | msg - > msg_control = = NULL ) {
return 0 ;
}
for ( cmsg = CMSG_FIRSTHDR ( msg ) ;
cmsg ! = NULL ;
cmsg = CMSG_NXTHDR ( msg , cmsg ) ) {
switch ( cmsg - > cmsg_level ) {
case IPPROTO_IP :
2021-02-09 10:56:42 +03:00
rc = swrap_sendmsg_filter_cmsg_ipproto_ip ( cmsg ,
cm_data ,
cm_data_space ) ;
break ;
case SOL_SOCKET :
rc = swrap_sendmsg_filter_cmsg_sol_socket ( cmsg ,
cm_data ,
cm_data_space ) ;
2014-06-03 17:03:03 +04:00
break ;
default :
2014-06-03 17:03:41 +04:00
rc = swrap_sendmsg_copy_cmsg ( cmsg ,
cm_data ,
cm_data_space ) ;
2014-06-03 17:03:03 +04:00
break ;
}
2021-02-09 10:56:42 +03:00
if ( rc < 0 ) {
int saved_errno = errno ;
SAFE_FREE ( * cm_data ) ;
* cm_data_space = 0 ;
errno = saved_errno ;
return rc ;
}
2014-06-03 17:03:03 +04:00
}
return rc ;
}
2014-06-03 17:03:41 +04:00
2021-02-09 10:56:42 +03:00
static int swrap_sendmsg_copy_cmsg ( const struct cmsghdr * cmsg ,
2014-06-03 17:06:33 +04:00
uint8_t * * cm_data ,
2014-06-03 17:03:41 +04:00
size_t * cm_data_space )
{
size_t cmspace ;
uint8_t * p ;
2016-03-15 17:47:08 +03:00
cmspace = * cm_data_space + CMSG_ALIGN ( cmsg - > cmsg_len ) ;
2014-06-03 17:03:41 +04:00
2014-06-03 17:06:33 +04:00
p = realloc ( ( * cm_data ) , cmspace ) ;
2014-06-03 17:03:41 +04:00
if ( p = = NULL ) {
return - 1 ;
}
2014-06-03 17:06:33 +04:00
( * cm_data ) = p ;
2014-06-03 17:03:41 +04:00
2014-06-03 17:06:33 +04:00
p = ( * cm_data ) + ( * cm_data_space ) ;
2014-06-03 17:03:41 +04:00
* cm_data_space = cmspace ;
memcpy ( p , cmsg , cmsg - > cmsg_len ) ;
return 0 ;
}
2014-06-03 17:04:18 +04:00
2021-02-09 10:56:42 +03:00
static int swrap_sendmsg_filter_cmsg_pktinfo ( const struct cmsghdr * cmsg ,
2014-06-03 17:06:33 +04:00
uint8_t * * cm_data ,
2014-06-03 17:04:45 +04:00
size_t * cm_data_space ) ;
2021-02-09 10:56:42 +03:00
static int swrap_sendmsg_filter_cmsg_ipproto_ip ( const struct cmsghdr * cmsg ,
uint8_t * * cm_data ,
size_t * cm_data_space )
2014-06-03 17:04:18 +04:00
{
int rc = - 1 ;
switch ( cmsg - > cmsg_type ) {
# ifdef IP_PKTINFO
case IP_PKTINFO :
2014-06-03 17:04:45 +04:00
rc = swrap_sendmsg_filter_cmsg_pktinfo ( cmsg ,
cm_data ,
cm_data_space ) ;
2014-06-03 17:04:18 +04:00
break ;
# endif
# ifdef IPV6_PKTINFO
case IPV6_PKTINFO :
2014-06-03 17:04:45 +04:00
rc = swrap_sendmsg_filter_cmsg_pktinfo ( cmsg ,
cm_data ,
cm_data_space ) ;
2014-06-03 17:04:18 +04:00
break ;
# endif
default :
break ;
}
return rc ;
}
2014-06-03 17:04:45 +04:00
2021-02-09 10:56:42 +03:00
static int swrap_sendmsg_filter_cmsg_pktinfo ( const struct cmsghdr * cmsg ,
2014-06-03 17:06:33 +04:00
uint8_t * * cm_data ,
2014-06-03 17:04:45 +04:00
size_t * cm_data_space )
{
( void ) cmsg ; /* unused */
( void ) cm_data ; /* unused */
( void ) cm_data_space ; /* unused */
/*
* Passing a IP pktinfo to a unix socket might be rejected by the
* Kernel , at least on FreeBSD . So skip this cmsg .
*/
return 0 ;
}
2014-06-03 16:55:13 +04:00
2021-02-09 10:56:42 +03:00
static int swrap_sendmsg_filter_cmsg_sol_socket ( const struct cmsghdr * cmsg ,
uint8_t * * cm_data ,
size_t * cm_data_space )
2010-10-30 18:08:49 +04:00
{
2021-02-09 10:56:42 +03:00
int rc = - 1 ;
2010-10-30 18:08:49 +04:00
2021-02-09 10:56:42 +03:00
switch ( cmsg - > cmsg_type ) {
case SCM_RIGHTS :
SWRAP_LOG ( SWRAP_LOG_TRACE ,
" Ignoring SCM_RIGHTS on inet socket! " ) ;
rc = 0 ;
break ;
# ifdef SCM_CREDENTIALS
case SCM_CREDENTIALS :
SWRAP_LOG ( SWRAP_LOG_TRACE ,
" Ignoring SCM_CREDENTIALS on inet socket! " ) ;
rc = 0 ;
break ;
# endif /* SCM_CREDENTIALS */
default :
rc = swrap_sendmsg_copy_cmsg ( cmsg ,
cm_data ,
cm_data_space ) ;
break ;
2010-10-30 18:08:49 +04:00
}
2021-02-09 10:56:42 +03:00
return rc ;
}
2018-05-02 16:57:38 +03:00
2021-02-09 10:56:42 +03:00
static const uint64_t swrap_unix_scm_right_magic = 0x8e0e13f27c42fc36 ;
2015-08-25 18:20:20 +03:00
2021-02-09 10:56:42 +03:00
/*
* We only allow up to 6 fds at a time
* as that ' s more than enough for Samba
* and it means we can keep the logic simple
* and work with fixed size arrays .
*
* We also keep sizeof ( struct swrap_unix_scm_rights )
* under PIPE_BUF ( 4096 ) in order to allow a non - blocking
* write into the pipe .
*/
# ifndef PIPE_BUF
# define PIPE_BUF 4096
# endif
# define SWRAP_MAX_PASSED_FDS ((size_t)6)
# define SWRAP_MAX_PASSED_SOCKET_INFO SWRAP_MAX_PASSED_FDS
struct swrap_unix_scm_rights_payload {
uint8_t num_idxs ;
int8_t idxs [ SWRAP_MAX_PASSED_FDS ] ;
struct socket_info infos [ SWRAP_MAX_PASSED_SOCKET_INFO ] ;
} ;
struct swrap_unix_scm_rights {
uint64_t magic ;
char package_name [ sizeof ( SOCKET_WRAPPER_PACKAGE ) ] ;
char package_version [ sizeof ( SOCKET_WRAPPER_VERSION ) ] ;
uint32_t full_size ;
uint32_t payload_size ;
struct swrap_unix_scm_rights_payload payload ;
} ;
static void swrap_dec_fd_passed_array ( size_t num , struct socket_info * * array )
{
int saved_errno = errno ;
size_t i ;
for ( i = 0 ; i < num ; i + + ) {
struct socket_info * si = array [ i ] ;
if ( si = = NULL ) {
continue ;
2010-10-30 18:08:49 +04:00
}
2021-02-09 10:56:42 +03:00
SWRAP_LOCK_SI ( si ) ;
swrap_dec_refcount ( si ) ;
if ( si - > fd_passed > 0 ) {
si - > fd_passed - = 1 ;
2010-10-30 18:08:49 +04:00
}
2021-02-09 10:56:42 +03:00
SWRAP_UNLOCK_SI ( si ) ;
array [ i ] = NULL ;
}
2010-10-30 18:08:49 +04:00
2021-02-09 10:56:42 +03:00
errno = saved_errno ;
}
static void swrap_undo_si_idx_array ( size_t num , int * array )
{
int saved_errno = errno ;
size_t i ;
swrap_mutex_lock ( & first_free_mutex ) ;
for ( i = 0 ; i < num ; i + + ) {
struct socket_info * si = NULL ;
if ( array [ i ] = = - 1 ) {
continue ;
}
si = swrap_get_socket_info ( array [ i ] ) ;
if ( si = = NULL ) {
continue ;
}
SWRAP_LOCK_SI ( si ) ;
swrap_dec_refcount ( si ) ;
SWRAP_UNLOCK_SI ( si ) ;
swrap_set_next_free ( si , first_free ) ;
first_free = array [ i ] ;
array [ i ] = - 1 ;
}
swrap_mutex_unlock ( & first_free_mutex ) ;
errno = saved_errno ;
}
static void swrap_close_fd_array ( size_t num , const int * array )
{
int saved_errno = errno ;
size_t i ;
for ( i = 0 ; i < num ; i + + ) {
if ( array [ i ] = = - 1 ) {
continue ;
}
libc_close ( array [ i ] ) ;
}
errno = saved_errno ;
}
union __swrap_fds {
const uint8_t * p ;
int * fds ;
} ;
union __swrap_cmsghdr {
const uint8_t * p ;
struct cmsghdr * cmsg ;
} ;
static int swrap_sendmsg_unix_scm_rights ( const struct cmsghdr * cmsg ,
uint8_t * * cm_data ,
size_t * cm_data_space ,
int * scm_rights_pipe_fd )
{
struct swrap_unix_scm_rights info ;
struct swrap_unix_scm_rights_payload * payload = NULL ;
int si_idx_array [ SWRAP_MAX_PASSED_FDS ] ;
struct socket_info * si_array [ SWRAP_MAX_PASSED_FDS ] = { NULL , } ;
size_t info_idx = 0 ;
size_t size_fds_in ;
size_t num_fds_in ;
union __swrap_fds __fds_in = { . p = NULL , } ;
const int * fds_in = NULL ;
size_t num_fds_out ;
size_t size_fds_out ;
union __swrap_fds __fds_out = { . p = NULL , } ;
int * fds_out = NULL ;
size_t cmsg_len ;
size_t cmsg_space ;
size_t new_cm_data_space ;
union __swrap_cmsghdr __new_cmsg = { . p = NULL , } ;
struct cmsghdr * new_cmsg = NULL ;
uint8_t * p = NULL ;
size_t i ;
int pipefd [ 2 ] = { - 1 , - 1 } ;
int rc ;
ssize_t sret ;
/*
* We pass this a buffer to the kernel make sure any padding
* is also cleared .
*/
ZERO_STRUCT ( info ) ;
info . magic = swrap_unix_scm_right_magic ;
memcpy ( info . package_name ,
SOCKET_WRAPPER_PACKAGE ,
sizeof ( info . package_name ) ) ;
memcpy ( info . package_version ,
SOCKET_WRAPPER_VERSION ,
sizeof ( info . package_version ) ) ;
info . full_size = sizeof ( info ) ;
info . payload_size = sizeof ( info . payload ) ;
payload = & info . payload ;
if ( * scm_rights_pipe_fd ! = - 1 ) {
SWRAP_LOG ( SWRAP_LOG_ERROR ,
" Two SCM_RIGHTS headers are not supported by socket_wrapper " ) ;
errno = EINVAL ;
return - 1 ;
}
if ( cmsg - > cmsg_len < CMSG_LEN ( 0 ) ) {
SWRAP_LOG ( SWRAP_LOG_ERROR ,
" cmsg->cmsg_len=%zu < CMSG_LEN(0)=%zu " ,
( size_t ) cmsg - > cmsg_len ,
CMSG_LEN ( 0 ) ) ;
errno = EINVAL ;
return - 1 ;
}
size_fds_in = cmsg - > cmsg_len - CMSG_LEN ( 0 ) ;
if ( ( size_fds_in % sizeof ( int ) ) ! = 0 ) {
SWRAP_LOG ( SWRAP_LOG_ERROR ,
" cmsg->cmsg_len=%zu => (size_fds_in=%zu %% sizeof(int)=%zu) != 0 " ,
( size_t ) cmsg - > cmsg_len ,
size_fds_in ,
sizeof ( int ) ) ;
errno = EINVAL ;
return - 1 ;
}
num_fds_in = size_fds_in / sizeof ( int ) ;
if ( num_fds_in > SWRAP_MAX_PASSED_FDS ) {
SWRAP_LOG ( SWRAP_LOG_ERROR ,
" cmsg->cmsg_len=%zu,size_fds_in=%zu => "
" num_fds_in=%zu > "
" SWRAP_MAX_PASSED_FDS(%zu) " ,
( size_t ) cmsg - > cmsg_len ,
size_fds_in ,
num_fds_in ,
SWRAP_MAX_PASSED_FDS ) ;
errno = EINVAL ;
return - 1 ;
}
if ( num_fds_in = = 0 ) {
SWRAP_LOG ( SWRAP_LOG_ERROR ,
" cmsg->cmsg_len=%zu,size_fds_in=%zu => "
" num_fds_in=%zu " ,
( size_t ) cmsg - > cmsg_len ,
size_fds_in ,
num_fds_in ) ;
errno = EINVAL ;
return - 1 ;
}
__fds_in . p = CMSG_DATA ( cmsg ) ;
fds_in = __fds_in . fds ;
num_fds_out = num_fds_in + 1 ;
SWRAP_LOG ( SWRAP_LOG_TRACE ,
" num_fds_in=%zu num_fds_out=%zu " ,
num_fds_in , num_fds_out ) ;
size_fds_out = sizeof ( int ) * num_fds_out ;
cmsg_len = CMSG_LEN ( size_fds_out ) ;
cmsg_space = CMSG_SPACE ( size_fds_out ) ;
new_cm_data_space = * cm_data_space + cmsg_space ;
p = realloc ( ( * cm_data ) , new_cm_data_space ) ;
if ( p = = NULL ) {
return - 1 ;
}
( * cm_data ) = p ;
p = ( * cm_data ) + ( * cm_data_space ) ;
memset ( p , 0 , cmsg_space ) ;
__new_cmsg . p = p ;
new_cmsg = __new_cmsg . cmsg ;
* new_cmsg = * cmsg ;
__fds_out . p = CMSG_DATA ( new_cmsg ) ;
fds_out = __fds_out . fds ;
memcpy ( fds_out , fds_in , size_fds_in ) ;
new_cmsg - > cmsg_len = cmsg - > cmsg_len ;
for ( i = 0 ; i < num_fds_in ; i + + ) {
size_t j ;
payload - > idxs [ i ] = - 1 ;
payload - > num_idxs + + ;
si_idx_array [ i ] = find_socket_info_index ( fds_in [ i ] ) ;
if ( si_idx_array [ i ] = = - 1 ) {
continue ;
}
si_array [ i ] = swrap_get_socket_info ( si_idx_array [ i ] ) ;
if ( si_array [ i ] = = NULL ) {
SWRAP_LOG ( SWRAP_LOG_ERROR ,
" fds_in[%zu]=%d si_idx_array[%zu]=%d missing! " ,
i , fds_in [ i ] , i , si_idx_array [ i ] ) ;
errno = EINVAL ;
return - 1 ;
}
for ( j = 0 ; j < i ; j + + ) {
if ( si_array [ j ] = = si_array [ i ] ) {
payload - > idxs [ i ] = payload - > idxs [ j ] ;
break ;
}
}
if ( payload - > idxs [ i ] = = - 1 ) {
if ( info_idx > = SWRAP_MAX_PASSED_SOCKET_INFO ) {
SWRAP_LOG ( SWRAP_LOG_ERROR ,
" fds_in[%zu]=%d,si_idx_array[%zu]=%d: "
" info_idx=%zu >= SWRAP_MAX_PASSED_FDS(%zu)! " ,
i , fds_in [ i ] , i , si_idx_array [ i ] ,
info_idx ,
SWRAP_MAX_PASSED_SOCKET_INFO ) ;
errno = EINVAL ;
return - 1 ;
}
payload - > idxs [ i ] = info_idx ;
info_idx + = 1 ;
continue ;
}
}
for ( i = 0 ; i < num_fds_in ; i + + ) {
struct socket_info * si = si_array [ i ] ;
if ( si = = NULL ) {
SWRAP_LOG ( SWRAP_LOG_TRACE ,
" fds_in[%zu]=%d not an inet socket " ,
i , fds_in [ i ] ) ;
continue ;
}
SWRAP_LOG ( SWRAP_LOG_TRACE ,
" fds_in[%zu]=%d si_idx_array[%zu]=%d "
" passing as info.idxs[%zu]=%d! " ,
i , fds_in [ i ] ,
i , si_idx_array [ i ] ,
i , payload - > idxs [ i ] ) ;
SWRAP_LOCK_SI ( si ) ;
si - > fd_passed + = 1 ;
payload - > infos [ payload - > idxs [ i ] ] = * si ;
payload - > infos [ payload - > idxs [ i ] ] . fd_passed = 0 ;
SWRAP_UNLOCK_SI ( si ) ;
}
rc = pipe ( pipefd ) ;
if ( rc = = - 1 ) {
int saved_errno = errno ;
SWRAP_LOG ( SWRAP_LOG_ERROR ,
" pipe() failed - %d %s " ,
saved_errno ,
strerror ( saved_errno ) ) ;
swrap_dec_fd_passed_array ( num_fds_in , si_array ) ;
errno = saved_errno ;
return - 1 ;
}
2021-02-17 14:57:01 +03:00
sret = libc_write ( pipefd [ 1 ] , & info , sizeof ( info ) ) ;
2021-02-09 10:56:42 +03:00
if ( sret ! = sizeof ( info ) ) {
int saved_errno = errno ;
if ( sret ! = - 1 ) {
saved_errno = EINVAL ;
}
SWRAP_LOG ( SWRAP_LOG_ERROR ,
" write() failed - sret=%zd - %d %s " ,
sret , saved_errno ,
strerror ( saved_errno ) ) ;
swrap_dec_fd_passed_array ( num_fds_in , si_array ) ;
libc_close ( pipefd [ 1 ] ) ;
libc_close ( pipefd [ 0 ] ) ;
errno = saved_errno ;
return - 1 ;
}
libc_close ( pipefd [ 1 ] ) ;
/*
* Add the pipe read end to the end of the passed fd array
*/
fds_out [ num_fds_in ] = pipefd [ 0 ] ;
new_cmsg - > cmsg_len = cmsg_len ;
/* we're done ... */
* scm_rights_pipe_fd = pipefd [ 0 ] ;
* cm_data_space = new_cm_data_space ;
return 0 ;
}
static int swrap_sendmsg_unix_sol_socket ( const struct cmsghdr * cmsg ,
uint8_t * * cm_data ,
size_t * cm_data_space ,
int * scm_rights_pipe_fd )
{
int rc = - 1 ;
switch ( cmsg - > cmsg_type ) {
case SCM_RIGHTS :
rc = swrap_sendmsg_unix_scm_rights ( cmsg ,
cm_data ,
cm_data_space ,
scm_rights_pipe_fd ) ;
break ;
default :
rc = swrap_sendmsg_copy_cmsg ( cmsg ,
cm_data ,
cm_data_space ) ;
break ;
}
return rc ;
}
static int swrap_recvmsg_unix_scm_rights ( const struct cmsghdr * cmsg ,
uint8_t * * cm_data ,
size_t * cm_data_space )
{
int scm_rights_pipe_fd = - 1 ;
struct swrap_unix_scm_rights info ;
struct swrap_unix_scm_rights_payload * payload = NULL ;
int si_idx_array [ SWRAP_MAX_PASSED_FDS ] ;
size_t size_fds_in ;
size_t num_fds_in ;
union __swrap_fds __fds_in = { . p = NULL , } ;
const int * fds_in = NULL ;
size_t num_fds_out ;
size_t size_fds_out ;
union __swrap_fds __fds_out = { . p = NULL , } ;
int * fds_out = NULL ;
size_t cmsg_len ;
size_t cmsg_space ;
size_t new_cm_data_space ;
union __swrap_cmsghdr __new_cmsg = { . p = NULL , } ;
struct cmsghdr * new_cmsg = NULL ;
uint8_t * p = NULL ;
ssize_t sret ;
size_t i ;
int cmp ;
if ( cmsg - > cmsg_len < CMSG_LEN ( 0 ) ) {
SWRAP_LOG ( SWRAP_LOG_ERROR ,
" cmsg->cmsg_len=%zu < CMSG_LEN(0)=%zu " ,
( size_t ) cmsg - > cmsg_len ,
CMSG_LEN ( 0 ) ) ;
errno = EINVAL ;
return - 1 ;
}
size_fds_in = cmsg - > cmsg_len - CMSG_LEN ( 0 ) ;
if ( ( size_fds_in % sizeof ( int ) ) ! = 0 ) {
SWRAP_LOG ( SWRAP_LOG_ERROR ,
" cmsg->cmsg_len=%zu => (size_fds_in=%zu %% sizeof(int)=%zu) != 0 " ,
( size_t ) cmsg - > cmsg_len ,
size_fds_in ,
sizeof ( int ) ) ;
errno = EINVAL ;
return - 1 ;
}
num_fds_in = size_fds_in / sizeof ( int ) ;
if ( num_fds_in > ( SWRAP_MAX_PASSED_FDS + 1 ) ) {
SWRAP_LOG ( SWRAP_LOG_ERROR ,
" cmsg->cmsg_len=%zu,size_fds_in=%zu => "
" num_fds_in=%zu > SWRAP_MAX_PASSED_FDS+1(%zu) " ,
( size_t ) cmsg - > cmsg_len ,
size_fds_in ,
num_fds_in ,
SWRAP_MAX_PASSED_FDS + 1 ) ;
errno = EINVAL ;
return - 1 ;
}
if ( num_fds_in < = 1 ) {
SWRAP_LOG ( SWRAP_LOG_ERROR ,
" cmsg->cmsg_len=%zu,size_fds_in=%zu => "
" num_fds_in=%zu " ,
( size_t ) cmsg - > cmsg_len ,
size_fds_in ,
num_fds_in ) ;
errno = EINVAL ;
return - 1 ;
}
__fds_in . p = CMSG_DATA ( cmsg ) ;
fds_in = __fds_in . fds ;
num_fds_out = num_fds_in - 1 ;
SWRAP_LOG ( SWRAP_LOG_TRACE ,
" num_fds_in=%zu num_fds_out=%zu " ,
num_fds_in , num_fds_out ) ;
for ( i = 0 ; i < num_fds_in ; i + + ) {
/* Check if we have a stale fd and remove it */
swrap_remove_stale ( fds_in [ i ] ) ;
}
scm_rights_pipe_fd = fds_in [ num_fds_out ] ;
size_fds_out = sizeof ( int ) * num_fds_out ;
cmsg_len = CMSG_LEN ( size_fds_out ) ;
cmsg_space = CMSG_SPACE ( size_fds_out ) ;
new_cm_data_space = * cm_data_space + cmsg_space ;
p = realloc ( ( * cm_data ) , new_cm_data_space ) ;
if ( p = = NULL ) {
swrap_close_fd_array ( num_fds_in , fds_in ) ;
return - 1 ;
}
( * cm_data ) = p ;
p = ( * cm_data ) + ( * cm_data_space ) ;
memset ( p , 0 , cmsg_space ) ;
__new_cmsg . p = p ;
new_cmsg = __new_cmsg . cmsg ;
* new_cmsg = * cmsg ;
__fds_out . p = CMSG_DATA ( new_cmsg ) ;
fds_out = __fds_out . fds ;
memcpy ( fds_out , fds_in , size_fds_out ) ;
new_cmsg - > cmsg_len = cmsg_len ;
sret = read ( scm_rights_pipe_fd , & info , sizeof ( info ) ) ;
if ( sret ! = sizeof ( info ) ) {
int saved_errno = errno ;
if ( sret ! = - 1 ) {
saved_errno = EINVAL ;
}
SWRAP_LOG ( SWRAP_LOG_ERROR ,
" read() failed - sret=%zd - %d %s " ,
sret , saved_errno ,
strerror ( saved_errno ) ) ;
swrap_close_fd_array ( num_fds_in , fds_in ) ;
errno = saved_errno ;
return - 1 ;
}
libc_close ( scm_rights_pipe_fd ) ;
payload = & info . payload ;
if ( info . magic ! = swrap_unix_scm_right_magic ) {
SWRAP_LOG ( SWRAP_LOG_ERROR ,
" info.magic=0x%llx != swrap_unix_scm_right_magic=0x%llx " ,
( unsigned long long ) info . magic ,
( unsigned long long ) swrap_unix_scm_right_magic ) ;
swrap_close_fd_array ( num_fds_out , fds_out ) ;
errno = EINVAL ;
return - 1 ;
}
cmp = memcmp ( info . package_name ,
SOCKET_WRAPPER_PACKAGE ,
sizeof ( info . package_name ) ) ;
if ( cmp ! = 0 ) {
SWRAP_LOG ( SWRAP_LOG_ERROR ,
" info.package_name='%.*s' != '%s' " ,
( int ) sizeof ( info . package_name ) ,
info . package_name ,
SOCKET_WRAPPER_PACKAGE ) ;
swrap_close_fd_array ( num_fds_out , fds_out ) ;
errno = EINVAL ;
return - 1 ;
}
cmp = memcmp ( info . package_version ,
SOCKET_WRAPPER_VERSION ,
sizeof ( info . package_version ) ) ;
if ( cmp ! = 0 ) {
SWRAP_LOG ( SWRAP_LOG_ERROR ,
" info.package_version='%.*s' != '%s' " ,
( int ) sizeof ( info . package_version ) ,
info . package_version ,
SOCKET_WRAPPER_VERSION ) ;
swrap_close_fd_array ( num_fds_out , fds_out ) ;
errno = EINVAL ;
return - 1 ;
}
if ( info . full_size ! = sizeof ( info ) ) {
SWRAP_LOG ( SWRAP_LOG_ERROR ,
" info.full_size=%zu != sizeof(info)=%zu " ,
( size_t ) info . full_size ,
sizeof ( info ) ) ;
swrap_close_fd_array ( num_fds_out , fds_out ) ;
errno = EINVAL ;
return - 1 ;
}
if ( info . payload_size ! = sizeof ( info . payload ) ) {
SWRAP_LOG ( SWRAP_LOG_ERROR ,
" info.payload_size=%zu != sizeof(info.payload)=%zu " ,
( size_t ) info . payload_size ,
sizeof ( info . payload ) ) ;
swrap_close_fd_array ( num_fds_out , fds_out ) ;
errno = EINVAL ;
return - 1 ;
}
if ( payload - > num_idxs ! = num_fds_out ) {
SWRAP_LOG ( SWRAP_LOG_ERROR ,
" info.num_idxs=%u != num_fds_out=%zu " ,
payload - > num_idxs , num_fds_out ) ;
swrap_close_fd_array ( num_fds_out , fds_out ) ;
errno = EINVAL ;
return - 1 ;
}
for ( i = 0 ; i < num_fds_out ; i + + ) {
size_t j ;
si_idx_array [ i ] = - 1 ;
if ( payload - > idxs [ i ] = = - 1 ) {
SWRAP_LOG ( SWRAP_LOG_TRACE ,
" fds_out[%zu]=%d not an inet socket " ,
i , fds_out [ i ] ) ;
continue ;
}
if ( payload - > idxs [ i ] < 0 ) {
SWRAP_LOG ( SWRAP_LOG_ERROR ,
" fds_out[%zu]=%d info.idxs[%zu]=%d < 0! " ,
i , fds_out [ i ] , i , payload - > idxs [ i ] ) ;
swrap_close_fd_array ( num_fds_out , fds_out ) ;
errno = EINVAL ;
return - 1 ;
}
if ( payload - > idxs [ i ] > = payload - > num_idxs ) {
SWRAP_LOG ( SWRAP_LOG_ERROR ,
" fds_out[%zu]=%d info.idxs[%zu]=%d >= %u! " ,
i , fds_out [ i ] , i , payload - > idxs [ i ] ,
payload - > num_idxs ) ;
swrap_close_fd_array ( num_fds_out , fds_out ) ;
errno = EINVAL ;
return - 1 ;
}
if ( ( size_t ) fds_out [ i ] > = socket_fds_max ) {
SWRAP_LOG ( SWRAP_LOG_ERROR ,
" The max socket index limit of %zu has been reached, "
" trying to add %d " ,
socket_fds_max ,
fds_out [ i ] ) ;
swrap_close_fd_array ( num_fds_out , fds_out ) ;
errno = EMFILE ;
return - 1 ;
}
SWRAP_LOG ( SWRAP_LOG_TRACE ,
" fds_in[%zu]=%d "
" received as info.idxs[%zu]=%d! " ,
i , fds_out [ i ] ,
i , payload - > idxs [ i ] ) ;
for ( j = 0 ; j < i ; j + + ) {
if ( payload - > idxs [ j ] = = - 1 ) {
continue ;
}
if ( payload - > idxs [ j ] = = payload - > idxs [ i ] ) {
si_idx_array [ i ] = si_idx_array [ j ] ;
}
}
if ( si_idx_array [ i ] = = - 1 ) {
const struct socket_info * si = & payload - > infos [ payload - > idxs [ i ] ] ;
si_idx_array [ i ] = swrap_add_socket_info ( si ) ;
if ( si_idx_array [ i ] = = - 1 ) {
int saved_errno = errno ;
SWRAP_LOG ( SWRAP_LOG_ERROR ,
" The max socket index limit of %zu has been reached, "
" trying to add %d " ,
socket_fds_max ,
fds_out [ i ] ) ;
swrap_undo_si_idx_array ( i , si_idx_array ) ;
swrap_close_fd_array ( num_fds_out , fds_out ) ;
errno = saved_errno ;
return - 1 ;
}
SWRAP_LOG ( SWRAP_LOG_TRACE ,
" Imported %s socket for protocol %s, fd=%d " ,
si - > family = = AF_INET ? " IPv4 " : " IPv6 " ,
si - > type = = SOCK_DGRAM ? " UDP " : " TCP " ,
fds_out [ i ] ) ;
}
}
for ( i = 0 ; i < num_fds_out ; i + + ) {
if ( si_idx_array [ i ] = = - 1 ) {
continue ;
}
set_socket_info_index ( fds_out [ i ] , si_idx_array [ i ] ) ;
}
/* we're done ... */
* cm_data_space = new_cm_data_space ;
return 0 ;
}
static int swrap_recvmsg_unix_sol_socket ( const struct cmsghdr * cmsg ,
uint8_t * * cm_data ,
size_t * cm_data_space )
{
int rc = - 1 ;
switch ( cmsg - > cmsg_type ) {
case SCM_RIGHTS :
rc = swrap_recvmsg_unix_scm_rights ( cmsg ,
cm_data ,
cm_data_space ) ;
break ;
default :
rc = swrap_sendmsg_copy_cmsg ( cmsg ,
cm_data ,
cm_data_space ) ;
break ;
}
return rc ;
}
# endif /* HAVE_STRUCT_MSGHDR_MSG_CONTROL */
static int swrap_sendmsg_before_unix ( const struct msghdr * _msg_in ,
struct msghdr * msg_tmp ,
int * scm_rights_pipe_fd )
{
# ifdef HAVE_STRUCT_MSGHDR_MSG_CONTROL
struct msghdr * msg_in = discard_const_p ( struct msghdr , _msg_in ) ;
struct cmsghdr * cmsg = NULL ;
uint8_t * cm_data = NULL ;
size_t cm_data_space = 0 ;
int rc = - 1 ;
* msg_tmp = * msg_in ;
* scm_rights_pipe_fd = - 1 ;
/* Nothing to do */
if ( msg_in - > msg_controllen = = 0 | | msg_in - > msg_control = = NULL ) {
return 0 ;
}
for ( cmsg = CMSG_FIRSTHDR ( msg_in ) ;
cmsg ! = NULL ;
cmsg = CMSG_NXTHDR ( msg_in , cmsg ) ) {
switch ( cmsg - > cmsg_level ) {
case SOL_SOCKET :
rc = swrap_sendmsg_unix_sol_socket ( cmsg ,
& cm_data ,
& cm_data_space ,
scm_rights_pipe_fd ) ;
break ;
default :
rc = swrap_sendmsg_copy_cmsg ( cmsg ,
& cm_data ,
& cm_data_space ) ;
break ;
}
if ( rc < 0 ) {
int saved_errno = errno ;
SAFE_FREE ( cm_data ) ;
errno = saved_errno ;
return rc ;
}
}
msg_tmp - > msg_controllen = cm_data_space ;
msg_tmp - > msg_control = cm_data ;
return 0 ;
# else /* HAVE_STRUCT_MSGHDR_MSG_CONTROL */
* msg_tmp = * _msg_in ;
return 0 ;
# endif /* ! HAVE_STRUCT_MSGHDR_MSG_CONTROL */
}
static ssize_t swrap_sendmsg_after_unix ( struct msghdr * msg_tmp ,
ssize_t ret ,
int scm_rights_pipe_fd )
{
# ifdef HAVE_STRUCT_MSGHDR_MSG_CONTROL
int saved_errno = errno ;
SAFE_FREE ( msg_tmp - > msg_control ) ;
if ( scm_rights_pipe_fd ! = - 1 ) {
libc_close ( scm_rights_pipe_fd ) ;
}
errno = saved_errno ;
# endif /* HAVE_STRUCT_MSGHDR_MSG_CONTROL */
return ret ;
}
static int swrap_recvmsg_before_unix ( struct msghdr * msg_in ,
struct msghdr * msg_tmp ,
uint8_t * * tmp_control )
{
# ifdef HAVE_STRUCT_MSGHDR_MSG_CONTROL
const size_t cm_extra_space = CMSG_SPACE ( sizeof ( int ) ) ;
uint8_t * cm_data = NULL ;
size_t cm_data_space = 0 ;
* msg_tmp = * msg_in ;
* tmp_control = NULL ;
SWRAP_LOG ( SWRAP_LOG_TRACE ,
" msg_in->msg_controllen=%zu " ,
( size_t ) msg_in - > msg_controllen ) ;
/* Nothing to do */
if ( msg_in - > msg_controllen = = 0 | | msg_in - > msg_control = = NULL ) {
return 0 ;
}
/*
* We need to give the kernel a bit more space in order
* recv the pipe fd , added by swrap_sendmsg_before_unix ( ) ) .
* swrap_recvmsg_after_unix ( ) will hide it again .
*/
cm_data_space = msg_in - > msg_controllen ;
if ( cm_data_space < ( INT32_MAX - cm_extra_space ) ) {
cm_data_space + = cm_extra_space ;
}
cm_data = calloc ( 1 , cm_data_space ) ;
if ( cm_data = = NULL ) {
return - 1 ;
}
msg_tmp - > msg_controllen = cm_data_space ;
msg_tmp - > msg_control = cm_data ;
* tmp_control = cm_data ;
SWRAP_LOG ( SWRAP_LOG_TRACE ,
" msg_tmp->msg_controllen=%zu " ,
( size_t ) msg_tmp - > msg_controllen ) ;
return 0 ;
# else /* HAVE_STRUCT_MSGHDR_MSG_CONTROL */
* msg_tmp = * msg_in ;
* tmp_control = NULL ;
return 0 ;
# endif /* ! HAVE_STRUCT_MSGHDR_MSG_CONTROL */
}
static ssize_t swrap_recvmsg_after_unix ( struct msghdr * msg_tmp ,
uint8_t * * tmp_control ,
struct msghdr * msg_out ,
ssize_t ret )
{
# ifdef HAVE_STRUCT_MSGHDR_MSG_CONTROL
struct cmsghdr * cmsg = NULL ;
uint8_t * cm_data = NULL ;
size_t cm_data_space = 0 ;
int rc = - 1 ;
if ( ret < 0 ) {
int saved_errno = errno ;
SWRAP_LOG ( SWRAP_LOG_TRACE , " ret=%zd - %d - %s " , ret ,
saved_errno , strerror ( saved_errno ) ) ;
SAFE_FREE ( * tmp_control ) ;
/* msg_out should not be touched on error */
errno = saved_errno ;
return ret ;
}
SWRAP_LOG ( SWRAP_LOG_TRACE ,
" msg_tmp->msg_controllen=%zu " ,
( size_t ) msg_tmp - > msg_controllen ) ;
/* Nothing to do */
if ( msg_tmp - > msg_controllen = = 0 | | msg_tmp - > msg_control = = NULL ) {
int saved_errno = errno ;
* msg_out = * msg_tmp ;
SAFE_FREE ( * tmp_control ) ;
errno = saved_errno ;
return ret ;
}
for ( cmsg = CMSG_FIRSTHDR ( msg_tmp ) ;
cmsg ! = NULL ;
cmsg = CMSG_NXTHDR ( msg_tmp , cmsg ) ) {
switch ( cmsg - > cmsg_level ) {
case SOL_SOCKET :
rc = swrap_recvmsg_unix_sol_socket ( cmsg ,
& cm_data ,
& cm_data_space ) ;
break ;
default :
rc = swrap_sendmsg_copy_cmsg ( cmsg ,
& cm_data ,
& cm_data_space ) ;
break ;
}
if ( rc < 0 ) {
int saved_errno = errno ;
SAFE_FREE ( cm_data ) ;
SAFE_FREE ( * tmp_control ) ;
errno = saved_errno ;
return rc ;
}
}
/*
* msg_tmp - > msg_control ( * tmp_control ) was created by
* swrap_recvmsg_before_unix ( ) and msg_out - > msg_control
* is still the buffer of the caller .
*/
msg_tmp - > msg_control = msg_out - > msg_control ;
msg_tmp - > msg_controllen = msg_out - > msg_controllen ;
* msg_out = * msg_tmp ;
cm_data_space = MIN ( cm_data_space , msg_out - > msg_controllen ) ;
memcpy ( msg_out - > msg_control , cm_data , cm_data_space ) ;
msg_out - > msg_controllen = cm_data_space ;
SAFE_FREE ( cm_data ) ;
SAFE_FREE ( * tmp_control ) ;
SWRAP_LOG ( SWRAP_LOG_TRACE ,
" msg_out->msg_controllen=%zu " ,
( size_t ) msg_out - > msg_controllen ) ;
return ret ;
# else /* HAVE_STRUCT_MSGHDR_MSG_CONTROL */
int saved_errno = errno ;
* msg_out = * msg_tmp ;
SAFE_FREE ( * tmp_control ) ;
errno = saved_errno ;
return ret ;
# endif /* ! HAVE_STRUCT_MSGHDR_MSG_CONTROL */
}
static ssize_t swrap_sendmsg_before ( int fd ,
struct socket_info * si ,
struct msghdr * msg ,
struct iovec * tmp_iov ,
struct sockaddr_un * tmp_un ,
const struct sockaddr_un * * to_un ,
const struct sockaddr * * to ,
int * bcast )
{
size_t i , len = 0 ;
ssize_t ret = - 1 ;
if ( to_un ) {
* to_un = NULL ;
}
if ( to ) {
* to = NULL ;
}
if ( bcast ) {
* bcast = 0 ;
}
SWRAP_LOCK_SI ( si ) ;
switch ( si - > type ) {
case SOCK_STREAM : {
unsigned long mtu ;
if ( ! si - > connected ) {
errno = ENOTCONN ;
goto out ;
}
if ( msg - > msg_iovlen = = 0 ) {
break ;
}
mtu = socket_wrapper_mtu ( ) ;
for ( i = 0 ; i < ( size_t ) msg - > msg_iovlen ; i + + ) {
size_t nlen ;
nlen = len + msg - > msg_iov [ i ] . iov_len ;
if ( nlen < len ) {
/* overflow */
errno = EMSGSIZE ;
goto out ;
2019-03-21 12:02:54 +03:00
}
2015-08-25 18:20:20 +03:00
if ( nlen > mtu ) {
2010-10-30 18:08:49 +04:00
break ;
}
}
msg - > msg_iovlen = i ;
if ( msg - > msg_iovlen = = 0 ) {
* tmp_iov = msg - > msg_iov [ 0 ] ;
2016-03-15 17:47:08 +03:00
tmp_iov - > iov_len = MIN ( ( size_t ) tmp_iov - > iov_len ,
( size_t ) mtu ) ;
2010-10-30 18:08:49 +04:00
msg - > msg_iov = tmp_iov ;
msg - > msg_iovlen = 1 ;
}
break ;
2015-08-25 18:20:20 +03:00
}
2010-10-30 18:08:49 +04:00
case SOCK_DGRAM :
if ( si - > connected ) {
2016-05-20 11:20:28 +03:00
if ( msg - > msg_name ! = NULL ) {
/*
* We are dealing with unix sockets and if we
* are connected , we should only talk to the
* connected unix path . Using the fd to send
* to another server would be hard to achieve .
*/
msg - > msg_name = NULL ;
msg - > msg_namelen = 0 ;
2010-10-30 18:08:49 +04:00
}
} else {
const struct sockaddr * msg_name ;
msg_name = ( const struct sockaddr * ) msg - > msg_name ;
if ( msg_name = = NULL ) {
errno = ENOTCONN ;
2018-05-02 16:57:38 +03:00
goto out ;
2010-10-30 18:08:49 +04:00
}
ret = sockaddr_convert_to_un ( si , msg_name , msg - > msg_namelen ,
tmp_un , 0 , bcast ) ;
2017-11-07 14:29:51 +03:00
if ( ret = = - 1 ) {
2018-05-02 16:57:38 +03:00
goto out ;
2017-11-07 14:29:51 +03:00
}
2010-10-30 18:08:49 +04:00
if ( to_un ) {
* to_un = tmp_un ;
}
if ( to ) {
* to = msg_name ;
}
msg - > msg_name = tmp_un ;
msg - > msg_namelen = sizeof ( * tmp_un ) ;
}
if ( si - > bound = = 0 ) {
2011-09-29 01:04:51 +04:00
ret = swrap_auto_bind ( fd , si , si - > family ) ;
2014-04-07 18:12:21 +04:00
if ( ret = = - 1 ) {
2018-05-02 16:57:38 +03:00
SWRAP_UNLOCK_SI ( si ) ;
2014-04-07 18:12:21 +04:00
if ( errno = = ENOTSOCK ) {
swrap_remove_stale ( fd ) ;
2018-05-02 16:57:38 +03:00
ret = - ENOTSOCK ;
2014-04-07 18:12:21 +04:00
} else {
SWRAP_LOG ( SWRAP_LOG_ERROR , " swrap_sendmsg_before failed " ) ;
}
2018-05-02 16:57:38 +03:00
return ret ;
2014-04-07 18:12:21 +04:00
}
2010-10-30 18:08:49 +04:00
}
if ( ! si - > defer_connect ) {
break ;
}
2014-10-02 09:17:10 +04:00
ret = sockaddr_convert_to_un ( si ,
& si - > peername . sa . s ,
si - > peername . sa_socklen ,
tmp_un ,
0 ,
NULL ) ;
2017-11-07 14:29:51 +03:00
if ( ret = = - 1 ) {
2018-05-02 16:57:38 +03:00
goto out ;
2017-11-07 14:29:51 +03:00
}
2010-10-30 18:08:49 +04:00
2014-04-07 18:12:21 +04:00
ret = libc_connect ( fd ,
( struct sockaddr * ) ( void * ) tmp_un ,
2010-10-30 18:08:49 +04:00
sizeof ( * tmp_un ) ) ;
/* to give better errors */
if ( ret = = - 1 & & errno = = ENOENT ) {
errno = EHOSTUNREACH ;
}
if ( ret = = - 1 ) {
2018-05-02 16:57:38 +03:00
goto out ;
2010-10-30 18:08:49 +04:00
}
si - > defer_connect = 0 ;
break ;
default :
errno = EHOSTUNREACH ;
2018-05-02 16:57:38 +03:00
goto out ;
2010-10-30 18:08:49 +04:00
}
2018-05-02 16:57:38 +03:00
ret = 0 ;
out :
SWRAP_UNLOCK_SI ( si ) ;
return ret ;
2010-10-30 18:08:49 +04:00
}
2014-04-07 18:12:21 +04:00
static void swrap_sendmsg_after ( int fd ,
struct socket_info * si ,
2010-10-30 18:08:49 +04:00
struct msghdr * msg ,
const struct sockaddr * to ,
ssize_t ret )
{
int saved_errno = errno ;
size_t i , len = 0 ;
uint8_t * buf ;
off_t ofs = 0 ;
size_t avail = 0 ;
size_t remain ;
/* to give better errors */
2014-04-07 18:12:21 +04:00
if ( ret = = - 1 ) {
if ( saved_errno = = ENOENT ) {
saved_errno = EHOSTUNREACH ;
} else if ( saved_errno = = ENOTSOCK ) {
/* If the fd is not a socket, remove it */
swrap_remove_stale ( fd ) ;
}
2010-10-30 18:08:49 +04:00
}
2014-04-07 18:12:21 +04:00
for ( i = 0 ; i < ( size_t ) msg - > msg_iovlen ; i + + ) {
2010-10-30 18:08:49 +04:00
avail + = msg - > msg_iov [ i ] . iov_len ;
}
if ( ret = = - 1 ) {
remain = MIN ( 80 , avail ) ;
} else {
remain = ret ;
}
/* we capture it as one single packet */
buf = ( uint8_t * ) malloc ( remain ) ;
if ( ! buf ) {
/* we just not capture the packet */
errno = saved_errno ;
return ;
}
2014-04-07 18:12:21 +04:00
for ( i = 0 ; i < ( size_t ) msg - > msg_iovlen ; i + + ) {
size_t this_time = MIN ( remain , ( size_t ) msg - > msg_iov [ i ] . iov_len ) ;
2010-10-30 18:08:49 +04:00
memcpy ( buf + ofs ,
msg - > msg_iov [ i ] . iov_base ,
this_time ) ;
ofs + = this_time ;
remain - = this_time ;
}
len = ofs ;
2018-05-02 16:57:38 +03:00
SWRAP_LOCK_SI ( si ) ;
2010-10-30 18:08:49 +04:00
switch ( si - > type ) {
case SOCK_STREAM :
2014-04-07 18:12:21 +04:00
if ( ret = = - 1 ) {
2014-10-02 09:15:38 +04:00
swrap_pcap_dump_packet ( si , NULL , SWRAP_SEND , buf , len ) ;
swrap_pcap_dump_packet ( si , NULL , SWRAP_SEND_RST , NULL , 0 ) ;
2014-04-07 18:12:21 +04:00
} else {
2014-10-02 09:15:38 +04:00
swrap_pcap_dump_packet ( si , NULL , SWRAP_SEND , buf , len ) ;
2014-04-07 18:12:21 +04:00
}
break ;
case SOCK_DGRAM :
if ( si - > connected ) {
2014-10-02 09:17:10 +04:00
to = & si - > peername . sa . s ;
2014-04-07 18:12:21 +04:00
}
if ( ret = = - 1 ) {
2014-10-02 09:15:38 +04:00
swrap_pcap_dump_packet ( si , to , SWRAP_SENDTO , buf , len ) ;
swrap_pcap_dump_packet ( si , to , SWRAP_SENDTO_UNREACH , buf , len ) ;
2014-04-07 18:12:21 +04:00
} else {
2014-10-02 09:15:38 +04:00
swrap_pcap_dump_packet ( si , to , SWRAP_SENDTO , buf , len ) ;
2014-04-07 18:12:21 +04:00
}
break ;
}
2018-05-02 16:57:38 +03:00
SWRAP_UNLOCK_SI ( si ) ;
2014-04-07 18:12:21 +04:00
free ( buf ) ;
errno = saved_errno ;
}
static int swrap_recvmsg_before ( int fd ,
struct socket_info * si ,
struct msghdr * msg ,
struct iovec * tmp_iov )
{
size_t i , len = 0 ;
2018-05-02 16:57:38 +03:00
int ret = - 1 ;
SWRAP_LOCK_SI ( si ) ;
2014-04-07 18:12:21 +04:00
( void ) fd ; /* unused */
switch ( si - > type ) {
2015-08-25 18:20:20 +03:00
case SOCK_STREAM : {
unsigned int mtu ;
2014-04-07 18:12:21 +04:00
if ( ! si - > connected ) {
errno = ENOTCONN ;
2018-05-02 16:57:38 +03:00
goto out ;
2014-04-07 18:12:21 +04:00
}
if ( msg - > msg_iovlen = = 0 ) {
break ;
}
2015-08-25 18:20:20 +03:00
mtu = socket_wrapper_mtu ( ) ;
2014-04-07 18:12:21 +04:00
for ( i = 0 ; i < ( size_t ) msg - > msg_iovlen ; i + + ) {
size_t nlen ;
nlen = len + msg - > msg_iov [ i ] . iov_len ;
2015-08-25 18:20:20 +03:00
if ( nlen > mtu ) {
2014-04-07 18:12:21 +04:00
break ;
}
}
msg - > msg_iovlen = i ;
if ( msg - > msg_iovlen = = 0 ) {
* tmp_iov = msg - > msg_iov [ 0 ] ;
2016-03-15 17:47:08 +03:00
tmp_iov - > iov_len = MIN ( ( size_t ) tmp_iov - > iov_len ,
( size_t ) mtu ) ;
2014-04-07 18:12:21 +04:00
msg - > msg_iov = tmp_iov ;
msg - > msg_iovlen = 1 ;
}
break ;
2015-08-25 18:20:20 +03:00
}
2014-04-07 18:12:21 +04:00
case SOCK_DGRAM :
if ( msg - > msg_name = = NULL ) {
errno = EINVAL ;
2018-05-02 16:57:38 +03:00
goto out ;
2014-04-07 18:12:21 +04:00
}
if ( msg - > msg_iovlen = = 0 ) {
break ;
}
if ( si - > bound = = 0 ) {
ret = swrap_auto_bind ( fd , si , si - > family ) ;
if ( ret = = - 1 ) {
2018-05-02 16:57:38 +03:00
SWRAP_UNLOCK_SI ( si ) ;
2014-04-07 18:12:21 +04:00
/*
* When attempting to read or write to a
* descriptor , if an underlying autobind fails
* because it ' s not a socket , stop intercepting
* uses of that descriptor .
*/
if ( errno = = ENOTSOCK ) {
swrap_remove_stale ( fd ) ;
2018-05-02 16:57:38 +03:00
ret = - ENOTSOCK ;
2014-04-07 18:12:21 +04:00
} else {
SWRAP_LOG ( SWRAP_LOG_ERROR ,
" swrap_recvmsg_before failed " ) ;
}
2018-05-02 16:57:38 +03:00
return ret ;
2014-04-07 18:12:21 +04:00
}
}
break ;
default :
errno = EHOSTUNREACH ;
2018-05-02 16:57:38 +03:00
goto out ;
2014-04-07 18:12:21 +04:00
}
2018-05-02 16:57:38 +03:00
ret = 0 ;
out :
SWRAP_UNLOCK_SI ( si ) ;
return ret ;
2014-04-07 18:12:21 +04:00
}
static int swrap_recvmsg_after ( int fd ,
struct socket_info * si ,
struct msghdr * msg ,
const struct sockaddr_un * un_addr ,
socklen_t un_addrlen ,
ssize_t ret )
{
int saved_errno = errno ;
size_t i ;
2014-05-08 16:04:11 +04:00
uint8_t * buf = NULL ;
2014-04-07 18:12:21 +04:00
off_t ofs = 0 ;
size_t avail = 0 ;
size_t remain ;
2014-06-03 16:57:08 +04:00
int rc ;
2014-04-07 18:12:21 +04:00
/* to give better errors */
if ( ret = = - 1 ) {
if ( saved_errno = = ENOENT ) {
saved_errno = EHOSTUNREACH ;
} else if ( saved_errno = = ENOTSOCK ) {
/* If the fd is not a socket, remove it */
swrap_remove_stale ( fd ) ;
}
}
for ( i = 0 ; i < ( size_t ) msg - > msg_iovlen ; i + + ) {
avail + = msg - > msg_iov [ i ] . iov_len ;
}
2018-05-02 16:57:38 +03:00
SWRAP_LOCK_SI ( si ) ;
2015-08-25 18:19:02 +03:00
/* Convert the socket address before we leave */
if ( si - > type = = SOCK_DGRAM & & un_addr ! = NULL ) {
rc = sockaddr_convert_from_un ( si ,
un_addr ,
un_addrlen ,
si - > family ,
msg - > msg_name ,
& msg - > msg_namelen ) ;
if ( rc = = - 1 ) {
goto done ;
}
}
2014-04-07 18:12:21 +04:00
if ( avail = = 0 ) {
2014-06-03 16:57:08 +04:00
rc = 0 ;
goto done ;
2014-04-07 18:12:21 +04:00
}
if ( ret = = - 1 ) {
remain = MIN ( 80 , avail ) ;
} else {
remain = ret ;
}
/* we capture it as one single packet */
buf = ( uint8_t * ) malloc ( remain ) ;
2014-05-08 16:04:11 +04:00
if ( buf = = NULL ) {
2014-04-07 18:12:21 +04:00
/* we just not capture the packet */
2018-05-02 16:57:38 +03:00
SWRAP_UNLOCK_SI ( si ) ;
2014-04-07 18:12:21 +04:00
errno = saved_errno ;
return - 1 ;
}
for ( i = 0 ; i < ( size_t ) msg - > msg_iovlen ; i + + ) {
size_t this_time = MIN ( remain , ( size_t ) msg - > msg_iov [ i ] . iov_len ) ;
memcpy ( buf + ofs ,
msg - > msg_iov [ i ] . iov_base ,
this_time ) ;
ofs + = this_time ;
remain - = this_time ;
}
switch ( si - > type ) {
case SOCK_STREAM :
if ( ret = = - 1 & & saved_errno ! = EAGAIN & & saved_errno ! = ENOBUFS ) {
2014-10-02 09:15:38 +04:00
swrap_pcap_dump_packet ( si , NULL , SWRAP_RECV_RST , NULL , 0 ) ;
2014-04-07 18:12:21 +04:00
} else if ( ret = = 0 ) { /* END OF FILE */
2014-10-02 09:15:38 +04:00
swrap_pcap_dump_packet ( si , NULL , SWRAP_RECV_RST , NULL , 0 ) ;
2014-04-07 18:12:21 +04:00
} else if ( ret > 0 ) {
2014-10-02 09:15:38 +04:00
swrap_pcap_dump_packet ( si , NULL , SWRAP_RECV , buf , ret ) ;
2010-10-30 18:08:49 +04:00
}
break ;
case SOCK_DGRAM :
if ( ret = = - 1 ) {
2014-04-07 18:12:21 +04:00
break ;
}
if ( un_addr ! = NULL ) {
2014-10-02 09:15:38 +04:00
swrap_pcap_dump_packet ( si ,
2014-04-07 18:12:21 +04:00
msg - > msg_name ,
SWRAP_RECVFROM ,
buf ,
ret ) ;
2010-10-30 18:08:49 +04:00
} else {
2014-10-02 09:15:38 +04:00
swrap_pcap_dump_packet ( si ,
2014-04-07 18:12:21 +04:00
msg - > msg_name ,
SWRAP_RECV ,
buf ,
ret ) ;
2010-10-30 18:08:49 +04:00
}
2014-04-07 18:12:21 +04:00
2010-10-30 18:08:49 +04:00
break ;
}
2014-06-03 16:57:08 +04:00
rc = 0 ;
2014-05-08 16:04:11 +04:00
done :
2010-10-30 18:08:49 +04:00
free ( buf ) ;
errno = saved_errno ;
2014-06-03 16:57:08 +04:00
# ifdef HAVE_STRUCT_MSGHDR_MSG_CONTROL
if ( rc = = 0 & &
msg - > msg_controllen > 0 & &
msg - > msg_control ! = NULL ) {
rc = swrap_msghdr_add_socket_info ( si , msg ) ;
if ( rc < 0 ) {
2018-05-02 16:57:38 +03:00
SWRAP_UNLOCK_SI ( si ) ;
2014-06-03 16:57:08 +04:00
return - 1 ;
}
}
# endif
2018-05-02 16:57:38 +03:00
SWRAP_UNLOCK_SI ( si ) ;
2014-06-03 16:57:08 +04:00
return rc ;
2010-10-30 18:08:49 +04:00
}
2014-04-07 18:12:21 +04:00
/****************************************************************************
* RECVFROM
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
static ssize_t swrap_recvfrom ( int s , void * buf , size_t len , int flags ,
struct sockaddr * from , socklen_t * fromlen )
2005-03-28 05:00:39 +04:00
{
2014-10-02 09:09:33 +04:00
struct swrap_address from_addr = {
. sa_socklen = sizeof ( struct sockaddr_un ) ,
} ;
2014-04-07 18:12:21 +04:00
ssize_t ret ;
2005-03-28 05:00:39 +04:00
struct socket_info * si = find_socket_info ( s ) ;
2014-10-02 09:09:33 +04:00
struct swrap_address saddr = {
. sa_socklen = sizeof ( struct sockaddr_storage ) ,
} ;
2014-04-07 18:12:21 +04:00
struct msghdr msg ;
struct iovec tmp ;
int tret ;
2005-03-28 05:00:39 +04:00
if ( ! si ) {
2014-04-07 18:12:21 +04:00
return libc_recvfrom ( s ,
buf ,
len ,
flags ,
from ,
fromlen ) ;
2005-03-28 05:00:39 +04:00
}
2014-04-07 18:12:21 +04:00
tmp . iov_base = buf ;
tmp . iov_len = len ;
ZERO_STRUCT ( msg ) ;
if ( from ! = NULL & & fromlen ! = NULL ) {
msg . msg_name = from ; /* optional address */
msg . msg_namelen = * fromlen ; /* size of address */
} else {
2014-10-02 09:09:33 +04:00
msg . msg_name = & saddr . sa . s ; /* optional address */
msg . msg_namelen = saddr . sa_socklen ; /* size of address */
2009-03-08 19:19:50 +03:00
}
2014-04-07 18:12:21 +04:00
msg . msg_iov = & tmp ; /* scatter/gather array */
msg . msg_iovlen = 1 ; /* # elements in msg_iov */
# ifdef HAVE_STRUCT_MSGHDR_MSG_CONTROL
msg . msg_control = NULL ; /* ancillary data, see below */
msg . msg_controllen = 0 ; /* ancillary data buffer len */
msg . msg_flags = 0 ; /* flags on received message */
# endif
2009-03-08 19:19:50 +03:00
2014-04-07 18:12:21 +04:00
tret = swrap_recvmsg_before ( s , si , & msg , & tmp ) ;
if ( tret < 0 ) {
return - 1 ;
2009-06-19 07:25:28 +04:00
}
2008-06-10 10:33:24 +04:00
2014-04-07 18:12:21 +04:00
buf = msg . msg_iov [ 0 ] . iov_base ;
len = msg . msg_iov [ 0 ] . iov_len ;
ret = libc_recvfrom ( s ,
buf ,
len ,
flags ,
2014-10-02 09:09:33 +04:00
& from_addr . sa . s ,
& from_addr . sa_socklen ) ;
2014-04-07 18:12:21 +04:00
if ( ret = = - 1 ) {
2005-03-28 05:00:39 +04:00
return ret ;
2014-04-07 18:12:21 +04:00
}
2005-03-28 05:00:39 +04:00
2014-04-07 18:12:21 +04:00
tret = swrap_recvmsg_after ( s ,
si ,
& msg ,
2014-10-02 09:09:33 +04:00
& from_addr . sa . un ,
from_addr . sa_socklen ,
2014-04-07 18:12:21 +04:00
ret ) ;
if ( tret ! = 0 ) {
return tret ;
2005-03-31 16:40:12 +04:00
}
2006-09-12 10:19:11 +04:00
2014-04-07 18:12:21 +04:00
if ( from ! = NULL & & fromlen ! = NULL ) {
* fromlen = msg . msg_namelen ;
}
2006-09-12 10:19:11 +04:00
2005-03-28 05:00:39 +04:00
return ret ;
}
2014-04-07 18:12:21 +04:00
# ifdef HAVE_ACCEPT_PSOCKLEN_T
ssize_t recvfrom ( int s , void * buf , size_t len , int flags ,
struct sockaddr * from , Psocklen_t fromlen )
# else
ssize_t recvfrom ( int s , void * buf , size_t len , int flags ,
struct sockaddr * from , socklen_t * fromlen )
# endif
{
return swrap_recvfrom ( s , buf , len , flags , from , ( socklen_t * ) fromlen ) ;
}
/****************************************************************************
* SENDTO
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2005-06-10 16:21:46 +04:00
2014-04-07 18:12:21 +04:00
static ssize_t swrap_sendto ( int s , const void * buf , size_t len , int flags ,
const struct sockaddr * to , socklen_t tolen )
2005-03-28 05:00:39 +04:00
{
2010-10-30 18:23:49 +04:00
struct msghdr msg ;
struct iovec tmp ;
2014-10-02 09:09:33 +04:00
struct swrap_address un_addr = {
. sa_socklen = sizeof ( struct sockaddr_un ) ,
} ;
2010-10-30 18:23:49 +04:00
const struct sockaddr_un * to_un = NULL ;
ssize_t ret ;
2014-04-07 18:12:21 +04:00
int rc ;
2005-03-28 05:00:39 +04:00
struct socket_info * si = find_socket_info ( s ) ;
2005-11-07 18:36:51 +03:00
int bcast = 0 ;
2005-03-28 05:00:39 +04:00
if ( ! si ) {
2014-04-07 18:12:21 +04:00
return libc_sendto ( s , buf , len , flags , to , tolen ) ;
2005-03-28 05:00:39 +04:00
}
2010-10-30 18:23:49 +04:00
tmp . iov_base = discard_const_p ( char , buf ) ;
tmp . iov_len = len ;
2009-03-08 19:19:50 +03:00
2011-03-04 23:14:27 +03:00
ZERO_STRUCT ( msg ) ;
2010-10-30 18:23:49 +04:00
msg . msg_name = discard_const_p ( struct sockaddr , to ) ; /* optional address */
msg . msg_namelen = tolen ; /* size of address */
msg . msg_iov = & tmp ; /* scatter/gather array */
msg . msg_iovlen = 1 ; /* # elements in msg_iov */
2019-03-21 12:02:54 +03:00
# ifdef HAVE_STRUCT_MSGHDR_MSG_CONTROL
2010-10-30 18:23:49 +04:00
msg . msg_control = NULL ; /* ancillary data, see below */
msg . msg_controllen = 0 ; /* ancillary data buffer len */
msg . msg_flags = 0 ; /* flags on received message */
2011-03-04 23:14:27 +03:00
# endif
2009-03-08 19:19:50 +03:00
2014-10-02 09:09:33 +04:00
rc = swrap_sendmsg_before ( s ,
si ,
& msg ,
& tmp ,
& un_addr . sa . un ,
& to_un ,
& to ,
& bcast ) ;
2014-04-07 18:12:21 +04:00
if ( rc < 0 ) {
return - 1 ;
}
2011-02-12 14:18:16 +03:00
2010-10-30 18:23:49 +04:00
buf = msg . msg_iov [ 0 ] . iov_base ;
len = msg . msg_iov [ 0 ] . iov_len ;
2011-02-12 14:18:16 +03:00
2010-10-30 18:23:49 +04:00
if ( bcast ) {
struct stat st ;
unsigned int iface ;
2014-10-02 09:23:25 +04:00
unsigned int prt = ntohs ( ( ( const struct sockaddr_in * ) ( const void * ) to ) - > sin_port ) ;
2010-10-30 18:23:49 +04:00
char type ;
2019-03-21 12:02:54 +03:00
char * swrap_dir = NULL ;
2011-02-12 14:18:16 +03:00
2010-10-30 18:23:49 +04:00
type = SOCKET_TYPE_CHAR_UDP ;
2011-02-12 14:18:16 +03:00
2019-03-21 12:02:54 +03:00
swrap_dir = socket_wrapper_dir ( ) ;
if ( swrap_dir = = NULL ) {
return - 1 ;
}
2010-10-30 18:23:49 +04:00
for ( iface = 0 ; iface < = MAX_WRAPPED_INTERFACES ; iface + + ) {
2020-06-08 15:18:00 +03:00
swrap_un_path ( & un_addr . sa . un ,
swrap_dir ,
type ,
iface ,
prt ) ;
2014-10-02 09:09:33 +04:00
if ( stat ( un_addr . sa . un . sun_path , & st ) ! = 0 ) continue ;
2011-02-12 14:18:16 +03:00
2010-10-30 18:23:49 +04:00
/* ignore the any errors in broadcast sends */
2014-04-07 18:12:21 +04:00
libc_sendto ( s ,
buf ,
len ,
flags ,
2014-10-02 09:09:33 +04:00
& un_addr . sa . s ,
un_addr . sa_socklen ) ;
2005-11-07 18:36:51 +03:00
}
2009-03-23 11:16:18 +03:00
2019-03-21 12:02:54 +03:00
SAFE_FREE ( swrap_dir ) ;
2018-05-02 16:57:38 +03:00
SWRAP_LOCK_SI ( si ) ;
2014-10-02 09:15:38 +04:00
swrap_pcap_dump_packet ( si , to , SWRAP_SENDTO , buf , len ) ;
2009-03-23 11:16:18 +03:00
2018-05-02 16:57:38 +03:00
SWRAP_UNLOCK_SI ( si ) ;
2010-10-30 18:23:49 +04:00
return len ;
2005-11-07 18:36:51 +03:00
}
2011-02-12 14:18:16 +03:00
2018-05-02 16:57:38 +03:00
SWRAP_LOCK_SI ( si ) ;
2016-05-20 11:20:28 +03:00
/*
* If it is a dgram socket and we are connected , don ' t include the
* ' to ' address .
*/
if ( si - > type = = SOCK_DGRAM & & si - > connected ) {
ret = libc_sendto ( s ,
buf ,
len ,
flags ,
NULL ,
0 ) ;
} else {
ret = libc_sendto ( s ,
buf ,
len ,
flags ,
( struct sockaddr * ) msg . msg_name ,
msg . msg_namelen ) ;
}
2005-11-07 18:36:51 +03:00
2018-05-02 16:57:38 +03:00
SWRAP_UNLOCK_SI ( si ) ;
2014-04-07 18:12:21 +04:00
swrap_sendmsg_after ( s , si , & msg , to , ret ) ;
2006-09-12 10:19:11 +04:00
2006-09-27 14:13:45 +04:00
return ret ;
}
2014-04-07 18:12:21 +04:00
ssize_t sendto ( int s , const void * buf , size_t len , int flags ,
const struct sockaddr * to , socklen_t tolen )
2006-09-12 10:19:11 +04:00
{
2014-04-07 18:12:21 +04:00
return swrap_sendto ( s , buf , len , flags , to , tolen ) ;
}
2006-09-12 10:19:11 +04:00
2014-04-07 18:12:21 +04:00
/****************************************************************************
* READV
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
static ssize_t swrap_recv ( int s , void * buf , size_t len , int flags )
{
struct socket_info * si ;
struct msghdr msg ;
2014-10-02 09:09:33 +04:00
struct swrap_address saddr = {
. sa_socklen = sizeof ( struct sockaddr_storage ) ,
} ;
2014-04-07 18:12:21 +04:00
struct iovec tmp ;
ssize_t ret ;
int tret ;
si = find_socket_info ( s ) ;
if ( si = = NULL ) {
return libc_recv ( s , buf , len , flags ) ;
2006-09-12 10:19:11 +04:00
}
2014-04-07 18:12:21 +04:00
tmp . iov_base = buf ;
tmp . iov_len = len ;
ZERO_STRUCT ( msg ) ;
2014-10-02 09:09:33 +04:00
msg . msg_name = & saddr . sa . s ; /* optional address */
msg . msg_namelen = saddr . sa_socklen ; /* size of address */
2014-04-07 18:12:21 +04:00
msg . msg_iov = & tmp ; /* scatter/gather array */
msg . msg_iovlen = 1 ; /* # elements in msg_iov */
# ifdef HAVE_STRUCT_MSGHDR_MSG_CONTROL
msg . msg_control = NULL ; /* ancillary data, see below */
msg . msg_controllen = 0 ; /* ancillary data buffer len */
msg . msg_flags = 0 ; /* flags on received message */
# endif
tret = swrap_recvmsg_before ( s , si , & msg , & tmp ) ;
if ( tret < 0 ) {
return - 1 ;
2009-06-19 07:25:28 +04:00
}
2008-06-10 10:33:24 +04:00
2014-04-07 18:12:21 +04:00
buf = msg . msg_iov [ 0 ] . iov_base ;
len = msg . msg_iov [ 0 ] . iov_len ;
ret = libc_recv ( s , buf , len , flags ) ;
tret = swrap_recvmsg_after ( s , si , & msg , NULL , 0 , ret ) ;
if ( tret ! = 0 ) {
return tret ;
2006-09-29 13:31:20 +04:00
}
2006-09-12 10:19:11 +04:00
return ret ;
}
2014-04-07 18:12:21 +04:00
ssize_t recv ( int s , void * buf , size_t len , int flags )
2009-09-08 07:31:01 +04:00
{
2014-04-07 18:12:21 +04:00
return swrap_recv ( s , buf , len , flags ) ;
}
2009-09-08 07:31:01 +04:00
2014-04-07 18:12:21 +04:00
/****************************************************************************
* READ
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
static ssize_t swrap_read ( int s , void * buf , size_t len )
{
struct socket_info * si ;
struct msghdr msg ;
struct iovec tmp ;
2014-10-02 09:09:33 +04:00
struct swrap_address saddr = {
. sa_socklen = sizeof ( struct sockaddr_storage ) ,
} ;
2014-04-07 18:12:21 +04:00
ssize_t ret ;
int tret ;
si = find_socket_info ( s ) ;
if ( si = = NULL ) {
return libc_read ( s , buf , len ) ;
2009-09-08 07:31:01 +04:00
}
2014-04-07 18:12:21 +04:00
tmp . iov_base = buf ;
tmp . iov_len = len ;
ZERO_STRUCT ( msg ) ;
2014-10-02 09:09:33 +04:00
msg . msg_name = & saddr . sa . ss ; /* optional address */
msg . msg_namelen = saddr . sa_socklen ; /* size of address */
2014-04-07 18:12:21 +04:00
msg . msg_iov = & tmp ; /* scatter/gather array */
msg . msg_iovlen = 1 ; /* # elements in msg_iov */
# ifdef HAVE_STRUCT_MSGHDR_MSG_CONTROL
msg . msg_control = NULL ; /* ancillary data, see below */
msg . msg_controllen = 0 ; /* ancillary data buffer len */
msg . msg_flags = 0 ; /* flags on received message */
# endif
tret = swrap_recvmsg_before ( s , si , & msg , & tmp ) ;
if ( tret < 0 ) {
if ( tret = = - ENOTSOCK ) {
return libc_read ( s , buf , len ) ;
}
return - 1 ;
2009-09-08 07:31:01 +04:00
}
2014-04-07 18:12:21 +04:00
buf = msg . msg_iov [ 0 ] . iov_base ;
len = msg . msg_iov [ 0 ] . iov_len ;
ret = libc_read ( s , buf , len ) ;
tret = swrap_recvmsg_after ( s , si , & msg , NULL , 0 , ret ) ;
if ( tret ! = 0 ) {
return tret ;
2009-09-08 07:31:01 +04:00
}
return ret ;
}
2014-04-07 18:12:21 +04:00
ssize_t read ( int s , void * buf , size_t len )
{
return swrap_read ( s , buf , len ) ;
}
2016-03-15 17:47:08 +03:00
/****************************************************************************
* WRITE
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
static ssize_t swrap_write ( int s , const void * buf , size_t len )
{
struct msghdr msg ;
struct iovec tmp ;
struct sockaddr_un un_addr ;
ssize_t ret ;
int rc ;
struct socket_info * si ;
si = find_socket_info ( s ) ;
if ( si = = NULL ) {
return libc_write ( s , buf , len ) ;
}
tmp . iov_base = discard_const_p ( char , buf ) ;
tmp . iov_len = len ;
ZERO_STRUCT ( msg ) ;
msg . msg_name = NULL ; /* optional address */
msg . msg_namelen = 0 ; /* size of address */
msg . msg_iov = & tmp ; /* scatter/gather array */
msg . msg_iovlen = 1 ; /* # elements in msg_iov */
2019-03-21 12:02:54 +03:00
# ifdef HAVE_STRUCT_MSGHDR_MSG_CONTROL
2016-03-15 17:47:08 +03:00
msg . msg_control = NULL ; /* ancillary data, see below */
msg . msg_controllen = 0 ; /* ancillary data buffer len */
msg . msg_flags = 0 ; /* flags on received message */
# endif
rc = swrap_sendmsg_before ( s , si , & msg , & tmp , & un_addr , NULL , NULL , NULL ) ;
if ( rc < 0 ) {
return - 1 ;
}
buf = msg . msg_iov [ 0 ] . iov_base ;
len = msg . msg_iov [ 0 ] . iov_len ;
ret = libc_write ( s , buf , len ) ;
swrap_sendmsg_after ( s , si , & msg , NULL , ret ) ;
return ret ;
}
ssize_t write ( int s , const void * buf , size_t len )
{
return swrap_write ( s , buf , len ) ;
}
2014-04-07 18:12:21 +04:00
/****************************************************************************
* SEND
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2006-09-12 10:19:11 +04:00
2014-04-07 18:12:21 +04:00
static ssize_t swrap_send ( int s , const void * buf , size_t len , int flags )
2006-09-12 10:19:11 +04:00
{
2010-10-30 18:23:49 +04:00
struct msghdr msg ;
struct iovec tmp ;
struct sockaddr_un un_addr ;
ssize_t ret ;
2014-04-07 18:12:21 +04:00
int rc ;
2006-09-12 10:19:11 +04:00
struct socket_info * si = find_socket_info ( s ) ;
if ( ! si ) {
2014-04-07 18:12:21 +04:00
return libc_send ( s , buf , len , flags ) ;
2006-09-12 10:19:11 +04:00
}
2010-10-30 18:23:49 +04:00
tmp . iov_base = discard_const_p ( char , buf ) ;
tmp . iov_len = len ;
2009-03-23 11:16:18 +03:00
2011-03-04 23:14:27 +03:00
ZERO_STRUCT ( msg ) ;
2010-10-30 18:23:49 +04:00
msg . msg_name = NULL ; /* optional address */
msg . msg_namelen = 0 ; /* size of address */
msg . msg_iov = & tmp ; /* scatter/gather array */
msg . msg_iovlen = 1 ; /* # elements in msg_iov */
2019-03-21 12:02:54 +03:00
# ifdef HAVE_STRUCT_MSGHDR_MSG_CONTROL
2010-10-30 18:23:49 +04:00
msg . msg_control = NULL ; /* ancillary data, see below */
msg . msg_controllen = 0 ; /* ancillary data buffer len */
msg . msg_flags = 0 ; /* flags on received message */
2011-03-04 23:14:27 +03:00
# endif
2009-03-23 11:16:18 +03:00
2014-04-07 18:12:21 +04:00
rc = swrap_sendmsg_before ( s , si , & msg , & tmp , & un_addr , NULL , NULL , NULL ) ;
if ( rc < 0 ) {
return - 1 ;
}
2009-03-23 11:16:18 +03:00
2010-10-30 18:23:49 +04:00
buf = msg . msg_iov [ 0 ] . iov_base ;
len = msg . msg_iov [ 0 ] . iov_len ;
2009-03-23 11:16:18 +03:00
2014-04-07 18:12:21 +04:00
ret = libc_send ( s , buf , len , flags ) ;
swrap_sendmsg_after ( s , si , & msg , NULL , ret ) ;
return ret ;
}
ssize_t send ( int s , const void * buf , size_t len , int flags )
{
return swrap_send ( s , buf , len , flags ) ;
}
/****************************************************************************
* RECVMSG
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
static ssize_t swrap_recvmsg ( int s , struct msghdr * omsg , int flags )
{
2014-10-02 09:09:33 +04:00
struct swrap_address from_addr = {
. sa_socklen = sizeof ( struct sockaddr_un ) ,
} ;
2016-03-15 17:47:08 +03:00
struct swrap_address convert_addr = {
. sa_socklen = sizeof ( struct sockaddr_storage ) ,
} ;
2014-04-07 18:12:21 +04:00
struct socket_info * si ;
struct msghdr msg ;
struct iovec tmp ;
2014-06-03 17:00:18 +04:00
# ifdef HAVE_STRUCT_MSGHDR_MSG_CONTROL
2014-06-03 16:57:35 +04:00
size_t msg_ctrllen_filled ;
size_t msg_ctrllen_left ;
2014-06-03 17:00:18 +04:00
# endif
2014-04-07 18:12:21 +04:00
ssize_t ret ;
int rc ;
si = find_socket_info ( s ) ;
if ( si = = NULL ) {
2021-02-09 10:56:42 +03:00
uint8_t * tmp_control = NULL ;
rc = swrap_recvmsg_before_unix ( omsg , & msg , & tmp_control ) ;
if ( rc < 0 ) {
return rc ;
}
ret = libc_recvmsg ( s , & msg , flags ) ;
return swrap_recvmsg_after_unix ( & msg , & tmp_control , omsg , ret ) ;
2014-04-07 18:12:21 +04:00
}
tmp . iov_base = NULL ;
tmp . iov_len = 0 ;
ZERO_STRUCT ( msg ) ;
2014-10-02 09:09:33 +04:00
msg . msg_name = & from_addr . sa ; /* optional address */
msg . msg_namelen = from_addr . sa_socklen ; /* size of address */
2014-04-07 18:12:21 +04:00
msg . msg_iov = omsg - > msg_iov ; /* scatter/gather array */
msg . msg_iovlen = omsg - > msg_iovlen ; /* # elements in msg_iov */
# ifdef HAVE_STRUCT_MSGHDR_MSG_CONTROL
2014-06-03 16:57:35 +04:00
msg_ctrllen_filled = 0 ;
msg_ctrllen_left = omsg - > msg_controllen ;
2014-04-07 18:12:21 +04:00
msg . msg_control = omsg - > msg_control ; /* ancillary data, see below */
msg . msg_controllen = omsg - > msg_controllen ; /* ancillary data buffer len */
msg . msg_flags = omsg - > msg_flags ; /* flags on received message */
# endif
rc = swrap_recvmsg_before ( s , si , & msg , & tmp ) ;
if ( rc < 0 ) {
return - 1 ;
}
ret = libc_recvmsg ( s , & msg , flags ) ;
2006-09-12 10:19:11 +04:00
2014-06-03 16:57:35 +04:00
# ifdef HAVE_STRUCT_MSGHDR_MSG_CONTROL
msg_ctrllen_filled + = msg . msg_controllen ;
msg_ctrllen_left - = msg . msg_controllen ;
if ( omsg - > msg_control ! = NULL ) {
uint8_t * p ;
p = omsg - > msg_control ;
p + = msg_ctrllen_filled ;
msg . msg_control = p ;
msg . msg_controllen = msg_ctrllen_left ;
} else {
msg . msg_control = NULL ;
msg . msg_controllen = 0 ;
}
# endif
2016-03-15 17:47:08 +03:00
/*
* We convert the unix address to a IP address so we need a buffer
* which can store the address in case of SOCK_DGRAM , see below .
*/
msg . msg_name = & convert_addr . sa ;
msg . msg_namelen = convert_addr . sa_socklen ;
2014-10-02 09:09:33 +04:00
rc = swrap_recvmsg_after ( s ,
si ,
& msg ,
& from_addr . sa . un ,
from_addr . sa_socklen ,
ret ) ;
2014-04-07 18:12:21 +04:00
if ( rc ! = 0 ) {
return rc ;
}
2006-09-12 10:19:11 +04:00
2014-06-03 16:57:35 +04:00
# ifdef HAVE_STRUCT_MSGHDR_MSG_CONTROL
if ( omsg - > msg_control ! = NULL ) {
/* msg.msg_controllen = space left */
msg_ctrllen_left = msg . msg_controllen ;
msg_ctrllen_filled = omsg - > msg_controllen - msg_ctrllen_left ;
}
/* Update the original message length */
omsg - > msg_controllen = msg_ctrllen_filled ;
omsg - > msg_flags = msg . msg_flags ;
# endif
omsg - > msg_iovlen = msg . msg_iovlen ;
2018-05-02 16:57:38 +03:00
SWRAP_LOCK_SI ( si ) ;
2015-08-25 18:19:02 +03:00
/*
* From the manpage :
*
* The msg_name field points to a caller - allocated buffer that is
* used to return the source address if the socket is unconnected . The
* caller should set msg_namelen to the size of this buffer before this
* call ; upon return from a successful call , msg_name will contain the
* length of the returned address . If the application does not need
* to know the source address , msg_name can be specified as NULL .
*/
2015-08-25 18:19:43 +03:00
if ( si - > type = = SOCK_STREAM ) {
omsg - > msg_namelen = 0 ;
} else if ( omsg - > msg_name ! = NULL & &
omsg - > msg_namelen ! = 0 & &
omsg - > msg_namelen > = msg . msg_namelen ) {
2015-08-25 18:19:02 +03:00
memcpy ( omsg - > msg_name , msg . msg_name , msg . msg_namelen ) ;
omsg - > msg_namelen = msg . msg_namelen ;
}
2018-05-02 16:57:38 +03:00
SWRAP_UNLOCK_SI ( si ) ;
2005-03-28 05:00:39 +04:00
return ret ;
}
2014-04-07 18:12:21 +04:00
ssize_t recvmsg ( int sockfd , struct msghdr * msg , int flags )
{
return swrap_recvmsg ( sockfd , msg , flags ) ;
}
/****************************************************************************
* SENDMSG
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
static ssize_t swrap_sendmsg ( int s , const struct msghdr * omsg , int flags )
2009-05-26 05:43:37 +04:00
{
2010-10-30 18:23:49 +04:00
struct msghdr msg ;
struct iovec tmp ;
struct sockaddr_un un_addr ;
const struct sockaddr_un * to_un = NULL ;
const struct sockaddr * to = NULL ;
ssize_t ret ;
2014-04-07 18:12:21 +04:00
int rc ;
2009-05-26 05:43:37 +04:00
struct socket_info * si = find_socket_info ( s ) ;
2010-10-30 18:23:49 +04:00
int bcast = 0 ;
2009-05-26 05:43:37 +04:00
if ( ! si ) {
2021-02-09 10:56:42 +03:00
int scm_rights_pipe_fd = - 1 ;
rc = swrap_sendmsg_before_unix ( omsg , & msg ,
& scm_rights_pipe_fd ) ;
if ( rc < 0 ) {
return rc ;
}
ret = libc_sendmsg ( s , & msg , flags ) ;
return swrap_sendmsg_after_unix ( & msg , ret , scm_rights_pipe_fd ) ;
2009-05-26 05:43:37 +04:00
}
2014-04-07 18:12:21 +04:00
ZERO_STRUCT ( un_addr ) ;
2010-10-30 18:23:49 +04:00
tmp . iov_base = NULL ;
tmp . iov_len = 0 ;
2009-05-26 05:43:37 +04:00
2014-04-07 18:12:21 +04:00
ZERO_STRUCT ( msg ) ;
2015-08-25 18:19:43 +03:00
2018-05-02 16:57:38 +03:00
SWRAP_LOCK_SI ( si ) ;
2015-08-25 18:19:43 +03:00
if ( si - > connected = = 0 ) {
msg . msg_name = omsg - > msg_name ; /* optional address */
msg . msg_namelen = omsg - > msg_namelen ; /* size of address */
}
2010-10-30 18:23:49 +04:00
msg . msg_iov = omsg - > msg_iov ; /* scatter/gather array */
msg . msg_iovlen = omsg - > msg_iovlen ; /* # elements in msg_iov */
2018-05-02 16:57:38 +03:00
SWRAP_UNLOCK_SI ( si ) ;
2014-04-07 18:12:21 +04:00
# ifdef HAVE_STRUCT_MSGHDR_MSG_CONTROL
2021-02-09 10:56:42 +03:00
if ( omsg ! = NULL & & omsg - > msg_controllen > 0 & & omsg - > msg_control ! = NULL ) {
uint8_t * cmbuf = NULL ;
size_t cmlen = 0 ;
2014-06-03 17:05:12 +04:00
2021-02-09 10:56:42 +03:00
rc = swrap_sendmsg_filter_cmsghdr ( omsg , & cmbuf , & cmlen ) ;
if ( rc < 0 ) {
return rc ;
}
2014-06-03 17:05:12 +04:00
2021-02-09 10:56:42 +03:00
if ( cmlen = = 0 ) {
msg . msg_controllen = 0 ;
msg . msg_control = NULL ;
} else {
msg . msg_control = cmbuf ;
msg . msg_controllen = cmlen ;
}
2014-06-03 17:05:12 +04:00
}
2010-10-30 18:23:49 +04:00
msg . msg_flags = omsg - > msg_flags ; /* flags on received message */
2011-03-04 23:14:27 +03:00
# endif
2014-04-07 18:12:21 +04:00
rc = swrap_sendmsg_before ( s , si , & msg , & tmp , & un_addr , & to_un , & to , & bcast ) ;
if ( rc < 0 ) {
2021-02-09 10:56:42 +03:00
int saved_errno = errno ;
# ifdef HAVE_STRUCT_MSGHDR_MSG_CONTROL
SAFE_FREE ( msg . msg_control ) ;
# endif
errno = saved_errno ;
2014-04-07 18:12:21 +04:00
return - 1 ;
}
2010-10-30 18:23:49 +04:00
if ( bcast ) {
struct stat st ;
unsigned int iface ;
2014-10-02 09:23:25 +04:00
unsigned int prt = ntohs ( ( ( const struct sockaddr_in * ) ( const void * ) to ) - > sin_port ) ;
2010-10-30 18:23:49 +04:00
char type ;
size_t i , len = 0 ;
uint8_t * buf ;
off_t ofs = 0 ;
size_t avail = 0 ;
size_t remain ;
2019-03-21 12:02:54 +03:00
char * swrap_dir = NULL ;
2010-10-30 18:23:49 +04:00
2014-04-07 18:12:21 +04:00
for ( i = 0 ; i < ( size_t ) msg . msg_iovlen ; i + + ) {
2010-10-30 18:23:49 +04:00
avail + = msg . msg_iov [ i ] . iov_len ;
2009-05-26 05:43:37 +04:00
}
2010-10-30 18:23:49 +04:00
len = avail ;
remain = avail ;
2009-05-26 05:43:37 +04:00
2010-10-30 18:23:49 +04:00
/* we capture it as one single packet */
buf = ( uint8_t * ) malloc ( remain ) ;
if ( ! buf ) {
2021-02-09 10:56:42 +03:00
int saved_errno = errno ;
# ifdef HAVE_STRUCT_MSGHDR_MSG_CONTROL
SAFE_FREE ( msg . msg_control ) ;
# endif
errno = saved_errno ;
2010-10-30 18:23:49 +04:00
return - 1 ;
}
2009-05-26 05:43:37 +04:00
2014-04-07 18:12:21 +04:00
for ( i = 0 ; i < ( size_t ) msg . msg_iovlen ; i + + ) {
size_t this_time = MIN ( remain , ( size_t ) msg . msg_iov [ i ] . iov_len ) ;
2010-10-30 18:23:49 +04:00
memcpy ( buf + ofs ,
msg . msg_iov [ i ] . iov_base ,
this_time ) ;
ofs + = this_time ;
remain - = this_time ;
2009-05-26 05:43:37 +04:00
}
2010-10-30 18:23:49 +04:00
type = SOCKET_TYPE_CHAR_UDP ;
2019-03-21 12:02:54 +03:00
swrap_dir = socket_wrapper_dir ( ) ;
if ( swrap_dir = = NULL ) {
2021-02-09 10:56:42 +03:00
int saved_errno = errno ;
# ifdef HAVE_STRUCT_MSGHDR_MSG_CONTROL
SAFE_FREE ( msg . msg_control ) ;
# endif
SAFE_FREE ( buf ) ;
errno = saved_errno ;
2019-03-21 12:02:54 +03:00
return - 1 ;
}
2010-10-30 18:23:49 +04:00
for ( iface = 0 ; iface < = MAX_WRAPPED_INTERFACES ; iface + + ) {
2020-06-08 15:18:00 +03:00
swrap_un_path ( & un_addr , swrap_dir , type , iface , prt ) ;
2010-10-30 18:23:49 +04:00
if ( stat ( un_addr . sun_path , & st ) ! = 0 ) continue ;
msg . msg_name = & un_addr ; /* optional address */
msg . msg_namelen = sizeof ( un_addr ) ; /* size of address */
/* ignore the any errors in broadcast sends */
2014-04-07 18:12:21 +04:00
libc_sendmsg ( s , & msg , flags ) ;
2009-05-26 05:43:37 +04:00
}
2019-03-21 12:02:54 +03:00
SAFE_FREE ( swrap_dir ) ;
2018-05-02 16:57:38 +03:00
SWRAP_LOCK_SI ( si ) ;
2014-10-02 09:15:38 +04:00
swrap_pcap_dump_packet ( si , to , SWRAP_SENDTO , buf , len ) ;
2010-10-30 18:23:49 +04:00
free ( buf ) ;
2011-02-12 14:18:16 +03:00
2018-05-02 16:57:38 +03:00
SWRAP_UNLOCK_SI ( si ) ;
2010-10-30 18:23:49 +04:00
return len ;
2009-05-26 05:43:37 +04:00
}
2011-02-12 14:18:16 +03:00
2014-04-07 18:12:21 +04:00
ret = libc_sendmsg ( s , & msg , flags ) ;
2011-02-12 14:18:16 +03:00
2014-04-07 18:12:21 +04:00
swrap_sendmsg_after ( s , si , & msg , to , ret ) ;
2009-05-26 05:43:37 +04:00
2021-02-09 10:56:42 +03:00
# ifdef HAVE_STRUCT_MSGHDR_MSG_CONTROL
{
int saved_errno = errno ;
SAFE_FREE ( msg . msg_control ) ;
errno = saved_errno ;
}
# endif
2009-05-26 05:43:37 +04:00
return ret ;
}
2014-04-07 18:12:21 +04:00
ssize_t sendmsg ( int s , const struct msghdr * omsg , int flags )
2009-03-09 19:48:08 +03:00
{
2014-04-07 18:12:21 +04:00
return swrap_sendmsg ( s , omsg , flags ) ;
}
2009-03-09 19:48:08 +03:00
2014-04-07 18:12:21 +04:00
/****************************************************************************
* READV
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2010-10-30 18:28:23 +04:00
2014-04-07 18:12:21 +04:00
static ssize_t swrap_readv ( int s , const struct iovec * vector , int count )
{
struct socket_info * si ;
struct msghdr msg ;
struct iovec tmp ;
2014-10-02 09:09:33 +04:00
struct swrap_address saddr = {
. sa_socklen = sizeof ( struct sockaddr_storage )
} ;
2014-04-07 18:12:21 +04:00
ssize_t ret ;
int rc ;
2011-02-12 14:18:16 +03:00
2014-04-07 18:12:21 +04:00
si = find_socket_info ( s ) ;
if ( si = = NULL ) {
return libc_readv ( s , vector , count ) ;
2009-03-09 19:48:08 +03:00
}
2014-04-07 18:12:21 +04:00
tmp . iov_base = NULL ;
tmp . iov_len = 0 ;
2009-03-09 19:48:08 +03:00
2014-04-07 18:12:21 +04:00
ZERO_STRUCT ( msg ) ;
2014-10-02 09:09:33 +04:00
msg . msg_name = & saddr . sa . s ; /* optional address */
msg . msg_namelen = saddr . sa_socklen ; /* size of address */
2014-04-07 18:12:21 +04:00
msg . msg_iov = discard_const_p ( struct iovec , vector ) ; /* scatter/gather array */
msg . msg_iovlen = count ; /* # elements in msg_iov */
# ifdef HAVE_STRUCT_MSGHDR_MSG_CONTROL
msg . msg_control = NULL ; /* ancillary data, see below */
msg . msg_controllen = 0 ; /* ancillary data buffer len */
msg . msg_flags = 0 ; /* flags on received message */
# endif
2009-03-09 19:48:08 +03:00
2014-04-07 18:12:21 +04:00
rc = swrap_recvmsg_before ( s , si , & msg , & tmp ) ;
if ( rc < 0 ) {
if ( rc = = - ENOTSOCK ) {
return libc_readv ( s , vector , count ) ;
2009-03-09 19:48:08 +03:00
}
2014-04-07 18:12:21 +04:00
return - 1 ;
}
2009-03-09 19:48:08 +03:00
2014-04-07 18:12:21 +04:00
ret = libc_readv ( s , msg . msg_iov , msg . msg_iovlen ) ;
rc = swrap_recvmsg_after ( s , si , & msg , NULL , 0 , ret ) ;
if ( rc ! = 0 ) {
return rc ;
2009-03-09 19:48:08 +03:00
}
return ret ;
}
2014-04-07 18:12:21 +04:00
ssize_t readv ( int s , const struct iovec * vector , int count )
{
return swrap_readv ( s , vector , count ) ;
}
/****************************************************************************
* WRITEV
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
static ssize_t swrap_writev ( int s , const struct iovec * vector , int count )
2009-03-09 19:48:08 +03:00
{
2010-10-30 18:23:49 +04:00
struct msghdr msg ;
struct iovec tmp ;
struct sockaddr_un un_addr ;
ssize_t ret ;
2014-04-07 18:12:21 +04:00
int rc ;
2009-03-09 19:48:08 +03:00
struct socket_info * si = find_socket_info ( s ) ;
if ( ! si ) {
2014-04-07 18:12:21 +04:00
return libc_writev ( s , vector , count ) ;
2009-03-09 19:48:08 +03:00
}
2010-10-30 18:23:49 +04:00
tmp . iov_base = NULL ;
tmp . iov_len = 0 ;
2009-03-09 19:48:08 +03:00
2011-03-04 23:14:27 +03:00
ZERO_STRUCT ( msg ) ;
2010-10-30 18:23:49 +04:00
msg . msg_name = NULL ; /* optional address */
msg . msg_namelen = 0 ; /* size of address */
msg . msg_iov = discard_const_p ( struct iovec , vector ) ; /* scatter/gather array */
msg . msg_iovlen = count ; /* # elements in msg_iov */
2019-03-21 12:02:54 +03:00
# ifdef HAVE_STRUCT_MSGHDR_MSG_CONTROL
2010-10-30 18:23:49 +04:00
msg . msg_control = NULL ; /* ancillary data, see below */
msg . msg_controllen = 0 ; /* ancillary data buffer len */
msg . msg_flags = 0 ; /* flags on received message */
2011-03-04 23:14:27 +03:00
# endif
2009-03-09 19:48:08 +03:00
2014-04-07 18:12:21 +04:00
rc = swrap_sendmsg_before ( s , si , & msg , & tmp , & un_addr , NULL , NULL , NULL ) ;
if ( rc < 0 ) {
if ( rc = = - ENOTSOCK ) {
return libc_readv ( s , vector , count ) ;
}
return - 1 ;
}
2009-03-09 19:48:08 +03:00
2014-04-07 18:12:21 +04:00
ret = libc_writev ( s , msg . msg_iov , msg . msg_iovlen ) ;
2009-03-09 19:48:08 +03:00
2014-04-07 18:12:21 +04:00
swrap_sendmsg_after ( s , si , & msg , NULL , ret ) ;
2009-03-09 19:48:08 +03:00
return ret ;
}
2014-04-07 18:12:21 +04:00
ssize_t writev ( int s , const struct iovec * vector , int count )
{
return swrap_writev ( s , vector , count ) ;
}
/****************************
* CLOSE
* * * * * * * * * * * * * * * * * * * * * * * * * * */
2021-02-17 14:57:01 +03:00
static int swrap_remove_wrapper ( const char * __func_name ,
int ( * __close_fd_fn ) ( int fd ) ,
int fd )
2005-03-28 05:00:39 +04:00
{
2017-11-07 14:29:51 +03:00
struct socket_info * si = NULL ;
int si_index ;
2021-02-17 14:57:01 +03:00
int ret_errno = errno ;
2006-09-26 17:15:31 +04:00
int ret ;
2018-05-02 16:57:38 +03:00
swrap_mutex_lock ( & socket_reset_mutex ) ;
si_index = find_socket_info_index ( fd ) ;
if ( si_index = = - 1 ) {
swrap_mutex_unlock ( & socket_reset_mutex ) ;
2021-02-17 14:57:01 +03:00
return __close_fd_fn ( fd ) ;
2006-09-26 17:15:31 +04:00
}
2005-03-28 05:00:39 +04:00
2021-02-17 14:57:01 +03:00
swrap_log ( SWRAP_LOG_TRACE , __func_name , " Remove wrapper for fd=%d " , fd ) ;
2018-05-02 16:57:38 +03:00
reset_socket_info_index ( fd ) ;
2017-11-07 14:29:51 +03:00
2018-05-02 16:57:38 +03:00
si = swrap_get_socket_info ( si_index ) ;
swrap_mutex_lock ( & first_free_mutex ) ;
SWRAP_LOCK_SI ( si ) ;
2017-11-07 14:29:51 +03:00
2021-02-17 14:57:01 +03:00
ret = __close_fd_fn ( fd ) ;
if ( ret = = - 1 ) {
ret_errno = errno ;
}
2011-09-29 01:09:49 +04:00
2018-05-02 16:57:38 +03:00
swrap_dec_refcount ( si ) ;
2017-11-07 14:29:51 +03:00
2018-05-02 16:57:38 +03:00
if ( swrap_get_refcount ( si ) > 0 ) {
2011-09-29 01:09:49 +04:00
/* there are still references left */
2018-05-02 16:57:38 +03:00
goto out ;
2011-09-29 01:09:49 +04:00
}
2021-02-09 10:56:42 +03:00
if ( si - > fd_passed ) {
goto set_next_free ;
}
2014-10-02 09:17:10 +04:00
if ( si - > myname . sa_socklen > 0 & & si - > peername . sa_socklen > 0 ) {
2014-10-02 09:15:38 +04:00
swrap_pcap_dump_packet ( si , NULL , SWRAP_CLOSE_SEND , NULL , 0 ) ;
2006-09-29 13:31:20 +04:00
}
2014-10-02 09:17:10 +04:00
if ( si - > myname . sa_socklen > 0 & & si - > peername . sa_socklen > 0 ) {
2014-10-02 09:15:38 +04:00
swrap_pcap_dump_packet ( si , NULL , SWRAP_CLOSE_RECV , NULL , 0 ) ;
swrap_pcap_dump_packet ( si , NULL , SWRAP_CLOSE_ACK , NULL , 0 ) ;
2006-09-29 13:31:20 +04:00
}
2014-10-02 09:16:25 +04:00
if ( si - > un_addr . sun_path [ 0 ] ! = ' \0 ' ) {
unlink ( si - > un_addr . sun_path ) ;
2005-03-28 05:00:39 +04:00
}
2017-11-07 14:29:51 +03:00
2021-02-09 10:56:42 +03:00
set_next_free :
2018-05-02 16:57:38 +03:00
swrap_set_next_free ( si , first_free ) ;
2017-11-07 14:29:51 +03:00
first_free = si_index ;
2005-03-28 05:00:39 +04:00
2018-05-02 16:57:38 +03:00
out :
SWRAP_UNLOCK_SI ( si ) ;
swrap_mutex_unlock ( & first_free_mutex ) ;
swrap_mutex_unlock ( & socket_reset_mutex ) ;
2021-02-17 14:57:01 +03:00
errno = ret_errno ;
2006-09-26 17:15:31 +04:00
return ret ;
2005-03-28 05:00:39 +04:00
}
2011-08-12 08:28:03 +04:00
2021-02-17 14:57:01 +03:00
static int swrap_noop_close ( int fd )
{
( void ) fd ; /* unused */
return 0 ;
}
static void swrap_remove_stale ( int fd )
{
swrap_remove_wrapper ( __func__ , swrap_noop_close , fd ) ;
}
/*
* This allows socket_wrapper aware applications to
* indicate that the given fd does not belong to
* an inet socket .
*
* We already overload a lot of unrelated functions
* like eventfd ( ) , timerfd_create ( ) , . . . in order to
* call swrap_remove_stale ( ) on the returned fd , but
* we ' ll never be able to handle all possible syscalls .
*
* socket_wrapper_indicate_no_inet_fd ( ) gives them a way
* to do the same .
*
* We don ' t export swrap_remove_stale ( ) in order to
* make it easier to analyze SOCKET_WRAPPER_DEBUGLEVEL = 3
* log files .
*/
void socket_wrapper_indicate_no_inet_fd ( int fd )
{
swrap_remove_wrapper ( __func__ , swrap_noop_close , fd ) ;
}
static int swrap_close ( int fd )
{
return swrap_remove_wrapper ( __func__ , libc_close , fd ) ;
}
2014-04-07 18:12:21 +04:00
int close ( int fd )
{
return swrap_close ( fd ) ;
}
2021-02-17 14:57:01 +03:00
# ifdef HAVE___CLOSE_NOCANCEL
static int swrap___close_nocancel ( int fd )
{
return swrap_remove_wrapper ( __func__ , libc___close_nocancel , fd ) ;
}
int __close_nocancel ( int fd ) ;
int __close_nocancel ( int fd )
{
return swrap___close_nocancel ( fd ) ;
}
# endif /* HAVE___CLOSE_NOCANCEL */
2014-04-07 18:12:21 +04:00
/****************************
* DUP
* * * * * * * * * * * * * * * * * * * * * * * * * * */
static int swrap_dup ( int fd )
2011-08-12 08:28:03 +04:00
{
2011-09-29 01:09:49 +04:00
struct socket_info * si ;
2018-05-02 16:57:38 +03:00
int dup_fd , idx ;
2011-08-12 08:28:03 +04:00
2018-05-02 16:57:38 +03:00
idx = find_socket_info_index ( fd ) ;
if ( idx = = - 1 ) {
2014-04-07 18:12:21 +04:00
return libc_dup ( fd ) ;
2011-08-12 08:28:03 +04:00
}
2018-05-02 16:57:38 +03:00
si = swrap_get_socket_info ( idx ) ;
2011-08-12 08:28:03 +04:00
2018-05-02 16:57:38 +03:00
dup_fd = libc_dup ( fd ) ;
if ( dup_fd = = - 1 ) {
2011-09-29 01:09:49 +04:00
int saved_errno = errno ;
errno = saved_errno ;
return - 1 ;
2011-08-12 08:28:03 +04:00
}
2021-02-09 10:56:42 +03:00
if ( ( size_t ) dup_fd > = socket_fds_max ) {
SWRAP_LOG ( SWRAP_LOG_ERROR ,
" The max socket index limit of %zu has been reached, "
" trying to add %d " ,
socket_fds_max ,
dup_fd ) ;
libc_close ( dup_fd ) ;
errno = EMFILE ;
return - 1 ;
}
2018-05-02 16:57:38 +03:00
SWRAP_LOCK_SI ( si ) ;
swrap_inc_refcount ( si ) ;
SWRAP_UNLOCK_SI ( si ) ;
2017-11-07 14:29:51 +03:00
2014-04-07 18:12:21 +04:00
/* Make sure we don't have an entry for the fd */
2018-05-02 16:57:38 +03:00
swrap_remove_stale ( dup_fd ) ;
2014-04-07 18:12:21 +04:00
2018-05-02 16:57:38 +03:00
set_socket_info_index ( dup_fd , idx ) ;
return dup_fd ;
2011-08-12 08:28:03 +04:00
}
2014-04-07 18:12:21 +04:00
int dup ( int fd )
{
return swrap_dup ( fd ) ;
}
/****************************
* DUP2
* * * * * * * * * * * * * * * * * * * * * * * * * * */
static int swrap_dup2 ( int fd , int newfd )
2011-08-12 08:28:03 +04:00
{
2011-09-29 01:09:49 +04:00
struct socket_info * si ;
2018-05-02 16:57:38 +03:00
int dup_fd , idx ;
2011-08-12 08:28:03 +04:00
2018-05-02 16:57:38 +03:00
idx = find_socket_info_index ( fd ) ;
if ( idx = = - 1 ) {
2014-04-07 18:12:21 +04:00
return libc_dup2 ( fd , newfd ) ;
2011-08-12 08:28:03 +04:00
}
2018-05-02 16:57:38 +03:00
si = swrap_get_socket_info ( idx ) ;
2017-11-07 14:29:51 +03:00
if ( fd = = newfd ) {
/*
* According to the manpage :
*
* " If oldfd is a valid file descriptor, and newfd has the same
* value as oldfd , then dup2 ( ) does nothing , and returns newfd . "
*/
return newfd ;
}
2021-02-09 10:56:42 +03:00
if ( ( size_t ) newfd > = socket_fds_max ) {
SWRAP_LOG ( SWRAP_LOG_ERROR ,
" The max socket index limit of %zu has been reached, "
" trying to add %d " ,
socket_fds_max ,
newfd ) ;
errno = EMFILE ;
return - 1 ;
}
2011-08-12 08:28:03 +04:00
if ( find_socket_info ( newfd ) ) {
/* dup2() does an implicit close of newfd, which we
* need to emulate */
swrap_close ( newfd ) ;
}
2018-05-02 16:57:38 +03:00
dup_fd = libc_dup2 ( fd , newfd ) ;
if ( dup_fd = = - 1 ) {
2011-09-29 01:09:49 +04:00
int saved_errno = errno ;
errno = saved_errno ;
return - 1 ;
2011-08-12 08:28:03 +04:00
}
2018-05-02 16:57:38 +03:00
SWRAP_LOCK_SI ( si ) ;
swrap_inc_refcount ( si ) ;
SWRAP_UNLOCK_SI ( si ) ;
2017-11-07 14:29:51 +03:00
2014-04-07 18:12:21 +04:00
/* Make sure we don't have an entry for the fd */
2018-05-02 16:57:38 +03:00
swrap_remove_stale ( dup_fd ) ;
set_socket_info_index ( dup_fd , idx ) ;
2014-04-07 18:12:21 +04:00
2018-05-02 16:57:38 +03:00
return dup_fd ;
2011-08-12 08:28:03 +04:00
}
2014-04-07 18:12:21 +04:00
int dup2 ( int fd , int newfd )
{
return swrap_dup2 ( fd , newfd ) ;
}
/****************************
2014-10-02 09:24:27 +04:00
* FCNTL
* * * * * * * * * * * * * * * * * * * * * * * * * * */
static int swrap_vfcntl ( int fd , int cmd , va_list va )
{
struct socket_info * si ;
2018-05-02 16:57:38 +03:00
int rc , dup_fd , idx ;
2014-10-02 09:24:27 +04:00
2018-05-02 16:57:38 +03:00
idx = find_socket_info_index ( fd ) ;
if ( idx = = - 1 ) {
2017-11-07 14:29:51 +03:00
return libc_vfcntl ( fd , cmd , va ) ;
2014-10-02 09:24:27 +04:00
}
2018-05-02 16:57:38 +03:00
si = swrap_get_socket_info ( idx ) ;
2017-11-07 14:29:51 +03:00
2014-10-02 09:24:27 +04:00
switch ( cmd ) {
case F_DUPFD :
2018-05-02 16:57:38 +03:00
dup_fd = libc_vfcntl ( fd , cmd , va ) ;
if ( dup_fd = = - 1 ) {
2014-10-02 09:24:27 +04:00
int saved_errno = errno ;
errno = saved_errno ;
return - 1 ;
}
2021-02-09 10:56:42 +03:00
/* Make sure we don't have an entry for the fd */
swrap_remove_stale ( dup_fd ) ;
if ( ( size_t ) dup_fd > = socket_fds_max ) {
SWRAP_LOG ( SWRAP_LOG_ERROR ,
" The max socket index limit of %zu has been reached, "
" trying to add %d " ,
socket_fds_max ,
dup_fd ) ;
libc_close ( dup_fd ) ;
errno = EMFILE ;
return - 1 ;
}
2018-05-02 16:57:38 +03:00
SWRAP_LOCK_SI ( si ) ;
swrap_inc_refcount ( si ) ;
SWRAP_UNLOCK_SI ( si ) ;
2017-11-07 14:29:51 +03:00
2014-10-02 09:24:27 +04:00
2018-05-02 16:57:38 +03:00
set_socket_info_index ( dup_fd , idx ) ;
2014-10-02 09:24:27 +04:00
2018-05-02 16:57:38 +03:00
rc = dup_fd ;
2014-10-02 09:24:27 +04:00
break ;
default :
rc = libc_vfcntl ( fd , cmd , va ) ;
break ;
}
return rc ;
}
int fcntl ( int fd , int cmd , . . . )
{
va_list va ;
int rc ;
va_start ( va , cmd ) ;
rc = swrap_vfcntl ( fd , cmd , va ) ;
va_end ( va ) ;
return rc ;
}
/****************************
* EVENTFD
2014-04-07 18:12:21 +04:00
* * * * * * * * * * * * * * * * * * * * * * * * * * */
# ifdef HAVE_EVENTFD
static int swrap_eventfd ( int count , int flags )
{
int fd ;
fd = libc_eventfd ( count , flags ) ;
if ( fd ! = - 1 ) {
swrap_remove_stale ( fd ) ;
}
return fd ;
}
2014-10-02 09:25:32 +04:00
# ifdef HAVE_EVENTFD_UNSIGNED_INT
int eventfd ( unsigned int count , int flags )
# else
2014-04-07 18:12:21 +04:00
int eventfd ( int count , int flags )
2014-10-02 09:25:32 +04:00
# endif
2014-04-07 18:12:21 +04:00
{
return swrap_eventfd ( count , flags ) ;
}
# endif
2016-05-20 11:20:28 +03:00
# ifdef HAVE_PLEDGE
int pledge ( const char * promises , const char * paths [ ] )
{
( void ) promises ; /* unused */
( void ) paths ; /* unused */
return 0 ;
}
# endif /* HAVE_PLEDGE */
2017-11-07 14:29:51 +03:00
static void swrap_thread_prepare ( void )
{
/*
* This function should only be called here ! !
*
* We bind all symobls to avoid deadlocks of the fork is
* interrupted by a signal handler using a symbol of this
* library .
*/
swrap_bind_symbol_all ( ) ;
SWRAP_LOCK_ALL ;
}
static void swrap_thread_parent ( void )
{
SWRAP_UNLOCK_ALL ;
}
static void swrap_thread_child ( void )
{
2021-02-09 10:56:42 +03:00
SWRAP_REINIT_ALL ;
2017-11-07 14:29:51 +03:00
}
/****************************
* CONSTRUCTOR
* * * * * * * * * * * * * * * * * * * * * * * * * * */
void swrap_constructor ( void )
{
2021-02-09 10:56:42 +03:00
if ( PIPE_BUF < sizeof ( struct swrap_unix_scm_rights ) ) {
SWRAP_LOG ( SWRAP_LOG_ERROR ,
" PIPE_BUF=%zu < "
" sizeof(struct swrap_unix_scm_rights)=%zu \n "
" sizeof(struct swrap_unix_scm_rights_payload)=%zu "
" sizeof(struct socket_info)=%zu " ,
( size_t ) PIPE_BUF ,
sizeof ( struct swrap_unix_scm_rights ) ,
sizeof ( struct swrap_unix_scm_rights_payload ) ,
sizeof ( struct socket_info ) ) ;
exit ( - 1 ) ;
}
SWRAP_REINIT_ALL ;
2018-05-02 16:57:38 +03:00
2017-11-07 14:29:51 +03:00
/*
* If we hold a lock and the application forks , then the child
* is not able to unlock the mutex and we are in a deadlock .
* This should prevent such deadlocks .
*/
pthread_atfork ( & swrap_thread_prepare ,
& swrap_thread_parent ,
& swrap_thread_child ) ;
}
2014-04-07 18:12:21 +04:00
/****************************
* DESTRUCTOR
* * * * * * * * * * * * * * * * * * * * * * * * * * */
/*
* This function is called when the library is unloaded and makes sure that
* sockets get closed and the unix file for the socket are unlinked .
*/
void swrap_destructor ( void )
{
2018-05-02 16:57:38 +03:00
size_t i ;
2014-04-07 18:12:21 +04:00
2018-05-02 16:57:38 +03:00
if ( socket_fds_idx ! = NULL ) {
for ( i = 0 ; i < socket_fds_max ; + + i ) {
if ( socket_fds_idx [ i ] ! = - 1 ) {
swrap_close ( i ) ;
}
}
SAFE_FREE ( socket_fds_idx ) ;
2014-04-07 18:12:21 +04:00
}
2015-08-25 18:21:33 +03:00
2018-05-02 16:57:38 +03:00
SAFE_FREE ( sockets ) ;
2017-11-07 14:29:51 +03:00
if ( swrap . libc . handle ! = NULL ) {
dlclose ( swrap . libc . handle ) ;
2015-08-25 18:21:33 +03:00
}
2017-11-07 14:29:51 +03:00
if ( swrap . libc . socket_handle ) {
dlclose ( swrap . libc . socket_handle ) ;
2015-08-25 18:21:33 +03:00
}
2014-04-07 18:12:21 +04:00
}
2020-03-10 15:27:27 +03:00
# if defined(HAVE__SOCKET) && defined(HAVE__CLOSE)
/*
* On FreeBSD 12 ( and maybe other platforms )
* system libraries like libresolv prefix there
* syscalls with ' _ ' in order to always use
* the symbols from libc .
*
* In the interaction with resolv_wrapper ,
* we need to inject socket wrapper into libresolv ,
* which means we need to private all socket
* related syscalls also with the ' _ ' prefix .
*
* This is tested in Samba ' s ' make test ' ,
* there we noticed that providing ' _read '
* and ' _open ' would cause errors , which
* means we skip ' _read ' , ' _write ' and
* all non socket related calls without
* further analyzing the problem .
*/
# define SWRAP_SYMBOL_ALIAS(__sym, __aliassym) \
extern typeof ( __sym ) __aliassym __attribute__ ( ( alias ( # __sym ) ) )
# ifdef HAVE_ACCEPT4
SWRAP_SYMBOL_ALIAS ( accept4 , _accept4 ) ;
# endif
SWRAP_SYMBOL_ALIAS ( accept , _accept ) ;
SWRAP_SYMBOL_ALIAS ( bind , _bind ) ;
SWRAP_SYMBOL_ALIAS ( close , _close ) ;
SWRAP_SYMBOL_ALIAS ( connect , _connect ) ;
SWRAP_SYMBOL_ALIAS ( dup , _dup ) ;
SWRAP_SYMBOL_ALIAS ( dup2 , _dup2 ) ;
SWRAP_SYMBOL_ALIAS ( fcntl , _fcntl ) ;
SWRAP_SYMBOL_ALIAS ( getpeername , _getpeername ) ;
SWRAP_SYMBOL_ALIAS ( getsockname , _getsockname ) ;
SWRAP_SYMBOL_ALIAS ( getsockopt , _getsockopt ) ;
SWRAP_SYMBOL_ALIAS ( ioctl , _ioctl ) ;
SWRAP_SYMBOL_ALIAS ( listen , _listen ) ;
SWRAP_SYMBOL_ALIAS ( readv , _readv ) ;
SWRAP_SYMBOL_ALIAS ( recv , _recv ) ;
SWRAP_SYMBOL_ALIAS ( recvfrom , _recvfrom ) ;
SWRAP_SYMBOL_ALIAS ( recvmsg , _recvmsg ) ;
SWRAP_SYMBOL_ALIAS ( send , _send ) ;
SWRAP_SYMBOL_ALIAS ( sendmsg , _sendmsg ) ;
SWRAP_SYMBOL_ALIAS ( sendto , _sendto ) ;
SWRAP_SYMBOL_ALIAS ( setsockopt , _setsockopt ) ;
SWRAP_SYMBOL_ALIAS ( socket , _socket ) ;
SWRAP_SYMBOL_ALIAS ( socketpair , _socketpair ) ;
SWRAP_SYMBOL_ALIAS ( writev , _writev ) ;
# endif /* SOCKET_WRAPPER_EXPORT_UNDERSCORE_SYMBOLS */