Uploaded image for project: 'JDK'
  1. JDK
  2. JDK-8060470

Unify and simplify the implementations of Inet{4,6}AddressImpl_getLocalHostName()

    XMLWordPrintable

Details

    • Enhancement
    • Resolution: Unresolved
    • P4
    • None
    • None
    • core-libs
    • None
    • Cause Known

    Description

      I wonder why the implementations of Inet6AddressImpl_getLocalHostName() and
      Inet4AddressImpl_getLocalHostName() are different . It seems to me
      that this is simply copy/paste error since the very first 1.4 version.
      Here's what we currently have:

      Inet4AddressImpl_getLocalHostName()

      if (gethostname(hostname, NI_MAXHOST)) {
          /* Something went wrong, maybe networking is not setup? */
          strcpy(hostname, "localhost");
      } else {
      ...
          error = getaddrinfo(hostname, NULL, &hints, &res);
      ...
          error = getnameinfo(res->ai_addr, res->ai_addrlen, hostname,
      ...
      }

      We first call gethostname(). If that succeeds we call getaddrinfo()
      with the host name returned by gethostname() and if that succeeds
      again we call getnameinfo() with the address returned by getaddrinfo()
      to get the final hostname. This is uniformly done on all Unix
      platforms.

      And here's how the corresponding IPv6 version looks like:

      Inet6AddressImpl_getLocalHostName()

          ret = gethostname(hostname, NI_MAXHOST);

      #if defined(__solaris__) && defined(AF_INET6)
      ...
          error = getaddrinfo(hostname, NULL, &hints, &res);
      ...
          error = getnameinfo(res->ai_addr, res->ai_addrlen, hostname,
      #endif

      As you can see, for the IPv6 version we only do the
      getaddrinfo()/getnameinfo() roundtrip on Solaris although there is no
      evidence that the inovolved system calls behave differently for IPv4
      and IPv6. Instead I think the IPv6 version is just a leftover of the
      very first implementation which hasn't been updated in the same way
      like its IPv4 counterpart. Notice the comment in the IPv6 version
      which says "Solaris doesn't want to give us a fully qualified domain
      name". But that holds true for the Linux version as well -
      gethostname() on Linux returns "uname -n" which is usually
      unqualified. The comment further notices that even the reverse lookup
      may not return a fully qualified name which is true because that's
      highly system and name service dependent.

      I think we can therefore safely use the same implementation for both,
      Inet4AddressImpl_getLocalHostName() and
      Inet6AddressImpl_getLocalHostName(). We should actually refactor this
      implementation into its own function to avoid differences in the
      future.

      There's also a funny punchline in this whole story: trough a bug
      introduced by the Mac OS port, the two implementations have been
      semanticall equal for a while. But then this has been changed back as
      a fix for "7166687: InetAddress.getLocalHost().getHostName() returns
      FQDN " (https://bugs.openjdk.java.net/browse/JDK-7166687 ,
      http://hg.openjdk.java.net/jdk9/dev/jdk/rev/b26c04717735). But I'm
      pretty sure that change didn't really fixed the problem described in
      the bug report (maybe just incidentally worked around). Here's why:

      getLocalHostName() is used by InetAddress.getLocalHost(), but it's
      result (i.e. the host name) is immediately converted back into an
      address (i.e. InetAddress) on which subsequently getHostName() is
      called. The result of getHostName() only depends on the available
      name services and not on the fact if getLocalHostName() returned a
      simple or a fully qualified host name. However the resolution of a
      host name to an IP-address may be different depending on whether we
      have a simple (may resolve trough /etc/hosts) or fully qualified name
      (may resolve through name service like DNS).

      The hacky way to fix issue 7166687 would be to have the corresponding
      entries in your /etc/hosts (i.e. short names for both, IPv4 and IPv6
      interfaces). The right way to handle it would be to actually expect
      both, simple and full qualified host names as return values from
      InetAddress.getHostName().

      Notice the InetAddress.getLocalHost() isn't guaranteed to not return
      the loopback address. If you have configured your system such that
      /etc/hosts associates your host name with the loopback device and
      /etc/resolve.conf in such a way to first query /etc/hosts before doing
      a name service lookup (which is not unusual) than
      InetAddress.getLocalHost() will do just that - return the address of
      your loopback device!

      So to finally cut a long story short, I propose the following:

       - refactor the implementation of Inet6AddressImpl_getLocalHostName()
      and Inet4AddressImpl_getLocalHostName() into a single function which
      corresponds to the current Inet4AddressImpl_getLocalHostName()
      implementation.

       - it may be also possible to complete omit the call to getnameinfo()
      in that new implementation, because as far as I can see the
      'ai_canonname' field of the first addrinfo structure returned by
      getaddrinfo() already contains the canonical name of the host if we
      pass AI_CANONNAME as 'hints' to getaddrinfo (which we already do).

      More information can be found in the following mail threads:

      http://mail.openjdk.java.net/pipermail/net-dev/2014-October/thread.html#8721
      http://mail.openjdk.java.net/pipermail/net-dev/2013-June/thread.html#6543

      Attachments

        Issue Links

          Activity

            People

              simonis Volker Simonis
              simonis Volker Simonis
              Votes:
              0 Vote for this issue
              Watchers:
              1 Start watching this issue

              Dates

                Created:
                Updated: