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/>.
*
* Author : Daniel P . Berrange < berrange @ redhat . com >
*/
# include <config.h>
# if HAVE_DLFCN_H
# include <dlfcn.h>
# endif
2016-02-12 15:48:02 +03:00
# if defined(__linux__) && defined(RTLD_NEXT)
2016-02-11 15:46:16 +03:00
# include "internal.h"
# include <sys / socket.h>
# include <arpa / inet.h>
# include <netinet / in.h>
# 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 ) ;
}
int bind ( int sockfd ATTRIBUTE_UNUSED ,
const struct sockaddr * addr ,
socklen_t addrlen ATTRIBUTE_UNUSED )
{
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