|
Packit |
3de91b |
use strict;
|
|
Packit |
3de91b |
use warnings;
|
|
Packit |
3de91b |
use Test::More tests => 31;
|
|
Packit |
3de91b |
|
|
Packit |
3de91b |
use Socket qw(:addrinfo AF_INET SOCK_STREAM IPPROTO_TCP unpack_sockaddr_in inet_aton);
|
|
Packit |
3de91b |
|
|
Packit |
3de91b |
my ( $err, @res );
|
|
Packit |
3de91b |
|
|
Packit |
3de91b |
( $err, @res ) = getaddrinfo( "127.0.0.1", "80", { socktype => SOCK_STREAM } );
|
|
Packit |
3de91b |
cmp_ok( $err, "==", 0, '$err == 0 for host=127.0.0.1/service=80/socktype=STREAM' );
|
|
Packit |
3de91b |
cmp_ok( $err, "eq", "", '$err eq "" for host=127.0.0.1/service=80/socktype=STREAM' );
|
|
Packit |
3de91b |
is( scalar @res, 1,
|
|
Packit |
3de91b |
'@res has 1 result' );
|
|
Packit |
3de91b |
|
|
Packit |
3de91b |
is( $res[0]->{family}, AF_INET,
|
|
Packit |
3de91b |
'$res[0] family is AF_INET' );
|
|
Packit |
3de91b |
is( $res[0]->{socktype}, SOCK_STREAM,
|
|
Packit |
3de91b |
'$res[0] socktype is SOCK_STREAM' );
|
|
Packit |
3de91b |
ok( $res[0]->{protocol} == 0 || $res[0]->{protocol} == IPPROTO_TCP,
|
|
Packit |
3de91b |
'$res[0] protocol is 0 or IPPROTO_TCP' );
|
|
Packit |
3de91b |
ok( defined $res[0]->{addr},
|
|
Packit |
3de91b |
'$res[0] addr is defined' );
|
|
Packit |
3de91b |
if (length $res[0]->{addr}) {
|
|
Packit |
3de91b |
is_deeply( [ unpack_sockaddr_in $res[0]->{addr} ],
|
|
Packit |
3de91b |
[ 80, inet_aton( "127.0.0.1" ) ],
|
|
Packit |
3de91b |
'$res[0] addr is {"127.0.0.1", 80}' );
|
|
Packit |
3de91b |
} else {
|
|
Packit |
3de91b |
fail( '$res[0] addr is empty: check $socksizetype' );
|
|
Packit |
3de91b |
}
|
|
Packit |
3de91b |
|
|
Packit |
3de91b |
# Check actual IV integers work just as well as PV strings
|
|
Packit |
3de91b |
( $err, @res ) = getaddrinfo( "127.0.0.1", 80, { socktype => SOCK_STREAM } );
|
|
Packit |
3de91b |
cmp_ok( $err, "==", 0, '$err == 0 for host=127.0.0.1/service=80/socktype=STREAM' );
|
|
Packit |
3de91b |
is_deeply( [ unpack_sockaddr_in $res[0]->{addr} ],
|
|
Packit |
3de91b |
[ 80, inet_aton( "127.0.0.1" ) ],
|
|
Packit |
3de91b |
'$res[0] addr is {"127.0.0.1", 80}' );
|
|
Packit |
3de91b |
|
|
Packit |
3de91b |
( $err, @res ) = getaddrinfo( "127.0.0.1", "" );
|
|
Packit |
3de91b |
cmp_ok( $err, "==", 0, '$err == 0 for host=127.0.0.1' );
|
|
Packit |
3de91b |
# Might get more than one; e.g. different socktypes
|
|
Packit |
3de91b |
ok( scalar @res > 0, '@res has results' );
|
|
Packit |
3de91b |
|
|
Packit |
3de91b |
( $err, @res ) = getaddrinfo( "127.0.0.1", undef );
|
|
Packit |
3de91b |
cmp_ok( $err, "==", 0, '$err == 0 for host=127.0.0.1/service=undef' );
|
|
Packit |
3de91b |
|
|
Packit |
3de91b |
# Test GETMAGIC
|
|
Packit |
3de91b |
{
|
|
Packit |
3de91b |
"127.0.0.1" =~ /(.+)/;
|
|
Packit |
3de91b |
( $err, @res ) = getaddrinfo($1, undef);
|
|
Packit |
3de91b |
cmp_ok( $err, "==", 0, '$err == 0 for host=$1' );
|
|
Packit |
3de91b |
ok( scalar @res > 0, '@res has results' );
|
|
Packit |
3de91b |
is( (unpack_sockaddr_in $res[0]->{addr})[1],
|
|
Packit |
3de91b |
inet_aton( "127.0.0.1" ),
|
|
Packit |
3de91b |
'$res[0] addr is {"127.0.0.1", ??}' );
|
|
Packit |
3de91b |
}
|
|
Packit |
3de91b |
|
|
Packit |
3de91b |
( $err, @res ) = getaddrinfo( "", "80", { family => AF_INET, socktype => SOCK_STREAM, protocol => IPPROTO_TCP } );
|
|
Packit |
3de91b |
cmp_ok( $err, "==", 0, '$err == 0 for service=80/family=AF_INET/socktype=STREAM/protocol=IPPROTO_TCP' );
|
|
Packit |
3de91b |
is( scalar @res, 1, '@res has 1 result' );
|
|
Packit |
3de91b |
|
|
Packit |
3de91b |
# Just pick the first one
|
|
Packit |
3de91b |
is( $res[0]->{family}, AF_INET,
|
|
Packit |
3de91b |
'$res[0] family is AF_INET' );
|
|
Packit |
3de91b |
is( $res[0]->{socktype}, SOCK_STREAM,
|
|
Packit |
3de91b |
'$res[0] socktype is SOCK_STREAM' );
|
|
Packit |
3de91b |
ok( $res[0]->{protocol} == 0 || $res[0]->{protocol} == IPPROTO_TCP,
|
|
Packit |
3de91b |
'$res[0] protocol is 0 or IPPROTO_TCP' );
|
|
Packit |
3de91b |
|
|
Packit |
3de91b |
# Now some tests of a few well-known internet hosts
|
|
Packit |
3de91b |
my $goodhost = "cpan.perl.org";
|
|
Packit |
3de91b |
|
|
Packit |
3de91b |
SKIP: {
|
|
Packit |
3de91b |
skip "Resolver has no answer for $goodhost", 2 unless gethostbyname( $goodhost );
|
|
Packit |
3de91b |
|
|
Packit |
3de91b |
( $err, @res ) = getaddrinfo( "cpan.perl.org", "ftp", { socktype => SOCK_STREAM } );
|
|
Packit |
3de91b |
cmp_ok( $err, "==", 0, '$err == 0 for host=cpan.perl.org/service=ftp/socktype=STREAM' );
|
|
Packit |
3de91b |
# Might get more than one; e.g. different families
|
|
Packit |
3de91b |
ok( scalar @res > 0, '@res has results' );
|
|
Packit |
3de91b |
}
|
|
Packit |
3de91b |
|
|
Packit |
3de91b |
# Now something I hope doesn't exist - we put it in a known-missing TLD
|
|
Packit |
3de91b |
my $missinghost = "TbK4jM2M0OS.lm57DWIyu4i";
|
|
Packit |
3de91b |
|
|
Packit |
3de91b |
# Some CPAN testing machines seem to have wildcard DNS servers that reply to
|
|
Packit |
3de91b |
# any request. We'd better check for them
|
|
Packit |
3de91b |
|
|
Packit |
3de91b |
SKIP: {
|
|
Packit |
3de91b |
skip "Resolver has an answer for $missinghost", 1 if gethostbyname( $missinghost );
|
|
Packit |
3de91b |
|
|
Packit |
3de91b |
# Some OSes return $err == 0 but no results
|
|
Packit |
3de91b |
( $err, @res ) = getaddrinfo( $missinghost, "ftp", { socktype => SOCK_STREAM } );
|
|
Packit |
3de91b |
ok( $err != 0 || ( $err == 0 && @res == 0 ),
|
|
Packit |
3de91b |
'$err != 0 or @res == 0 for host=TbK4jM2M0OS.lm57DWIyu4i/service=ftp/socktype=SOCK_STREAM' );
|
|
Packit |
3de91b |
if( @res ) {
|
|
Packit |
3de91b |
# Diagnostic that might help
|
|
Packit |
3de91b |
while( my $r = shift @res ) {
|
|
Packit |
3de91b |
diag( "family=$r->{family} socktype=$r->{socktype} protocol=$r->{protocol} addr=[" . length( $r->{addr} ) . " bytes]" );
|
|
Packit |
3de91b |
diag( " addr=" . join( ", ", map { sprintf '0x%02x', ord $_ } split m//, $r->{addr} ) );
|
|
Packit |
3de91b |
}
|
|
Packit |
3de91b |
}
|
|
Packit |
3de91b |
}
|
|
Packit |
3de91b |
|
|
Packit |
3de91b |
# Numeric addresses with AI_NUMERICHOST should pass (RT95758)
|
|
Packit |
3de91b |
AI_NUMERICHOST: {
|
|
Packit |
3de91b |
# Here we need a port that is open to the world. Not all places have all
|
|
Packit |
3de91b |
# the ports. For example Solaris by default doesn't have http/80 in
|
|
Packit |
3de91b |
# /etc/services, and that would fail. Let's try a couple of commonly open
|
|
Packit |
3de91b |
# ports, and hope one of them will succeed. Conversely this means that
|
|
Packit |
3de91b |
# sometimes this will fail.
|
|
Packit |
3de91b |
#
|
|
Packit |
3de91b |
# An alternative method would be to manually parse /etc/services and look
|
|
Packit |
3de91b |
# for enabled services but that's kind of yuck, too.
|
|
Packit |
3de91b |
my @port = (80, 7, 22, 25, 88, 123, 110, 389, 443, 445, 873, 2049, 3306);
|
|
Packit |
3de91b |
foreach my $port ( @port ) {
|
|
Packit |
3de91b |
( $err, @res ) = getaddrinfo( "127.0.0.1", $port, { flags => AI_NUMERICHOST, socktype => SOCK_STREAM } );
|
|
Packit |
3de91b |
if( $err == 0 ) {
|
|
Packit |
3de91b |
ok( $err == 0, "\$err == 0 for 127.0.0.1/$port/flags=AI_NUMERICHOST" );
|
|
Packit |
3de91b |
last AI_NUMERICHOST;
|
|
Packit |
3de91b |
}
|
|
Packit |
3de91b |
}
|
|
Packit |
3de91b |
fail( "$err for 127.0.0.1/$port[-1]/flags=AI_NUMERICHOST (failed for ports @port)" );
|
|
Packit |
3de91b |
}
|
|
Packit |
3de91b |
|
|
Packit |
3de91b |
# Now check that names with AI_NUMERICHOST fail
|
|
Packit |
3de91b |
|
|
Packit |
3de91b |
SKIP: {
|
|
Packit |
3de91b |
skip "Resolver has no answer for $goodhost", 1 unless gethostbyname( $goodhost );
|
|
Packit |
3de91b |
|
|
Packit |
3de91b |
( $err, @res ) = getaddrinfo( $goodhost, "ftp", { flags => AI_NUMERICHOST, socktype => SOCK_STREAM } );
|
|
Packit |
3de91b |
ok( $err != 0, "\$err != 0 for host=$goodhost/service=ftp/flags=AI_NUMERICHOST/socktype=SOCK_STREAM" );
|
|
Packit |
3de91b |
}
|
|
Packit |
3de91b |
|
|
Packit |
3de91b |
# Some sanity checking on the hints hash
|
|
Packit |
3de91b |
ok( defined eval { getaddrinfo( "127.0.0.1", "80", undef ); 1 },
|
|
Packit |
3de91b |
'getaddrinfo() with undef hints works' );
|
|
Packit |
3de91b |
ok( !defined eval { getaddrinfo( "127.0.0.1", "80", "hints" ); 1 },
|
|
Packit |
3de91b |
'getaddrinfo() with string hints dies' );
|
|
Packit |
3de91b |
ok( !defined eval { getaddrinfo( "127.0.0.1", "80", [] ); 1 },
|
|
Packit |
3de91b |
'getaddrinfo() with ARRAY hints dies' );
|
|
Packit |
3de91b |
|
|
Packit |
3de91b |
# Ensure it doesn't segfault if args are missing
|
|
Packit |
3de91b |
|
|
Packit |
3de91b |
( $err, @res ) = getaddrinfo();
|
|
Packit |
3de91b |
ok( defined $err, '$err defined for getaddrinfo()' );
|
|
Packit |
3de91b |
|
|
Packit |
3de91b |
( $err, @res ) = getaddrinfo( "127.0.0.1" );
|
|
Packit |
3de91b |
ok( defined $err, '$err defined for getaddrinfo("127.0.0.1")' );
|