浏览代码

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.
Noriko Hosoi 13 年之前
父节点
当前提交
850005499b
共有 1 个文件被更改,包括 84 次插入23 次删除
  1. 84 23
      ldap/admin/src/scripts/DSUtil.pm.in

+ 84 - 23
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) {