From 850005499bd92c5b9b0027f944fcd33633c8db46 Mon Sep 17 00:00:00 2001 From: Noriko Hosoi Date: Mar 27 2012 23:15:50 +0000 Subject: Trac Ticket #46 - (take 3) setup-ds-admin.pl does not like ipv6 only hostnames https://fedorahosted.org/389/ticket/46 Fix Description: Perl functions (gethostbyname, gethostbyaddr) do not support IPv6 addresses. This patch addes the IPv6 support if an IPv6 enabled socket module is available. If Socket::addrinfo subsystem is found, use getaddrinfo and getnameinfo from the module. If not and if Socket6 module is available, the module is used. If both are not found on the system, the existing non-IPv6 methods are called. --- diff --git a/ldap/admin/src/scripts/DSUtil.pm.in b/ldap/admin/src/scripts/DSUtil.pm.in index 9e4b322..a3a8abf 100644 --- a/ldap/admin/src/scripts/DSUtil.pm.in +++ b/ldap/admin/src/scripts/DSUtil.pm.in @@ -59,7 +59,16 @@ require Exporter; use strict; use Socket; -use Socket6 qw( getaddrinfo getnameinfo unpack_sockaddr_in6 ); +BEGIN { + if (eval {require Socket::addrinfo; 1}) { + import Socket qw (:addrinfo inet_ntoa + unpack_sockaddr_in unpack_sockaddr_in6 + AF_INET INADDR_ANY + PF_INET SO_REUSEADDR SOCK_STREAM SOL_SOCKET); + } elsif (eval {require Socket6; 1}) { + import Socket6 qw (getaddrinfo getnameinfo unpack_sockaddr_in6); + } +} use NetAddr::IP::Util qw( ipv6_n2x ); use File::Temp qw(tempfile tempdir); @@ -210,35 +219,87 @@ sub checkHostname { } # see if we can resolve the hostname (IPv6 supported) - my @aires = getaddrinfo( $hn, "ldap", AF_UNSPEC, SOCK_STREAM ); - if (scalar(@aires) < 5) { - return $res->getText('warning_no_such_hostname', $hn); - } my $found = 0; my @hostip = (); - my $ailen = scalar(@aires); - while ( $ailen >= 5 ) { - debug(1, "found for hostname $hn\n"); - my ($family, $socktype, $proto, $saddr, $canonname, @aires) = @aires; - $ailen = scalar(@aires); - my $ip; - if ($family == AF_INET) { - my ( $port, $ipaddr ) = unpack_sockaddr_in( $saddr ); - $ip = inet_ntoa($ipaddr); - } else { - my ( $port, $ipaddr ) = unpack_sockaddr_in6( $saddr ); - $ip = ipv6_n2x($ipaddr); + if (eval {require Socket::addrinfo; 1}) { + my %hints = (socktype => SOCK_STREAM); + my ($err, @aires) = getaddrinfo($hn, "ldap", \%hints); + if ($err) { + return $res->getText('warning_no_such_hostname', $hn); + } + while (my $ai = shift @aires) { + debug(1, "found for hostname $hn\n"); + my $ip; + if ($ai->{family} == AF_INET) { + my ( $port, $ipaddr ) = unpack_sockaddr_in( $ai->{addr} ); + $ip = inet_ntoa($ipaddr); + } else { + my ( $port, $ipaddr ) = unpack_sockaddr_in6( $ai->{addr} ); + $ip = ipv6_n2x($ipaddr); + } + debug(1, "ipaddr=", $ip, "\n"); + # see if reverse resolution works + my ($err, $hn2, $service) = getnameinfo($ai->{addr}); + if (!$err) { + push @hostip, [$hn2, $ip]; + if (lc($hn) eq lc($hn2)) { + $found = 1; + last; + } + } + } + } elsif (eval {require Socket6; 1}) { + my @aires = getaddrinfo($hn, "ldap", AF_UNSPEC, SOCK_STREAM); + if (scalar(@aires) < 5) { + return $res->getText('warning_no_such_hostname', $hn); + } + my $ailen = scalar(@aires); + while ($ailen >= 5) { + debug(1, "found for hostname $hn\n"); + my ($family, $socktype, $proto, $saddr, $canonname, @aires) = @aires; + $ailen = scalar(@aires); + my $ip; + if ($family == AF_INET) { + my ($port, $ipaddr) = unpack_sockaddr_in($saddr); + $ip = inet_ntoa($ipaddr); + } else { + my ($port, $ipaddr) = unpack_sockaddr_in6($saddr); + $ip = ipv6_n2x($ipaddr); + } + debug(1, "ipaddr=", $ip, "\n"); + # see if reverse resolution works + my ($hn2, $service) = getnameinfo($saddr); + if (!$hn2) { + push @hostip, [$hn2, $ip]; + if (lc($hn) eq lc($hn2)) { + $found = 1; + } + } } - debug(1, "ipaddr=", $ip, "\n"); - # see if reverse resolution works - my ( $hn2, $service ) = getnameinfo( $saddr ); - if (!$hn2) { + } else { + # see if we can resolve the hostname + my ($name, $aliases, $addrtype, $length, @addrs) = gethostbyname($hn); + if (!$name) { + if ($res) { + return $res->getText('warning_no_such_hostname', $hn); + } else { + return "Warning: could not resolve hostname $hn\n"; + } + } + debug(1, "found for hostname $hn: name=$name\n"); + debug(1, "aliases=$aliases\n"); + debug(1, "addrtype=$addrtype\n"); + # see if reverse resolution works + foreach my $ii (@addrs) { + my $hn2 = gethostbyaddr($ii, $addrtype); + my $ip = join('.', unpack('C4', $ii)); + debug(1, "\thost=$hn2 ip=$ip\n"); push @hostip, [$hn2, $ip]; if (lc($hn) eq lc($hn2)) { $found = 1; last; - } - } + } + } } if (!$found) {