On Fri, Jun 12, 2020 at 06:58:15PM +0300, Niko Tyni wrote: > I have not had the tuits yet for looking at IO::Socket::IP properly. > It seems to me that it could look at the address and pass AI_NUMERICHOST > to getaddrinfo(3) if it looks like an IPv4 address. I guess matching > against qr/^\d+\.\d+\.\d+\.\d+$/ would suffice.
Here's a first try at such a patch. Something like this might be a better fix for #962047 in libio-socket-ip-perl than the test suite change in 0.39-2. I've only tested that libio-socket-ip-perl and libtest-tcp-perl build and work with this. -- Niko Tyni nt...@debian.org
>From cedf885dda8bdb0e1af3a8ab5675a347a5d7c22f Mon Sep 17 00:00:00 2001 From: Niko Tyni <nt...@debian.org> Date: Mon, 15 Jun 2020 19:31:31 +0100 Subject: [PATCH] Call getaddrinfo(3) with AI_NUMERICHOST for IPv4 numeric addresses AI_ADDRCONFIG can be a bad default for systems with a dual protocol loopback device but just IPv6 connectivity. In such a case, getaddrinfo(3) on 127.0.0.1 or 0.0.0.0 will fail with EAI_ADDRFAMILY even though the loopback device is able to handle them. Bug: https://rt.cpan.org/Ticket/Display.html?id=132760 Bug-Debian: https://bugs.debian.org/962047 Bug-Debian: https://bugs.debian.org/962318 --- lib/IO/Socket/IP.pm | 34 +++++++++++++++++++++++++++------- 1 file changed, 27 insertions(+), 7 deletions(-) diff --git a/lib/IO/Socket/IP.pm b/lib/IO/Socket/IP.pm index 4334a66..64f26f6 100755 --- a/lib/IO/Socket/IP.pm +++ b/lib/IO/Socket/IP.pm @@ -30,6 +30,7 @@ use Socket 1.97 qw( ); my $AF_INET6 = eval { Socket::AF_INET6() }; # may not be defined my $AI_ADDRCONFIG = eval { Socket::AI_ADDRCONFIG() } || 0; +my $AI_NUMERICHOST = eval { Socket::AI_NUMERICHOST() } || 0; use POSIX qw( dup2 ); use Errno qw( EINVAL EINPROGRESS EISCONN ENOTCONN ETIMEDOUT EWOULDBLOCK EOPNOTSUPP ); @@ -409,6 +410,8 @@ sub _io_socket_ip__configure my ( $arg ) = @_; my %hints; + my $localflags; + my $peerflags; my @localinfos; my @peerinfos; @@ -419,12 +422,23 @@ sub _io_socket_ip__configure } if( defined $arg->{GetAddrInfoFlags} ) { - $hints{flags} = $arg->{GetAddrInfoFlags}; + $peerflags = $arg->{GetAddrInfoFlags}; + } + elsif (defined $arg->{PeerHost} and $arg->{PeerHost} =~ /^\d+\.\d+\.\d+\.\d+$/) { + $peerflags = $AI_NUMERICHOST; + } + else { + $peerflags = $AI_ADDRCONFIG; + } + + if( defined $arg->{GetAddrInfoFlags} ) { + $localflags = $arg->{GetAddrInfoFlags}; + } + elsif (defined $arg->{LocalHost} and $arg->{LocalHost} =~ /^\d+\.\d+\.\d+\.\d+$/) { + $localflags = $AI_NUMERICHOST; } - elsif (defined $arg->{PeerHost} and $arg->{PeerHost} =~ /^\d+\.\d+\.\d+\.\d+$/) { - $hints{flags} = $AI_NUMERICHOST; else { - $hints{flags} = $AI_ADDRCONFIG; + $localflags = $AI_ADDRCONFIG; } if( defined( my $family = $arg->{Family} ) ) { @@ -481,6 +495,7 @@ sub _io_socket_ip__configure my $fallback_port = $1; my %localhints = %hints; + $localhints{flags} = $localflags; $localhints{flags} |= AI_PASSIVE; ( my $err, @localinfos ) = getaddrinfo( $host, $service, \%localhints ); @@ -509,10 +524,13 @@ sub _io_socket_ip__configure defined $service and $service =~ s/\((\d+)\)$// and my $fallback_port = $1; - ( my $err, @peerinfos ) = getaddrinfo( $host, $service, \%hints ); + my %peerhints = %hints; + $peerhints{flags} = $peerflags; + + ( my $err, @peerinfos ) = getaddrinfo( $host, $service, \%peerhints ); if( $err and defined $fallback_port ) { - ( $err, @peerinfos ) = getaddrinfo( $host, $fallback_port, \%hints ); + ( $err, @peerinfos ) = getaddrinfo( $host, $fallback_port, \%peerhints ); } if( $err ) { @@ -592,7 +610,9 @@ sub _io_socket_ip__configure # If there wasn't, use getaddrinfo()'s AI_ADDRCONFIG side-effect to guess a # suitable family first. else { - ( my $err, @infos ) = getaddrinfo( "", "0", \%hints ); + my %guesshints = %hints; + $guesshints{flags} = $AI_ADDRCONFIG; + ( my $err, @infos ) = getaddrinfo( "", "0", \%guesshints ); if( $err ) { $@ = "$err"; $! = EINVAL; -- 2.26.2