2016-02-15 16:02:05 +03:00
/*
* Copyright ( C ) 2016 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>
# include "testutils.h"
2020-06-02 18:26:54 +03:00
# ifdef WITH_NSS
2016-02-15 16:02:05 +03:00
# include "libvirt_nss.h"
2020-01-14 20:38:59 +03:00
# include "virsocket.h"
2016-02-15 16:02:05 +03:00
# define VIR_FROM_THIS VIR_FROM_NONE
# define BUF_SIZE 1024
struct testNSSData {
const char * hostname ;
const char * const * ipAddr ;
int af ;
} ;
static int
testGetHostByName ( const void * opaque )
{
const struct testNSSData * data = opaque ;
const bool existent = data - > hostname & & data - > ipAddr & & data - > ipAddr [ 0 ] ;
struct hostent resolved ;
char buf [ BUF_SIZE ] = { 0 } ;
char * * addrList ;
int rv , tmp_errno = 0 , tmp_herrno = 0 ;
2019-07-10 15:30:11 +03:00
size_t i = 0 ;
2016-02-15 16:02:05 +03:00
memset ( & resolved , 0 , sizeof ( resolved ) ) ;
2016-12-04 13:56:44 +03:00
rv = NSS_NAME ( gethostbyname2 ) ( data - > hostname ,
data - > af ,
& resolved ,
buf , sizeof ( buf ) ,
& tmp_errno ,
& tmp_herrno ) ;
2016-02-15 16:02:05 +03:00
if ( rv = = NSS_STATUS_TRYAGAIN | |
rv = = NSS_STATUS_UNAVAIL | |
rv = = NSS_STATUS_RETURN ) {
/* Resolving failed in unexpected fashion. */
virReportError ( VIR_ERR_INTERNAL_ERROR ,
" Resolving of %s failed due to internal error " ,
data - > hostname ) ;
2019-11-12 23:46:29 +03:00
return - 1 ;
2016-02-15 16:02:05 +03:00
} else if ( rv = = NSS_STATUS_NOTFOUND ) {
/* Resolving failed. Should it? */
if ( ! existent )
2019-11-12 23:46:29 +03:00
return 0 ;
2016-02-15 16:02:05 +03:00
else
virReportError ( VIR_ERR_INTERNAL_ERROR ,
" Resolving of %s failed " ,
data - > hostname ) ;
2019-11-12 23:46:29 +03:00
return - 1 ;
2016-02-15 16:02:05 +03:00
}
/* Resolving succeeded. Should it? */
if ( ! existent ) {
virReportError ( VIR_ERR_INTERNAL_ERROR ,
" Resolving of %s succeeded but was expected to fail " ,
data - > hostname ) ;
2019-11-12 23:46:29 +03:00
return - 1 ;
2016-02-15 16:02:05 +03:00
}
/* Now lets see if resolved address match our expectations. */
if ( ! resolved . h_name ) {
virReportError ( VIR_ERR_INTERNAL_ERROR , " %s " ,
" resolved.h_name empty " ) ;
2019-11-12 23:46:29 +03:00
return - 1 ;
2016-02-15 16:02:05 +03:00
}
if ( data - > af ! = AF_UNSPEC & &
resolved . h_addrtype ! = data - > af ) {
virReportError ( VIR_ERR_INTERNAL_ERROR ,
" Expected AF_INET (%d) got %d " ,
data - > af , resolved . h_addrtype ) ;
2019-11-12 23:46:29 +03:00
return - 1 ;
2016-02-15 16:02:05 +03:00
}
if ( ( resolved . h_addrtype = = AF_INET & & resolved . h_length ! = 4 ) | |
( resolved . h_addrtype = = AF_INET6 & & resolved . h_length ! = 16 ) ) {
/* IPv4 addresses are encoded into 4 bytes */
virReportError ( VIR_ERR_INTERNAL_ERROR ,
" Expected %d bytes long address, got %d " ,
resolved . h_addrtype = = AF_INET ? 4 : 16 ,
resolved . h_length ) ;
2019-11-12 23:46:29 +03:00
return - 1 ;
2016-02-15 16:02:05 +03:00
}
if ( ! resolved . h_addr_list ) {
virReportError ( VIR_ERR_INTERNAL_ERROR , " %s " ,
" resolved.h_addr_list empty " ) ;
2019-11-12 23:46:29 +03:00
return - 1 ;
2016-02-15 16:02:05 +03:00
}
addrList = resolved . h_addr_list ;
2019-07-10 15:30:11 +03:00
i = 0 ;
2016-02-15 16:02:05 +03:00
while ( * addrList ) {
virSocketAddr sa ;
char * ipAddr ;
2016-03-18 18:34:10 +03:00
void * address = * addrList ;
2016-02-15 16:02:05 +03:00
memset ( & sa , 0 , sizeof ( sa ) ) ;
if ( resolved . h_addrtype = = AF_INET ) {
2016-03-18 18:34:10 +03:00
virSocketAddrSetIPv4AddrNetOrder ( & sa , * ( ( uint32_t * ) address ) ) ;
2016-02-15 16:02:05 +03:00
} else {
2016-03-18 18:34:10 +03:00
virSocketAddrSetIPv6AddrNetOrder ( & sa , address ) ;
2016-02-15 16:02:05 +03:00
}
if ( ! ( ipAddr = virSocketAddrFormat ( & sa ) ) ) {
/* error reported by helper */
2019-11-12 23:46:29 +03:00
return - 1 ;
2016-02-15 16:02:05 +03:00
}
2019-07-10 15:30:11 +03:00
if ( STRNEQ_NULLABLE ( data - > ipAddr [ i ] , ipAddr ) ) {
2016-02-15 16:02:05 +03:00
virReportError ( VIR_ERR_INTERNAL_ERROR ,
2019-07-10 15:30:11 +03:00
" Unexpected address %s, expecting %s " ,
ipAddr , NULLSTR ( data - > ipAddr [ i ] ) ) ;
2016-02-15 16:02:05 +03:00
VIR_FREE ( ipAddr ) ;
2019-11-12 23:46:29 +03:00
return - 1 ;
2016-02-15 16:02:05 +03:00
}
VIR_FREE ( ipAddr ) ;
addrList + + ;
i + + ;
}
2019-07-10 15:30:11 +03:00
if ( data - > ipAddr [ i ] ) {
2016-02-15 16:02:05 +03:00
virReportError ( VIR_ERR_INTERNAL_ERROR ,
2019-07-10 15:30:11 +03:00
" Expected %s address, got NULL " ,
data - > ipAddr [ i ] ) ;
2019-11-12 23:46:29 +03:00
return - 1 ;
2016-02-15 16:02:05 +03:00
}
2019-11-12 23:46:29 +03:00
return 0 ;
2016-02-15 16:02:05 +03:00
}
static int
mymain ( void )
{
int ret = 0 ;
2017-11-03 15:09:47 +03:00
# define DO_TEST(name, family, ...) \
do { \
const char * addr [ ] = { __VA_ARGS__ , NULL } ; \
struct testNSSData data = { \
. hostname = name , . ipAddr = addr , . af = family , \
} ; \
if ( virTestRun ( name , testGetHostByName , & data ) < 0 ) \
ret = - 1 ; \
2016-02-15 16:02:05 +03:00
} while ( 0 )
2016-11-29 15:48:53 +03:00
# if !defined(LIBVIRT_NSS_GUEST)
2016-02-15 16:02:05 +03:00
DO_TEST ( " fedora " , AF_INET , " 192.168.122.197 " , " 192.168.122.198 " , " 192.168.122.199 " ) ;
DO_TEST ( " gentoo " , AF_INET , " 192.168.122.254 " ) ;
DO_TEST ( " gentoo " , AF_INET6 , " 2001:1234:dead:beef::2 " ) ;
DO_TEST ( " gentoo " , AF_UNSPEC , " 192.168.122.254 " ) ;
DO_TEST ( " non-existent " , AF_UNSPEC , NULL ) ;
2016-11-29 15:48:53 +03:00
# else /* defined(LIBVIRT_NSS_GUEST) */
DO_TEST ( " debian " , AF_INET , " 192.168.122.2 " ) ;
DO_TEST ( " suse " , AF_INET , " 192.168.122.3 " ) ;
# endif /* defined(LIBVIRT_NSS_GUEST) */
2016-02-15 16:02:05 +03:00
return ret = = 0 ? EXIT_SUCCESS : EXIT_FAILURE ;
}
2019-08-21 19:13:16 +03:00
VIR_TEST_MAIN_PRELOAD ( mymain , VIR_TEST_MOCK ( " nss " ) )
2016-02-15 16:02:05 +03:00
# else
int
main ( void )
{
return EXIT_AM_SKIP ;
}
# endif