2016-02-11 15:46:16 +03:00
/*
* Copyright ( C ) 2013 - 2014 Red Hat , Inc .
*
* This library is free software ; you can redistribute it and / or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation ; either
* version 2.1 of the License , or ( at your option ) any later version .
*
* This library is distributed in the hope that it will be useful ,
* but WITHOUT ANY WARRANTY ; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE . See the GNU
* Lesser General Public License for more details .
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library . If not , see
* < http : //www.gnu.org/licenses/>.
*/
# include <config.h>
2020-09-01 14:27:44 +03:00
# if WITH_DLFCN_H
2016-02-11 15:46:16 +03:00
# include <dlfcn.h>
# endif
2016-02-12 15:48:02 +03:00
# if defined(__linux__) && defined(RTLD_NEXT)
2020-01-14 20:38:59 +03:00
# include "virsocket.h"
2016-02-11 15:46:16 +03:00
# include <unistd.h>
static bool host_has_ipv6 ;
static int ( * realsocket ) ( int domain , int type , int protocol ) ;
static void init_syms ( void )
{
int fd ;
if ( realsocket )
return ;
realsocket = dlsym ( RTLD_NEXT , " socket " ) ;
if ( ! realsocket ) {
fprintf ( stderr , " Unable to find 'socket' symbol \n " ) ;
abort ( ) ;
}
fd = realsocket ( AF_INET6 , SOCK_STREAM , 0 ) ;
if ( fd < 0 )
return ;
host_has_ipv6 = true ;
close ( fd ) ;
}
int socket ( int domain ,
int type ,
int protocol )
{
init_syms ( ) ;
if ( getenv ( " LIBVIRT_TEST_IPV4ONLY " ) & & domain = = AF_INET6 ) {
errno = EAFNOSUPPORT ;
return - 1 ;
}
return realsocket ( domain , type , protocol ) ;
}
2019-10-14 15:45:03 +03:00
int bind ( int sockfd G_GNUC_UNUSED ,
2016-02-11 15:46:16 +03:00
const struct sockaddr * addr ,
2019-10-14 15:45:03 +03:00
socklen_t addrlen G_GNUC_UNUSED )
2016-02-11 15:46:16 +03:00
{
struct sockaddr_in saddr ;
memcpy ( & saddr , addr , sizeof ( saddr ) ) ;
if ( host_has_ipv6 & & ! getenv ( " LIBVIRT_TEST_IPV4ONLY " ) ) {
if ( saddr . sin_port = = htons ( 5900 ) | |
( saddr . sin_family = = AF_INET & &
saddr . sin_port = = htons ( 5904 ) ) | |
( saddr . sin_family = = AF_INET6 & &
( saddr . sin_port = = htons ( 5905 ) | |
saddr . sin_port = = htons ( 5906 ) ) ) ) {
errno = EADDRINUSE ;
return - 1 ;
}
return 0 ;
}
if ( saddr . sin_port = = htons ( 5900 ) | |
saddr . sin_port = = htons ( 5904 ) | |
saddr . sin_port = = htons ( 5905 ) | |
saddr . sin_port = = htons ( 5906 ) ) {
errno = EADDRINUSE ;
return - 1 ;
}
return 0 ;
}
2016-02-12 15:48:02 +03:00
# else /* defined(__linux__) && defined(RTLD_NEXT) */
/* Nothing to override on other platforms. */
# endif