You are viewing a plain text version of this content. The canonical link for it is here.
Posted to common-commits@hadoop.apache.org by si...@apache.org on 2026/10/27 20:47:14 UTC

(hadoop) 02/06: HADOOP-19960. Support IPv6 reverse DNS names in DNS.reverseDns (#8807)

This is an automated email from the ASF dual-hosted git repository.

smengcl pushed a commit to branch branch-3.4
in repository https://gitbox.apache.org/repos/asf/hadoop.git

commit fabc704ccd5b50a981e0196aad9cc540d5bf514a
Author: Siyao Meng <50...@users.noreply.github.com>
AuthorDate: Sun Oct 11 15:20:24 2026 -0700

    HADOOP-19960. Support IPv6 reverse DNS names in DNS.reverseDns (#8807)
    
    Co-authored-by: Claude Opus 5.5 <no...@anthropic.com>
    (cherry picked from commit 3aeb542f5df374444ce47caa3a8f73eb3743efe6)
---
 .../src/main/java/org/apache/hadoop/net/DNS.java   | 34 +++++++++++++++----
 .../test/java/org/apache/hadoop/net/TestDNS.java   | 38 ++++++++++++++++++++++
 2 files changed, 65 insertions(+), 7 deletions(-)

diff --git a/hadoop-common-project/hadoop-common/src/main/java/org/apache/hadoop/net/DNS.java b/hadoop-common-project/hadoop-common/src/main/java/org/apache/hadoop/net/DNS.java
index 53bb44fb2e9..b8ad1e62fdb 100644
--- a/hadoop-common-project/hadoop-common/src/main/java/org/apache/hadoop/net/DNS.java
+++ b/hadoop-common-project/hadoop-common/src/main/java/org/apache/hadoop/net/DNS.java
@@ -25,6 +25,7 @@
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
+import java.net.Inet6Address;
 import java.net.InetAddress;
 import java.net.NetworkInterface;
 import java.net.SocketException;
@@ -75,13 +76,7 @@ public class DNS {
    */
   public static String reverseDns(InetAddress hostIp, @Nullable String ns)
     throws NamingException {
-    //
-    // Builds the reverse IP lookup form
-    // This is formed by reversing the IP numbers and appending in-addr.arpa
-    //
-    String[] parts = hostIp.getHostAddress().split("\\.");
-    String reverseIP = parts[3] + "." + parts[2] + "." + parts[1] + "."
-      + parts[0] + ".in-addr.arpa";
+    String reverseIP = getReverseDnsName(hostIp);
 
     DirContext ictx = new InitialDirContext();
     Attributes attribute;
@@ -102,6 +97,31 @@ public static String reverseDns(InetAddress hostIp, @Nullable String ns)
     return hostname;
   }
 
+  /**
+   * Builds the reverse IP lookup form of an address.
+   *
+   * @param hostIp The address to build the reverse lookup name for
+   * @return The in-addr.arpa name for an IPv4 address, or the ip6.arpa name
+   *         (RFC 3596) for an IPv6 address
+   */
+  @VisibleForTesting
+  static String getReverseDnsName(InetAddress hostIp) {
+    if (hostIp instanceof Inet6Address) {
+      // This is formed by reversing the 32 nibbles of the address and appending ip6.arpa.
+      // The scope id is not part of the name.
+      StringBuilder reverseIP = new StringBuilder();
+      byte[] addr = hostIp.getAddress();
+      for (int i = addr.length - 1; i >= 0; i--) {
+        reverseIP.append(Character.forDigit(addr[i] & 0xf, 16)).append('.')
+            .append(Character.forDigit((addr[i] >> 4) & 0xf, 16)).append('.');
+      }
+      return reverseIP.append("ip6.arpa").toString();
+    }
+    // This is formed by reversing the IP numbers and appending in-addr.arpa
+    String[] parts = hostIp.getHostAddress().split("\\.");
+    return parts[3] + "." + parts[2] + "." + parts[1] + "." + parts[0] + ".in-addr.arpa";
+  }
+
   /**
    * @return NetworkInterface for the given subinterface name (eg eth0:0)
    *    or null if no interface with the given name can be found  
diff --git a/hadoop-common-project/hadoop-common/src/test/java/org/apache/hadoop/net/TestDNS.java b/hadoop-common-project/hadoop-common/src/test/java/org/apache/hadoop/net/TestDNS.java
index d33545ab6fe..fd1383129ad 100644
--- a/hadoop-common-project/hadoop-common/src/test/java/org/apache/hadoop/net/TestDNS.java
+++ b/hadoop-common-project/hadoop-common/src/test/java/org/apache/hadoop/net/TestDNS.java
@@ -18,6 +18,7 @@
 
 package org.apache.hadoop.net;
 
+import java.net.Inet6Address;
 import java.net.NetworkInterface;
 import java.net.SocketException;
 import java.net.UnknownHostException;
@@ -25,6 +26,7 @@
 
 import javax.naming.CommunicationException;
 import javax.naming.NameNotFoundException;
+import javax.naming.NamingException;
 import javax.naming.ServiceUnavailableException;
 
 import org.apache.hadoop.util.Time;
@@ -37,6 +39,8 @@
 
 import static org.apache.hadoop.test.PlatformAssumptions.assumeNotWindows;
 import static org.junit.Assert.*;
+import static org.assertj.core.api.Assertions.assertThat;
+import static org.assertj.core.api.Assertions.assertThatThrownBy;
 
 /**
  * Test host name and IP resolution and caching.
@@ -182,6 +186,40 @@ public void testRDNS() throws Exception {
     }
   }
 
+  /**
+   * Test the reverse lookup names built for IPv4 and IPv6 addresses.
+   */
+  @Test
+  public void testReverseDnsName() throws Exception {
+    assertThat(DNS.getReverseDnsName(InetAddress.getByName("192.0.2.129")))
+        .isEqualTo("129.2.0.192.in-addr.arpa");
+    // The example from RFC 3596 section 2.5
+    assertThat(DNS.getReverseDnsName(InetAddress.getByName("4321:0:1:2:3:4:567:89ab")))
+        .isEqualTo("b.a.9.8.7.6.5.0.4.0.0.0.3.0.0.0.2.0.0.0.1.0.0.0.0.0.0.0.1.2.3.4.ip6.arpa");
+    assertThat(DNS.getReverseDnsName(InetAddress.getByName("2001:db8::1")))
+        .isEqualTo("1.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.8.b.d.0.1.0.0.2.ip6.arpa");
+    assertThat(DNS.getReverseDnsName(InetAddress.getByName("::1")))
+        .isEqualTo("1.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.ip6.arpa");
+    // The JDK resolves an IPv4-mapped address to an Inet4Address
+    assertThat(DNS.getReverseDnsName(InetAddress.getByName("::ffff:192.0.2.129")))
+        .isEqualTo("129.2.0.192.in-addr.arpa");
+    // The scope id is not part of the name
+    byte[] linkLocal = InetAddress.getByName("fe80::1").getAddress();
+    assertThat(DNS.getReverseDnsName(Inet6Address.getByAddress(null, linkLocal, 5)))
+        .isEqualTo("1.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.8.e.f.ip6.arpa");
+  }
+
+  /**
+   * Test that the reverse lookup of an IPv6 address fails with a
+   * NamingException, which DNS#getHosts handles, when no DNS server answers.
+   */
+  @Test
+  public void testReverseDnsIPv6WithInvalidServer() throws Exception {
+    InetAddress address = InetAddress.getByName("2001:db8::1");
+    assertThatThrownBy(() -> DNS.reverseDns(address, INVALID_DNS_SERVER))
+        .isInstanceOf(NamingException.class);
+  }
+
   /**
    * Test that when using an invalid DNS server with hosts file fallback,
    * we are able to get the hostname from the hosts file.


---------------------------------------------------------------------
To unsubscribe, e-mail: common-commits-unsubscribe@hadoop.apache.org
For additional commands, e-mail: common-commits-help@hadoop.apache.org