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

nnag pushed a commit to branch support/1.14
in repository https://gitbox.apache.org/repos/asf/geode.git


The following commit(s) were added to refs/heads/support/1.14 by this push:
     new 8638359  GEODE-9139 SSLException in starting up a Locator 
(#6308)(#6401)
8638359 is described below

commit 863835969db3b5408764887aeeaf3b6943040c68
Author: Ernie Burghardt <[email protected]>
AuthorDate: Wed Jun 2 16:33:55 2021 -0500

    GEODE-9139 SSLException in starting up a Locator (#6308)(#6401)
    
    
                * Preserve the bind-address string specified by the user for 
cluster communications
                * Enabled use of hostnames in member identifiers if endpoint 
validation is enabled.
                * Retain the bind-address string or bind-address InetAddress in 
a HostAddress
                * HostAndPort could not be used because there will be a port 
set but there may not be a bind-address set.  That class requires a host name.
               * Simplify HostAndPort & HostAddress by creating a common 
superclass to hold their InetSocketAddress.
               * Cache the result of attempting to resolve the hostname.
               * Retain the string passed in as the hostname to avoid things 
like 127.0.0.1 being converted to localhost
               * Added comments about retention of the hostname parameter
    
    Co-authored-by: Bruce Schuchardt <[email protected]>
    
    (cherry picked from commit 55921a4d7b66a51279e71d1a665dc797fcc8ca6f)
---
 .../client/sni/ClientSNICQAcceptanceTest.java      |  18 ++--
 .../client/sni/DualServerSNIAcceptanceTest.java    |  28 +++++-
 .../client/sni/GenerateSNIKeyAndTrustStores.java   |   7 +-
 .../client/sni/dual-server-docker-compose.yml      |  70 +++++++++++++++
 .../geode-starter.gfsh => dual-server-haproxy.cfg} |  30 ++++++-
 .../sni/geode-config/locator-maeve-keystore.jks    | Bin 3529 -> 3514 bytes
 .../geode-config/server-clementine-keystore.jks    | Bin 3537 -> 3520 bytes
 .../sni/geode-config/server-dolores-keystore.jks   | Bin 3533 -> 3515 bytes
 .../geode/client/sni/geode-config/truststore.jks   | Bin 1129 -> 1129 bytes
 .../{geode-starter.gfsh => create-regions.gfsh}    |   8 +-
 .../geode/client/sni/scripts/geode-starter-2.gfsh  |  23 -----
 .../geode/client/sni/scripts/geode-starter.gfsh    |   2 +-
 .../{geode-starter.gfsh => locator-maeve.gfsh}     |   6 +-
 .../{geode-starter.gfsh => server-clementine.gfsh} |   6 +-
 .../{geode-starter.gfsh => server-dolores.gfsh}    |   6 +-
 .../StartLocatorCommandIntegrationTest.java        |   8 +-
 ...ReconnectWithClusterConfigurationDUnitTest.java |   3 +-
 .../internal/InternalLocatorIntegrationTest.java   |   8 +-
 .../internal/membership/MembershipJUnitTest.java   |   9 +-
 .../java/org/apache/geode/distributed/Locator.java |  39 +++++---
 .../apache/geode/distributed/LocatorLauncher.java  |  78 +++++++++-------
 .../internal/InternalDistributedSystem.java        |   6 +-
 .../distributed/internal/InternalLocator.java      |  66 +++++++++-----
 .../geode/distributed/internal/ServerLocator.java  |   7 +-
 .../internal/membership/adapter/ServiceConfig.java |   5 +-
 .../apache/geode/internal/DistributionLocator.java |  30 +++----
 .../admin/remote/DistributionLocatorId.java        |   7 +-
 .../apache/geode/internal/net/SocketCreator.java   |  12 ---
 .../org/apache/geode/internal/tcp/Connection.java  |   8 +-
 .../distributed/internal/InternalLocatorTest.java  |   3 +-
 .../internal/cli/commands/StartLocatorCommand.java |   9 +-
 .../internal/cli/shell/JmxOperationInvoker.java    |   3 +-
 .../locator/GMSLocatorRecoveryIntegrationTest.java |   5 +-
 .../gms/membership/GMSJoinLeaveJUnitTest.java      |   2 +-
 .../membership/api/MembershipLocatorBuilder.java   |   4 +-
 .../internal/membership/gms/GMSMemberData.java     |   2 -
 .../gms/MembershipLocatorBuilderImpl.java          |   6 +-
 .../membership/gms/locator/GMSLocator.java         |   7 +-
 .../gms/locator/MembershipLocatorImpl.java         |   8 +-
 .../membership/gms/messenger/JGroupsMessenger.java |   7 +-
 .../internal/tcpserver/HostAddress.java            |  56 ++++++++++++
 .../internal/tcpserver/HostAndPort.java            |  81 +++--------------
 .../internal/tcpserver/InetSocketWrapper.java      | 100 +++++++++++++++++++++
 .../geode/internal/cache/wan/WANTestBase.java      |   3 +-
 44 files changed, 514 insertions(+), 272 deletions(-)

diff --git 
a/geode-assembly/src/acceptanceTest/java/org/apache/geode/client/sni/ClientSNICQAcceptanceTest.java
 
b/geode-assembly/src/acceptanceTest/java/org/apache/geode/client/sni/ClientSNICQAcceptanceTest.java
index 149667f..c597f05 100644
--- 
a/geode-assembly/src/acceptanceTest/java/org/apache/geode/client/sni/ClientSNICQAcceptanceTest.java
+++ 
b/geode-assembly/src/acceptanceTest/java/org/apache/geode/client/sni/ClientSNICQAcceptanceTest.java
@@ -116,11 +116,19 @@ public class ClientSNICQAcceptanceTest {
   }
 
   @AfterClass
-  public static void afterClass() throws Exception {
-    String output =
-        docker.get().exec(options("-T"), "geode",
-            arguments("cat", "server-dolores/server-dolores.log"));
-    System.out.println("Server log file--------------------------------\n" + 
output);
+  public static void afterClass() {
+    printlog("locator-maeve");
+    printlog("server-dolores");
+  }
+
+  private static void printlog(String name) {
+    try {
+      String output =
+          docker.get().exec(options("-T"), "geode",
+              arguments("cat", name + "/" + name + ".log"));
+      System.out.println(name + " log file--------------------------------\n" 
+ output);
+    } catch (Throwable ignore) {
+    }
   }
 
   @Before
diff --git 
a/geode-assembly/src/acceptanceTest/java/org/apache/geode/client/sni/DualServerSNIAcceptanceTest.java
 
b/geode-assembly/src/acceptanceTest/java/org/apache/geode/client/sni/DualServerSNIAcceptanceTest.java
index 7b08be2..7423b95 100644
--- 
a/geode-assembly/src/acceptanceTest/java/org/apache/geode/client/sni/DualServerSNIAcceptanceTest.java
+++ 
b/geode-assembly/src/acceptanceTest/java/org/apache/geode/client/sni/DualServerSNIAcceptanceTest.java
@@ -31,6 +31,7 @@ import java.util.Properties;
 
 import com.palantir.docker.compose.DockerComposeRule;
 import org.junit.After;
+import org.junit.AfterClass;
 import org.junit.BeforeClass;
 import org.junit.ClassRule;
 import org.junit.Test;
@@ -60,7 +61,7 @@ import 
org.apache.geode.cache.client.proxy.ProxySocketFactories;
 public class DualServerSNIAcceptanceTest {
 
   private static final URL DOCKER_COMPOSE_PATH =
-      SingleServerSNIAcceptanceTest.class.getResource("docker-compose.yml");
+      
DualServerSNIAcceptanceTest.class.getResource("dual-server-docker-compose.yml");
 
   // Docker compose does not work on windows in CI. Ignore this test on windows
   // Using a RuleChain to make sure we ignore the test before the rule comes 
into play
@@ -74,8 +75,17 @@ public class DualServerSNIAcceptanceTest {
 
   @BeforeClass
   public static void beforeClass() throws Exception {
-    docker.get().exec(options("-T"), "geode",
-        arguments("gfsh", "run", 
"--file=/geode/scripts/geode-starter-2.gfsh"));
+    docker.get().exec(options("-T"), "locator-maeve",
+        arguments("gfsh", "run", "--file=/geode/scripts/locator-maeve.gfsh"));
+
+    docker.get().exec(options("-T"), "server-dolores",
+        arguments("gfsh", "run", "--file=/geode/scripts/server-dolores.gfsh"));
+
+    docker.get().exec(options("-T"), "server-clementine",
+        arguments("gfsh", "run", 
"--file=/geode/scripts/server-clementine.gfsh"));
+
+    docker.get().exec(options("-T"), "locator-maeve",
+        arguments("gfsh", "run", "--file=/geode/scripts/create-regions.gfsh"));
 
     final String trustStorePath =
         createTempFileFromResource(SingleServerSNIAcceptanceTest.class,
@@ -97,6 +107,18 @@ public class DualServerSNIAcceptanceTest {
     ensureCacheClosed();
   }
 
+  @AfterClass
+  public static void afterClass() throws Exception {
+    // if you need to capture logs for one of the processes use this pattern:
+    // try {
+    // String output =
+    // docker.get().exec(options("-T"), "locator-maeve",
+    // arguments("cat", "locator-maeve/locator-maeve.log"));
+    // System.out.println("Locator log file--------------------------------\n" 
+ output);
+    // } catch (Throwable ignore) {
+    // }
+  }
+
   @Test
   public void successfulRoutingTest() {
     verifyPutAndGet("group-dolores", "region-dolores");
diff --git 
a/geode-assembly/src/acceptanceTest/java/org/apache/geode/client/sni/GenerateSNIKeyAndTrustStores.java
 
b/geode-assembly/src/acceptanceTest/java/org/apache/geode/client/sni/GenerateSNIKeyAndTrustStores.java
index 1e5168c..b48054a 100644
--- 
a/geode-assembly/src/acceptanceTest/java/org/apache/geode/client/sni/GenerateSNIKeyAndTrustStores.java
+++ 
b/geode-assembly/src/acceptanceTest/java/org/apache/geode/client/sni/GenerateSNIKeyAndTrustStores.java
@@ -15,7 +15,6 @@
 package org.apache.geode.client.sni;
 
 import java.io.File;
-import java.net.InetAddress;
 import java.net.URL;
 
 import org.apache.geode.cache.ssl.CertStores;
@@ -51,10 +50,8 @@ public class GenerateSNIKeyAndTrustStores {
       CertificateMaterial certificate = new CertificateBuilder(365 * 100, 
"SHA256withRSA")
           .commonName(certName)
           .issuedBy(ca)
-          .sanDnsName("geode") // for inside the docker container
-          .sanDnsName("localhost") // for inside the docker container
-          .sanIpAddress(InetAddress.getByName("0.0.0.0")) // for inside the 
docker container
-          .sanDnsName(certName) // for client endpoint validation
+          .sanDnsName(certName)
+          .sanDnsName("geode")
           .generate();
 
       CertStores store = new CertStores(certName);
diff --git 
a/geode-assembly/src/acceptanceTest/resources/org/apache/geode/client/sni/dual-server-docker-compose.yml
 
b/geode-assembly/src/acceptanceTest/resources/org/apache/geode/client/sni/dual-server-docker-compose.yml
new file mode 100644
index 0000000..f22e60a
--- /dev/null
+++ 
b/geode-assembly/src/acceptanceTest/resources/org/apache/geode/client/sni/dual-server-docker-compose.yml
@@ -0,0 +1,70 @@
+#
+# Licensed to the Apache Software Foundation (ASF) under one or more
+# contributor license agreements.  See the NOTICE file distributed with
+# this work for additional information regarding copyright ownership.
+# The ASF licenses this file to You under the Apache License, Version 2.0
+# (the "License"); you may not use this file except in compliance with
+# the License.  You may obtain a copy of the License at
+#
+#      http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+version: '3.5'
+services:
+  locator-maeve:
+    container_name: 'locator-maeve'
+    image: 'geode:develop'
+    hostname: locator-maeve
+    expose:
+      - '10334'
+    entrypoint: 'sh'
+    command: '-c /geode/scripts/forever'
+    networks:
+      geode-sni-test:
+    volumes:
+      - ./geode-config:/geode/config:ro
+      - ./scripts:/geode/scripts
+  server-clementine:
+    container_name: 'server-clementine'
+    image: 'geode:develop'
+    hostname: server-clementine
+    expose:
+      - '8501'
+    entrypoint: 'sh'
+    command: '-c /geode/scripts/forever'
+    networks:
+      geode-sni-test:
+    volumes:
+      - ./geode-config:/geode/config:ro
+      - ./scripts:/geode/scripts
+  server-dolores:
+    container_name: 'server-dolores'
+    image: 'geode:develop'
+    hostname: server-dolores
+    expose:
+      - '8502'
+    entrypoint: 'sh'
+    command: '-c /geode/scripts/forever'
+    networks:
+      geode-sni-test:
+    volumes:
+      - ./geode-config:/geode/config:ro
+      - ./scripts:/geode/scripts
+  haproxy:
+    container_name: 'haproxy'
+    image: 'haproxy:2.1'
+    ports:
+      - "15443"
+    networks:
+      geode-sni-test:
+    volumes:
+      - ./dual-server-haproxy.cfg:/usr/local/etc/haproxy/haproxy.cfg:ro
+networks:
+  geode-sni-test:
+    name: geode-sni-test
+
diff --git 
a/geode-assembly/src/acceptanceTest/resources/org/apache/geode/client/sni/scripts/geode-starter.gfsh
 
b/geode-assembly/src/acceptanceTest/resources/org/apache/geode/client/sni/dual-server-haproxy.cfg
similarity index 51%
copy from 
geode-assembly/src/acceptanceTest/resources/org/apache/geode/client/sni/scripts/geode-starter.gfsh
copy to 
geode-assembly/src/acceptanceTest/resources/org/apache/geode/client/sni/dual-server-haproxy.cfg
index a9a9685..130f804 100644
--- 
a/geode-assembly/src/acceptanceTest/resources/org/apache/geode/client/sni/scripts/geode-starter.gfsh
+++ 
b/geode-assembly/src/acceptanceTest/resources/org/apache/geode/client/sni/dual-server-haproxy.cfg
@@ -15,8 +15,30 @@
 # limitations under the License.
 #
 
-start locator --name=locator-maeve --connect=false 
--hostname-for-clients=locator-maeve 
--properties-file=/geode/config/gemfire.properties 
--security-properties-file=/geode/config/gfsecurity.properties 
--J=-Dgemfire.ssl-keystore=/geode/config/locator-maeve-keystore.jks
-start server --name=server-dolores --max-heap=256m 
--hostname-for-clients=server-dolores --server-port=8501 
--locators=geode[10334] --properties-file=/geode/config/gemfire.properties 
--security-properties-file=/geode/config/gfsecurity.properties 
--J=-Dgemfire.ssl-keystore=/geode/config/server-dolores-keystore.jks
-connect --locator=geode[10334] --use-ssl=true 
--security-properties-file=/geode/config/gfsecurity.properties
-create region --name=jellyfish --type=REPLICATE
+defaults
+  timeout client 1000
+  timeout connect 1000
+  timeout server 1000
 
+frontend sniproxy
+  bind *:15443
+  mode tcp
+  tcp-request inspect-delay 5s
+  tcp-request content accept if { req_ssl_hello_type 1 }
+  use_backend locators-maeve if { req.ssl_sni -i locator-maeve }
+  use_backend servers-dolores if { req.ssl_sni -i server-dolores }
+  use_backend servers-clementine if { req.ssl_sni -i server-clementine }
+  default_backend locators-maeve
+  log stdout format raw  local0  debug
+
+backend locators-maeve
+  mode tcp
+  server locator1 locator-maeve:10334
+
+backend servers-dolores
+  mode tcp
+  server server1 server-dolores:8501
+
+backend servers-clementine
+  mode tcp
+  server server1 server-clementine:8502
diff --git 
a/geode-assembly/src/acceptanceTest/resources/org/apache/geode/client/sni/geode-config/locator-maeve-keystore.jks
 
b/geode-assembly/src/acceptanceTest/resources/org/apache/geode/client/sni/geode-config/locator-maeve-keystore.jks
index ec2feb8..cce17bd 100644
Binary files 
a/geode-assembly/src/acceptanceTest/resources/org/apache/geode/client/sni/geode-config/locator-maeve-keystore.jks
 and 
b/geode-assembly/src/acceptanceTest/resources/org/apache/geode/client/sni/geode-config/locator-maeve-keystore.jks
 differ
diff --git 
a/geode-assembly/src/acceptanceTest/resources/org/apache/geode/client/sni/geode-config/server-clementine-keystore.jks
 
b/geode-assembly/src/acceptanceTest/resources/org/apache/geode/client/sni/geode-config/server-clementine-keystore.jks
index 626269d..5eb5b88 100644
Binary files 
a/geode-assembly/src/acceptanceTest/resources/org/apache/geode/client/sni/geode-config/server-clementine-keystore.jks
 and 
b/geode-assembly/src/acceptanceTest/resources/org/apache/geode/client/sni/geode-config/server-clementine-keystore.jks
 differ
diff --git 
a/geode-assembly/src/acceptanceTest/resources/org/apache/geode/client/sni/geode-config/server-dolores-keystore.jks
 
b/geode-assembly/src/acceptanceTest/resources/org/apache/geode/client/sni/geode-config/server-dolores-keystore.jks
index 54de8d6..490c75a 100644
Binary files 
a/geode-assembly/src/acceptanceTest/resources/org/apache/geode/client/sni/geode-config/server-dolores-keystore.jks
 and 
b/geode-assembly/src/acceptanceTest/resources/org/apache/geode/client/sni/geode-config/server-dolores-keystore.jks
 differ
diff --git 
a/geode-assembly/src/acceptanceTest/resources/org/apache/geode/client/sni/geode-config/truststore.jks
 
b/geode-assembly/src/acceptanceTest/resources/org/apache/geode/client/sni/geode-config/truststore.jks
index a381a9a..69b4346 100644
Binary files 
a/geode-assembly/src/acceptanceTest/resources/org/apache/geode/client/sni/geode-config/truststore.jks
 and 
b/geode-assembly/src/acceptanceTest/resources/org/apache/geode/client/sni/geode-config/truststore.jks
 differ
diff --git 
a/geode-assembly/src/acceptanceTest/resources/org/apache/geode/client/sni/scripts/geode-starter.gfsh
 
b/geode-assembly/src/acceptanceTest/resources/org/apache/geode/client/sni/scripts/create-regions.gfsh
similarity index 51%
copy from 
geode-assembly/src/acceptanceTest/resources/org/apache/geode/client/sni/scripts/geode-starter.gfsh
copy to 
geode-assembly/src/acceptanceTest/resources/org/apache/geode/client/sni/scripts/create-regions.gfsh
index a9a9685..53b601d 100644
--- 
a/geode-assembly/src/acceptanceTest/resources/org/apache/geode/client/sni/scripts/geode-starter.gfsh
+++ 
b/geode-assembly/src/acceptanceTest/resources/org/apache/geode/client/sni/scripts/create-regions.gfsh
@@ -15,8 +15,6 @@
 # limitations under the License.
 #
 
-start locator --name=locator-maeve --connect=false 
--hostname-for-clients=locator-maeve 
--properties-file=/geode/config/gemfire.properties 
--security-properties-file=/geode/config/gfsecurity.properties 
--J=-Dgemfire.ssl-keystore=/geode/config/locator-maeve-keystore.jks
-start server --name=server-dolores --max-heap=256m 
--hostname-for-clients=server-dolores --server-port=8501 
--locators=geode[10334] --properties-file=/geode/config/gemfire.properties 
--security-properties-file=/geode/config/gfsecurity.properties 
--J=-Dgemfire.ssl-keystore=/geode/config/server-dolores-keystore.jks
-connect --locator=geode[10334] --use-ssl=true 
--security-properties-file=/geode/config/gfsecurity.properties
-create region --name=jellyfish --type=REPLICATE
-
+connect --locator=locator-maeve[10334] --use-ssl=true 
--security-properties-file=/geode/config/gfsecurity.properties
+create region --name=region-dolores --group=group-dolores --type=REPLICATE
+create region --name=region-clementine --group=group-clementine 
--type=REPLICATE
diff --git 
a/geode-assembly/src/acceptanceTest/resources/org/apache/geode/client/sni/scripts/geode-starter-2.gfsh
 
b/geode-assembly/src/acceptanceTest/resources/org/apache/geode/client/sni/scripts/geode-starter-2.gfsh
deleted file mode 100644
index 5e6ad74..0000000
--- 
a/geode-assembly/src/acceptanceTest/resources/org/apache/geode/client/sni/scripts/geode-starter-2.gfsh
+++ /dev/null
@@ -1,23 +0,0 @@
-#
-# Licensed to the Apache Software Foundation (ASF) under one or more
-# contributor license agreements.  See the NOTICE file distributed with
-# this work for additional information regarding copyright ownership.
-# The ASF licenses this file to You under the Apache License, Version 2.0
-# (the "License"); you may not use this file except in compliance with
-# the License.  You may obtain a copy of the License at
-#
-#      http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-#
-
-start locator --name=locator-maeve --connect=false --redirect-output 
--hostname-for-clients=locator-maeve 
--properties-file=/geode/config/gemfire.properties 
--security-properties-file=/geode/config/gfsecurity.properties 
--J=-Dgemfire.ssl-keystore=/geode/config/locator-maeve-keystore.jks
-start server --name=server-dolores --group=group-dolores 
--hostname-for-clients=server-dolores --server-port=8501 
--locators=geode[10334] --properties-file=/geode/config/gemfire.properties 
--security-properties-file=/geode/config/gfsecurity.properties 
--J=-Dgemfire.ssl-keystore=/geode/config/server-dolores-keystore.jks
-start server --name=server-clementine --group=group-clementine 
--hostname-for-clients=server-clementine --server-port=8502 
--locators=geode[10334] --properties-file=/geode/config/gemfire.properties 
--security-properties-file=/geode/config/gfsecurity.properties 
--J=-Dgemfire.ssl-keystore=/geode/config/server-clementine-keystore.jks
-connect --locator=geode[10334] --use-ssl=true 
--security-properties-file=/geode/config/gfsecurity.properties
-create region --name=region-dolores --group=group-dolores --type=REPLICATE
-create region --name=region-clementine --group=group-clementine 
--type=REPLICATE
diff --git 
a/geode-assembly/src/acceptanceTest/resources/org/apache/geode/client/sni/scripts/geode-starter.gfsh
 
b/geode-assembly/src/acceptanceTest/resources/org/apache/geode/client/sni/scripts/geode-starter.gfsh
index a9a9685..e893a2f 100644
--- 
a/geode-assembly/src/acceptanceTest/resources/org/apache/geode/client/sni/scripts/geode-starter.gfsh
+++ 
b/geode-assembly/src/acceptanceTest/resources/org/apache/geode/client/sni/scripts/geode-starter.gfsh
@@ -15,7 +15,7 @@
 # limitations under the License.
 #
 
-start locator --name=locator-maeve --connect=false 
--hostname-for-clients=locator-maeve 
--properties-file=/geode/config/gemfire.properties 
--security-properties-file=/geode/config/gfsecurity.properties 
--J=-Dgemfire.ssl-keystore=/geode/config/locator-maeve-keystore.jks
+start locator --name=locator-maeve --connect=false 
--hostname-for-clients=locator-maeve --jmx-manager-hostname-for-clients=geode 
--properties-file=/geode/config/gemfire.properties 
--security-properties-file=/geode/config/gfsecurity.properties 
--J=-Dgemfire.ssl-keystore=/geode/config/locator-maeve-keystore.jks
 start server --name=server-dolores --max-heap=256m 
--hostname-for-clients=server-dolores --server-port=8501 
--locators=geode[10334] --properties-file=/geode/config/gemfire.properties 
--security-properties-file=/geode/config/gfsecurity.properties 
--J=-Dgemfire.ssl-keystore=/geode/config/server-dolores-keystore.jks
 connect --locator=geode[10334] --use-ssl=true 
--security-properties-file=/geode/config/gfsecurity.properties
 create region --name=jellyfish --type=REPLICATE
diff --git 
a/geode-assembly/src/acceptanceTest/resources/org/apache/geode/client/sni/scripts/geode-starter.gfsh
 
b/geode-assembly/src/acceptanceTest/resources/org/apache/geode/client/sni/scripts/locator-maeve.gfsh
similarity index 51%
copy from 
geode-assembly/src/acceptanceTest/resources/org/apache/geode/client/sni/scripts/geode-starter.gfsh
copy to 
geode-assembly/src/acceptanceTest/resources/org/apache/geode/client/sni/scripts/locator-maeve.gfsh
index a9a9685..bcf3224 100644
--- 
a/geode-assembly/src/acceptanceTest/resources/org/apache/geode/client/sni/scripts/geode-starter.gfsh
+++ 
b/geode-assembly/src/acceptanceTest/resources/org/apache/geode/client/sni/scripts/locator-maeve.gfsh
@@ -15,8 +15,4 @@
 # limitations under the License.
 #
 
-start locator --name=locator-maeve --connect=false 
--hostname-for-clients=locator-maeve 
--properties-file=/geode/config/gemfire.properties 
--security-properties-file=/geode/config/gfsecurity.properties 
--J=-Dgemfire.ssl-keystore=/geode/config/locator-maeve-keystore.jks
-start server --name=server-dolores --max-heap=256m 
--hostname-for-clients=server-dolores --server-port=8501 
--locators=geode[10334] --properties-file=/geode/config/gemfire.properties 
--security-properties-file=/geode/config/gfsecurity.properties 
--J=-Dgemfire.ssl-keystore=/geode/config/server-dolores-keystore.jks
-connect --locator=geode[10334] --use-ssl=true 
--security-properties-file=/geode/config/gfsecurity.properties
-create region --name=jellyfish --type=REPLICATE
-
+start locator --name=locator-maeve --connect=false --redirect-output 
--bind-address=locator-maeve --http-service-bind-address=locator-maeve 
--jmx-manager-hostname-for-clients=locator-maeve 
--hostname-for-clients=locator-maeve 
--properties-file=/geode/config/gemfire.properties 
--security-properties-file=/geode/config/gfsecurity.properties 
--J=-Dgemfire.ssl-keystore=/geode/config/locator-maeve-keystore.jks 
--J=-Dgemfire.forceDnsUse=true --J=-Djdk.tls.trustNameService=true
diff --git 
a/geode-assembly/src/acceptanceTest/resources/org/apache/geode/client/sni/scripts/geode-starter.gfsh
 
b/geode-assembly/src/acceptanceTest/resources/org/apache/geode/client/sni/scripts/server-clementine.gfsh
similarity index 51%
copy from 
geode-assembly/src/acceptanceTest/resources/org/apache/geode/client/sni/scripts/geode-starter.gfsh
copy to 
geode-assembly/src/acceptanceTest/resources/org/apache/geode/client/sni/scripts/server-clementine.gfsh
index a9a9685..0922445 100644
--- 
a/geode-assembly/src/acceptanceTest/resources/org/apache/geode/client/sni/scripts/geode-starter.gfsh
+++ 
b/geode-assembly/src/acceptanceTest/resources/org/apache/geode/client/sni/scripts/server-clementine.gfsh
@@ -15,8 +15,4 @@
 # limitations under the License.
 #
 
-start locator --name=locator-maeve --connect=false 
--hostname-for-clients=locator-maeve 
--properties-file=/geode/config/gemfire.properties 
--security-properties-file=/geode/config/gfsecurity.properties 
--J=-Dgemfire.ssl-keystore=/geode/config/locator-maeve-keystore.jks
-start server --name=server-dolores --max-heap=256m 
--hostname-for-clients=server-dolores --server-port=8501 
--locators=geode[10334] --properties-file=/geode/config/gemfire.properties 
--security-properties-file=/geode/config/gfsecurity.properties 
--J=-Dgemfire.ssl-keystore=/geode/config/server-dolores-keystore.jks
-connect --locator=geode[10334] --use-ssl=true 
--security-properties-file=/geode/config/gfsecurity.properties
-create region --name=jellyfish --type=REPLICATE
-
+start server --name=server-clementine --group=group-clementine 
--bind-address=server-clementine --http-service-bind-address=server-clementine 
--hostname-for-clients=server-clementine --server-port=8502 
--locators=locator-maeve[10334] 
--properties-file=/geode/config/gemfire.properties 
--security-properties-file=/geode/config/gfsecurity.properties 
--J=-Dgemfire.ssl-keystore=/geode/config/server-clementine-keystore.jks 
--J=-Dgemfire.forceDnsUse=true --J=-Djdk.tls.trustNameService=true
diff --git 
a/geode-assembly/src/acceptanceTest/resources/org/apache/geode/client/sni/scripts/geode-starter.gfsh
 
b/geode-assembly/src/acceptanceTest/resources/org/apache/geode/client/sni/scripts/server-dolores.gfsh
similarity index 51%
copy from 
geode-assembly/src/acceptanceTest/resources/org/apache/geode/client/sni/scripts/geode-starter.gfsh
copy to 
geode-assembly/src/acceptanceTest/resources/org/apache/geode/client/sni/scripts/server-dolores.gfsh
index a9a9685..4f128f5 100644
--- 
a/geode-assembly/src/acceptanceTest/resources/org/apache/geode/client/sni/scripts/geode-starter.gfsh
+++ 
b/geode-assembly/src/acceptanceTest/resources/org/apache/geode/client/sni/scripts/server-dolores.gfsh
@@ -15,8 +15,4 @@
 # limitations under the License.
 #
 
-start locator --name=locator-maeve --connect=false 
--hostname-for-clients=locator-maeve 
--properties-file=/geode/config/gemfire.properties 
--security-properties-file=/geode/config/gfsecurity.properties 
--J=-Dgemfire.ssl-keystore=/geode/config/locator-maeve-keystore.jks
-start server --name=server-dolores --max-heap=256m 
--hostname-for-clients=server-dolores --server-port=8501 
--locators=geode[10334] --properties-file=/geode/config/gemfire.properties 
--security-properties-file=/geode/config/gfsecurity.properties 
--J=-Dgemfire.ssl-keystore=/geode/config/server-dolores-keystore.jks
-connect --locator=geode[10334] --use-ssl=true 
--security-properties-file=/geode/config/gfsecurity.properties
-create region --name=jellyfish --type=REPLICATE
-
+start server --name=server-dolores --group=group-dolores 
--bind-address=server-dolores --http-service-bind-address=server-dolores 
--hostname-for-clients=server-dolores --server-port=8501 
--locators=locator-maeve[10334] 
--properties-file=/geode/config/gemfire.properties 
--security-properties-file=/geode/config/gfsecurity.properties 
--J=-Dgemfire.ssl-keystore=/geode/config/server-dolores-keystore.jks 
--J=-Dgemfire.forceDnsUse=true --J=-Djdk.tls.trustNameService=true
diff --git 
a/geode-assembly/src/integrationTest/java/org/apache/geode/management/internal/cli/commands/StartLocatorCommandIntegrationTest.java
 
b/geode-assembly/src/integrationTest/java/org/apache/geode/management/internal/cli/commands/StartLocatorCommandIntegrationTest.java
index 59aaa80..b81625e 100644
--- 
a/geode-assembly/src/integrationTest/java/org/apache/geode/management/internal/cli/commands/StartLocatorCommandIntegrationTest.java
+++ 
b/geode-assembly/src/integrationTest/java/org/apache/geode/management/internal/cli/commands/StartLocatorCommandIntegrationTest.java
@@ -22,6 +22,8 @@ import static org.mockito.Mockito.doReturn;
 import static org.mockito.Mockito.mock;
 import static org.mockito.Mockito.verify;
 
+import java.io.InputStream;
+import java.io.OutputStream;
 import java.util.Properties;
 
 import org.junit.Before;
@@ -79,7 +81,11 @@ public class StartLocatorCommandIntegrationTest {
 
   @Test
   public void startWithBindAddress() throws Exception {
-    doReturn(mock(Process.class)).when(spy).getProcess(any(), any());
+    final Process mockProcess = mock(Process.class);
+    doReturn(mock(InputStream.class)).when(mockProcess).getInputStream();
+    doReturn(mock(InputStream.class)).when(mockProcess).getErrorStream();
+    doReturn(mock(OutputStream.class)).when(mockProcess).getOutputStream();
+    doReturn(mockProcess).when(spy).getProcess(any(), any());
     commandRule.executeAndAssertThat(spy, "start locator 
--bind-address=127.0.0.1");
 
     ArgumentCaptor<String[]> commandLines = 
ArgumentCaptor.forClass(String[].class);
diff --git 
a/geode-core/src/distributedTest/java/org/apache/geode/cache30/ReconnectWithClusterConfigurationDUnitTest.java
 
b/geode-core/src/distributedTest/java/org/apache/geode/cache30/ReconnectWithClusterConfigurationDUnitTest.java
index 1c8f92c..8288ac2 100644
--- 
a/geode-core/src/distributedTest/java/org/apache/geode/cache30/ReconnectWithClusterConfigurationDUnitTest.java
+++ 
b/geode-core/src/distributedTest/java/org/apache/geode/cache30/ReconnectWithClusterConfigurationDUnitTest.java
@@ -49,6 +49,7 @@ import org.apache.geode.distributed.DistributedSystem;
 import org.apache.geode.distributed.Locator;
 import org.apache.geode.distributed.internal.InternalLocator;
 import 
org.apache.geode.distributed.internal.membership.api.MembershipManagerHelper;
+import org.apache.geode.distributed.internal.tcpserver.HostAddress;
 import org.apache.geode.internal.AvailablePort;
 import org.apache.geode.internal.AvailablePortHelper;
 import org.apache.geode.internal.inet.LocalHostUtil;
@@ -97,7 +98,7 @@ public class ReconnectWithClusterConfigurationDUnitTest 
implements Serializable
           dsProperties = null;
           Properties props = getDistributedSystemProperties();
           locator = InternalLocator.startLocator(locatorPorts[locatorNumber], 
new File(""),
-              null, null, LocalHostUtil.getLocalHost(), true,
+              null, null, new HostAddress(LocalHostUtil.getLocalHost()), true,
               props, null, Paths.get(workingDir));
           system = locator.getDistributedSystem();
           cache = ((InternalLocator) locator).getCache();
diff --git 
a/geode-core/src/integrationTest/java/org/apache/geode/distributed/internal/InternalLocatorIntegrationTest.java
 
b/geode-core/src/integrationTest/java/org/apache/geode/distributed/internal/InternalLocatorIntegrationTest.java
index e712508..5f1239e 100644
--- 
a/geode-core/src/integrationTest/java/org/apache/geode/distributed/internal/InternalLocatorIntegrationTest.java
+++ 
b/geode-core/src/integrationTest/java/org/apache/geode/distributed/internal/InternalLocatorIntegrationTest.java
@@ -21,7 +21,6 @@ import static org.mockito.Mockito.when;
 
 import java.io.File;
 import java.io.IOException;
-import java.net.InetAddress;
 import java.nio.charset.Charset;
 import java.nio.file.Path;
 import java.util.Properties;
@@ -41,6 +40,7 @@ import org.mockito.quality.Strictness;
 
 import org.apache.geode.distributed.Locator;
 import 
org.apache.geode.distributed.internal.membership.gms.membership.GMSJoinLeave;
+import org.apache.geode.distributed.internal.tcpserver.HostAddress;
 import org.apache.geode.internal.security.SecurableCommunicationChannel;
 import org.apache.geode.logging.internal.LoggingSession;
 
@@ -59,7 +59,7 @@ public class InternalLocatorIntegrationTest {
   @Mock
   private LoggingSession loggingSession;
   private File logFile;
-  private InetAddress bindAddress;
+  private HostAddress bindAddress;
   private String hostnameForClients;
   @Mock
   private Properties distributedSystemProperties;
@@ -119,7 +119,9 @@ public class InternalLocatorIntegrationTest {
     assertThatCode(() -> {
       internalLocator =
           new InternalLocator(port, loggingSession, logFile, null, null,
-              bindAddress, hostnameForClients, distributedSystemProperties, 
distributionConfig,
+              bindAddress,
+              hostnameForClients,
+              distributedSystemProperties, distributionConfig,
               workingDirectory);
     }).doesNotThrowAnyException();
   }
diff --git 
a/geode-core/src/integrationTest/java/org/apache/geode/distributed/internal/membership/MembershipJUnitTest.java
 
b/geode-core/src/integrationTest/java/org/apache/geode/distributed/internal/membership/MembershipJUnitTest.java
index cb3c19a..08f4fe1 100755
--- 
a/geode-core/src/integrationTest/java/org/apache/geode/distributed/internal/membership/MembershipJUnitTest.java
+++ 
b/geode-core/src/integrationTest/java/org/apache/geode/distributed/internal/membership/MembershipJUnitTest.java
@@ -31,7 +31,6 @@ import static org.mockito.Mockito.verify;
 import static org.mockito.Mockito.when;
 
 import java.io.File;
-import java.net.InetAddress;
 import java.util.Comparator;
 import java.util.List;
 import java.util.Properties;
@@ -66,6 +65,7 @@ import 
org.apache.geode.distributed.internal.membership.api.MembershipListener;
 import org.apache.geode.distributed.internal.membership.api.MembershipLocator;
 import org.apache.geode.distributed.internal.membership.api.MembershipView;
 import org.apache.geode.distributed.internal.membership.api.MessageListener;
+import org.apache.geode.distributed.internal.tcpserver.HostAddress;
 import org.apache.geode.distributed.internal.tcpserver.TcpClient;
 import org.apache.geode.distributed.internal.tcpserver.TcpSocketCreator;
 import org.apache.geode.distributed.internal.tcpserver.TcpSocketFactory;
@@ -137,7 +137,7 @@ public class MembershipJUnitTest {
 
       // boot up a locator
       int port = AvailablePortHelper.getRandomAvailableTCPPort();
-      InetAddress localHost = LocalHostUtil.getLocalHost();
+      HostAddress localHost = new HostAddress(LocalHostUtil.getLocalHost());
 
       // this locator will hook itself up with the first Membership
       // to be created
@@ -328,13 +328,14 @@ public class MembershipJUnitTest {
 
       // boot up a locator
       int port = AvailablePortHelper.getRandomAvailableTCPPort();
-      InetAddress localHost = LocalHostUtil.getLocalHost();
+      HostAddress localHost = new HostAddress(LocalHostUtil.getLocalHost());
       Properties p = new Properties();
       p.setProperty(ConfigurationProperties.SECURITY_UDP_DHALGO, "AES:128");
       // this locator will hook itself up with the first Membership
       // to be created
       internalLocator =
-          InternalLocator.startLocator(port, new File(""), null, null, 
localHost, false, p, null,
+          InternalLocator.startLocator(port, new File(""), null, null, 
localHost, false, p,
+              null,
               temporaryFolder.getRoot().toPath());
 
       // create configuration objects
diff --git a/geode-core/src/main/java/org/apache/geode/distributed/Locator.java 
b/geode-core/src/main/java/org/apache/geode/distributed/Locator.java
index e4b2c98..0a62382 100644
--- a/geode-core/src/main/java/org/apache/geode/distributed/Locator.java
+++ b/geode-core/src/main/java/org/apache/geode/distributed/Locator.java
@@ -22,6 +22,7 @@ import java.util.List;
 import java.util.Properties;
 
 import org.apache.geode.distributed.internal.InternalLocator;
+import org.apache.geode.distributed.internal.tcpserver.HostAddress;
 import org.apache.geode.internal.inet.LocalHostUtil;
 
 /**
@@ -63,9 +64,12 @@ public abstract class Locator {
   /** The file to which this locator logs */
   protected File logFile;
 
-  /** The bind address for this locator */
+  /** no longer used but kept for binary compatibility */
   protected InetAddress bindAddress;
 
+  /** The bind address for this locator */
+  protected HostAddress hostAddress;
+
   /**
    * the hostname to give to clients so they can connect to this locator.
    *
@@ -101,7 +105,7 @@ public abstract class Locator {
    */
   public static Locator startLocator(int port, File logFile) throws 
IOException {
 
-    return startLocator(port, logFile, false, (InetAddress) null, (Properties) 
null, true, true,
+    return startLocator(port, logFile, false, null, null, true, true,
         null);
   }
 
@@ -136,7 +140,7 @@ public abstract class Locator {
   public static Locator startLocatorAndDS(int port, File logFile,
       Properties distributedSystemProperties) throws IOException {
 
-    return startLocator(port, logFile, (InetAddress) null, 
distributedSystemProperties, true, true,
+    return startLocator(port, logFile, null, distributedSystemProperties, 
true, true,
         null);
   }
 
@@ -165,8 +169,9 @@ public abstract class Locator {
    */
   public static Locator startLocator(int port, File logFile, InetAddress 
bindAddress)
       throws IOException {
-
-    return startLocator(port, logFile, false, bindAddress, (Properties) null, 
true, true, null);
+    HostAddress hostAddress = bindAddress == null ? null : new 
HostAddress(bindAddress);
+    return startLocator(port, logFile, false, hostAddress, null, true,
+        true, null);
   }
 
 
@@ -198,7 +203,9 @@ public abstract class Locator {
    */
   public static Locator startLocatorAndDS(int port, File logFile, InetAddress 
bindAddress,
       java.util.Properties dsProperties) throws IOException {
-    return startLocator(port, logFile, bindAddress, dsProperties, true, true, 
null);
+    HostAddress hostAddress = bindAddress == null ? null : new 
HostAddress(bindAddress);
+    return startLocator(port, logFile, hostAddress, dsProperties, true, true,
+        null);
   }
 
   /**
@@ -239,14 +246,16 @@ public abstract class Locator {
   public static Locator startLocatorAndDS(int port, File logFile, InetAddress 
bindAddress,
       java.util.Properties dsProperties, boolean peerLocator, boolean 
serverLocator,
       String hostnameForClients) throws IOException {
-    return startLocator(port, logFile, bindAddress, dsProperties, true, true, 
hostnameForClients);
+    HostAddress hostAddress = bindAddress == null ? null : new 
HostAddress(bindAddress);
+    return startLocator(port, logFile, hostAddress, dsProperties, true, true,
+        hostnameForClients);
   }
 
   /**
    * all Locator methods that start locators should use this method to start 
the locator and its
    * distributed system
    */
-  private static Locator startLocator(int port, File logFile, InetAddress 
bindAddress,
+  private static Locator startLocator(int port, File logFile, HostAddress 
bindAddress,
       java.util.Properties dsProperties, boolean peerLocator, boolean 
serverLocator,
       String hostnameForClients) throws IOException {
     return InternalLocator.startLocator(port, logFile, null, null, 
bindAddress, true, dsProperties,
@@ -258,7 +267,7 @@ public abstract class Locator {
    *             peerLocator, serverLocator, hostnameForClients) instead.
    */
   private static Locator startLocator(int port, File logFile, boolean 
startDistributedSystem,
-      InetAddress bindAddress, java.util.Properties dsProperties, boolean 
peerLocator,
+      HostAddress bindAddress, java.util.Properties dsProperties, boolean 
peerLocator,
       boolean serverLocator, String hostnameForClients) throws IOException {
     return InternalLocator.startLocator(port, logFile, null, null, bindAddress,
         startDistributedSystem, dsProperties, hostnameForClients);
@@ -332,7 +341,7 @@ public abstract class Locator {
    * Returns the IP address to which this locator's listening socket is bound.
    */
   public InetAddress getBindAddress() {
-    return this.bindAddress;
+    return bindAddress;
   }
 
   /**
@@ -382,14 +391,16 @@ public abstract class Locator {
    * Get the string representation of this <code>Locator</code> in host[port] 
format.
    */
   public String asString() {
-    Object ba = this.bindAddress;
-    if (ba == null) {
+    String bindAddressString = null;
+    if (hostAddress == null) {
       try {
-        ba = LocalHostUtil.getLocalHostName();
+        bindAddressString = LocalHostUtil.getLocalHostName();
       } catch (java.net.UnknownHostException uh) {
       }
+    } else {
+      bindAddressString = hostAddress.getHostName();
     }
-    StringBuilder locatorString = new StringBuilder(String.valueOf(ba));
+    StringBuilder locatorString = new 
StringBuilder(String.valueOf(bindAddressString));
     Integer port = getPort();
     if (port != null && port.intValue() > 0) {
       locatorString.append('[').append(this.getPort()).append(']');
diff --git 
a/geode-core/src/main/java/org/apache/geode/distributed/LocatorLauncher.java 
b/geode-core/src/main/java/org/apache/geode/distributed/LocatorLauncher.java
index 0cd015e..bab4a14 100644
--- a/geode-core/src/main/java/org/apache/geode/distributed/LocatorLauncher.java
+++ b/geode-core/src/main/java/org/apache/geode/distributed/LocatorLauncher.java
@@ -60,6 +60,7 @@ import org.apache.geode.cache.Cache;
 import org.apache.geode.cache.client.internal.locator.LocatorStatusRequest;
 import org.apache.geode.cache.client.internal.locator.LocatorStatusResponse;
 import org.apache.geode.distributed.internal.InternalLocator;
+import org.apache.geode.distributed.internal.tcpserver.HostAddress;
 import org.apache.geode.distributed.internal.tcpserver.HostAndPort;
 import org.apache.geode.distributed.internal.tcpserver.TcpClient;
 import org.apache.geode.distributed.internal.tcpserver.TcpSocketCreator;
@@ -187,7 +188,7 @@ public class LocatorLauncher extends 
AbstractLauncher<String> {
   private final boolean portSpecified;
   private final boolean workingDirectorySpecified;
 
-  private final InetAddress bindAddress;
+  private final HostAddress bindAddress;
 
   private final Integer pid;
   private final Integer port;
@@ -259,7 +260,7 @@ public class LocatorLauncher extends 
AbstractLauncher<String> {
     this.command = builder.getCommand();
     this.help = Boolean.TRUE.equals(builder.getHelp());
     this.bindAddressSpecified = builder.isBindAddressSpecified();
-    this.bindAddress = builder.getBindAddress();
+    this.bindAddress = builder.getHostAddress();
     setDebug(Boolean.TRUE.equals(builder.getDebug()));
     this.deletePidFileOnStop = 
Boolean.TRUE.equals(builder.getDeletePidFileOnStop());
     this.distributedSystemProperties = 
builder.getDistributedSystemProperties();
@@ -297,19 +298,31 @@ public class LocatorLauncher extends 
AbstractLauncher<String> {
   @Deprecated
   public static LocatorStatusResponse statusLocator(int port, InetAddress 
bindAddress)
       throws IOException {
-    return statusLocator(port, bindAddress, new Properties());
+    return statusLocator(port, bindAddress == null ? null : 
bindAddress.getCanonicalHostName(),
+        new Properties());
   }
 
   /**
-   * Returns the status of the locator on the given host & port
+   * Returns the status of the locator on the given host & port. If you have 
endpoint
+   * identification enabled the preferred method is statusForLocator(int, 
String), which
+   * lets you specify the locator's name that the locator has stored in its 
TLS certificate
    */
   public LocatorStatusResponse statusForLocator(int port, InetAddress 
bindAddress)
       throws IOException {
-    return statusLocator(port, bindAddress, getProperties());
+    return statusLocator(port, bindAddress == null ? null : 
bindAddress.getCanonicalHostName(),
+        getProperties());
+  }
+
+  /**
+   * Returns the status of the locator on the given host & port
+   */
+  public LocatorStatusResponse statusForLocator(int port, String hostname)
+      throws IOException {
+    return statusLocator(port, hostname, getProperties());
   }
 
   private static LocatorStatusResponse statusLocator(
-      final int port, InetAddress bindAddress,
+      final int port, String bindAddress,
       final Properties properties)
       throws IOException {
 
@@ -328,7 +341,7 @@ public class LocatorLauncher extends 
AbstractLauncher<String> {
           TcpSocketFactory.DEFAULT);
 
       return (LocatorStatusResponse) client.requestToServer(
-          new HostAndPort(bindAddress == null ? null : 
bindAddress.getCanonicalHostName(), port),
+          new HostAndPort(bindAddress == null ? HostUtils.getLocalHost() : 
bindAddress, port),
           new LocatorStatusRequest(), timeout, true);
     } catch (ClassNotFoundException e) {
       throw new RuntimeException(e);
@@ -429,7 +442,7 @@ public class LocatorLauncher extends 
AbstractLauncher<String> {
    * @see java.net.InetAddress
    */
   public InetAddress getBindAddress() {
-    return this.bindAddress;
+    return bindAddress == null ? null : bindAddress.getAddress();
   }
 
   /**
@@ -448,10 +461,9 @@ public class LocatorLauncher extends 
AbstractLauncher<String> {
    */
   protected String getBindAddressAsString() {
     try {
-      if (getBindAddress() != null) {
-        return getBindAddress().getCanonicalHostName();
+      if (bindAddress != null) {
+        return bindAddress.getHostName();
       }
-
       return LocalHostUtil.getCanonicalLocalHostName();
     } catch (UnknownHostException handled) {
       // Returning localhost/127.0.0.1 implies the bindAddress was null and no 
IP address for
@@ -714,7 +726,8 @@ public class LocatorLauncher extends 
AbstractLauncher<String> {
 
         try {
           this.locator = InternalLocator.startLocator(getPort(), getLogFile(), 
null, null,
-              getBindAddress(), true, getDistributedSystemProperties(), 
getHostnameForClients(),
+              bindAddress, true, getDistributedSystemProperties(),
+              getHostnameForClients(),
               Paths.get(workingDirectory));
         } finally {
           ProcessLauncherContext.remove();
@@ -860,7 +873,7 @@ public class LocatorLauncher extends 
AbstractLauncher<String> {
 
     while (System.currentTimeMillis() < endTimeInMilliseconds) {
       try {
-        LocatorStatusResponse response = statusForLocator(getPort(), 
getBindAddress());
+        LocatorStatusResponse response = statusForLocator(getPort(), 
getBindAddressString());
         return new LocatorState(this, Status.ONLINE, response);
       } catch (Exception handled) {
         timedWait(interval, timeUnit);
@@ -985,7 +998,7 @@ public class LocatorLauncher extends 
AbstractLauncher<String> {
 
   private LocatorState statusWithPort() {
     try {
-      LocatorStatusResponse response = statusForLocator(getPort(), 
getBindAddress());
+      LocatorStatusResponse response = statusForLocator(getPort(), 
getBindAddressString());
       return new LocatorState(this, Status.ONLINE, response);
     } catch (Exception handled) {
       return createNoResponseState(handled,
@@ -1186,6 +1199,10 @@ public class LocatorLauncher extends 
AbstractLauncher<String> {
     return overriddenDefaults;
   }
 
+  public String getBindAddressString() {
+    return bindAddress == null ? null : bindAddress.getHostName();
+  }
+
   private class LocatorControllerParameters implements 
ProcessControllerParameters {
     @Override
     public File getPidFile() {
@@ -1260,7 +1277,7 @@ public class LocatorLauncher extends 
AbstractLauncher<String> {
     private Boolean loadSharedConfigFromDir;
     private Command command;
 
-    private InetAddress bindAddress;
+    private HostAddress bindAddress;
 
     private Integer pid;
     private Integer port;
@@ -1571,14 +1588,18 @@ public class LocatorLauncher extends 
AbstractLauncher<String> {
      * @see java.net.InetAddress
      */
     public InetAddress getBindAddress() {
-      return this.bindAddress;
+      return bindAddress == null ? null : bindAddress.getAddress();
+    }
+
+    HostAddress getHostAddress() {
+      return bindAddress;
     }
 
     /**
      * Sets the IP address as an java.net.InetAddress to which the Locator has 
bound itself
      * listening for client requests.
      *
-     * @param bindAddress the InetAddress with the IP address or hostname on 
which the Locator is
+     * @param addressString the InetAddress with the IP address or hostname on 
which the Locator is
      *        bound and listening.
      * @return this Builder instance.
      * @throws IllegalArgumentException wrapping the UnknownHostException if 
the IP address or
@@ -1586,24 +1607,23 @@ public class LocatorLauncher extends 
AbstractLauncher<String> {
      * @see #getBindAddress()
      * @see java.net.InetAddress
      */
-    public Builder setBindAddress(final String bindAddress) {
-      if (isBlank(bindAddress)) {
+    public Builder setBindAddress(final String addressString) {
+      if (isBlank(addressString)) {
         this.bindAddress = null;
         return this;
       } else {
         try {
-          InetAddress address = InetAddress.getByName(bindAddress);
+          InetAddress address = InetAddress.getByName(addressString);
           if (LocalHostUtil.isLocalHost(address)) {
-            this.bindAddress = address;
+            this.bindAddress = new HostAddress(addressString);
             return this;
           } else {
             throw new IllegalArgumentException(
-                bindAddress + " is not an address for this machine.");
+                addressString + " is not an address for this machine.");
           }
         } catch (UnknownHostException e) {
-          throw new IllegalArgumentException(
-              String.format("The hostname/IP address to which the %s will be 
bound is unknown.",
-                  "Locator"),
+          throw new IllegalArgumentException("The hostname/IP address (" + 
addressString
+              + ") to which the Locator will be bound is unknown.",
               e);
         }
       }
@@ -2130,11 +2150,9 @@ public class LocatorLauncher extends 
AbstractLauncher<String> {
     private static String getBindAddressAsString(LocatorLauncher launcher) {
       if (InternalLocator.hasLocator()) {
         final InternalLocator locator = InternalLocator.getLocator();
-        final InetAddress bindAddress = locator.getBindAddress();
-        if (bindAddress != null) {
-          if (isNotBlank(bindAddress.getHostAddress())) {
-            return bindAddress.getHostAddress();
-          }
+        String bindAddress = locator.getBindAddressString();
+        if (bindAddress != null && !bindAddress.isEmpty()) {
+          return bindAddress;
         }
       }
       return launcher.getBindAddressAsString();
diff --git 
a/geode-core/src/main/java/org/apache/geode/distributed/internal/InternalDistributedSystem.java
 
b/geode-core/src/main/java/org/apache/geode/distributed/internal/InternalDistributedSystem.java
index 5f3b5d9..5af9502 100644
--- 
a/geode-core/src/main/java/org/apache/geode/distributed/internal/InternalDistributedSystem.java
+++ 
b/geode-core/src/main/java/org/apache/geode/distributed/internal/InternalDistributedSystem.java
@@ -79,6 +79,7 @@ import 
org.apache.geode.distributed.internal.membership.InternalDistributedMembe
 import 
org.apache.geode.distributed.internal.membership.api.MembershipInformation;
 import org.apache.geode.distributed.internal.membership.api.MembershipLocator;
 import org.apache.geode.distributed.internal.membership.api.QuorumChecker;
+import org.apache.geode.distributed.internal.tcpserver.HostAddress;
 import org.apache.geode.internal.Assert;
 import org.apache.geode.internal.InternalDataSerializer;
 import org.apache.geode.internal.InternalInstantiator;
@@ -914,8 +915,9 @@ public class InternalDistributedSystem extends 
DistributedSystem
     try {
       startedLocator =
           InternalLocator.createLocator(locId.getPort(), 
NullLoggingSession.create(), null,
-              logWriter, securityLogWriter, locId.getHost().getAddress(),
-              locId.getHostnameForClients(), originalConfig.toProperties(), 
false);
+              logWriter, securityLogWriter, new HostAddress(locId.getHost()),
+              locId.getHostnameForClients(), originalConfig.toProperties(),
+              false);
 
       // if locator is started this way, cluster config is not enabled, set 
the flag correctly
       startedLocator.getConfig().setEnableClusterConfiguration(false);
diff --git 
a/geode-core/src/main/java/org/apache/geode/distributed/internal/InternalLocator.java
 
b/geode-core/src/main/java/org/apache/geode/distributed/internal/InternalLocator.java
index e011936..716613e 100644
--- 
a/geode-core/src/main/java/org/apache/geode/distributed/internal/InternalLocator.java
+++ 
b/geode-core/src/main/java/org/apache/geode/distributed/internal/InternalLocator.java
@@ -24,7 +24,6 @@ import static 
org.apache.geode.util.internal.GeodeGlossary.GEMFIRE_PREFIX;
 
 import java.io.File;
 import java.io.IOException;
-import java.net.InetAddress;
 import java.net.URI;
 import java.net.UnknownHostException;
 import java.nio.file.Path;
@@ -70,6 +69,7 @@ import 
org.apache.geode.distributed.internal.membership.api.MembershipConfigurat
 import org.apache.geode.distributed.internal.membership.api.MembershipLocator;
 import 
org.apache.geode.distributed.internal.membership.api.MembershipLocatorBuilder;
 import org.apache.geode.distributed.internal.membership.api.QuorumChecker;
+import org.apache.geode.distributed.internal.tcpserver.HostAddress;
 import org.apache.geode.distributed.internal.tcpserver.InfoRequest;
 import org.apache.geode.distributed.internal.tcpserver.TcpHandler;
 import org.apache.geode.distributed.internal.tcpserver.TcpServer;
@@ -262,13 +262,16 @@ public class InternalLocator extends Locator implements 
ConnectListener, LogConf
    * @param startDistributedSystem if true then this locator will also start 
its own ds
    *
    * @deprecated Please use
-   *             {@link #createLocator(int, LoggingSession, File, 
InternalLogWriter, InternalLogWriter, InetAddress, String, Properties, Path)}
+   *             {@link #createLocator(int, LoggingSession, File, 
InternalLogWriter, InternalLogWriter, HostAddress, String, Properties, Path)}
    *             instead.
    */
   @Deprecated
   public static InternalLocator createLocator(int port, LoggingSession 
loggingSession, File logFile,
-      InternalLogWriter logWriter, InternalLogWriter securityLogWriter, 
InetAddress bindAddress,
-      String hostnameForClients, Properties distributedSystemProperties,
+      InternalLogWriter logWriter,
+      InternalLogWriter securityLogWriter,
+      HostAddress bindAddress,
+      String hostnameForClients,
+      Properties distributedSystemProperties,
       boolean startDistributedSystem) {
     return createLocator(port, loggingSession, logFile, logWriter, 
securityLogWriter, bindAddress,
         hostnameForClients, distributedSystemProperties,
@@ -286,13 +289,18 @@ public class InternalLocator extends Locator implements 
ConnectListener, LogConf
    * @param logFile the file that log messages should be written to
    * @param logWriter a log writer that should be used (logFile parameter is 
ignored)
    * @param securityLogWriter the logWriter to be used for security related 
log messages
+   * @param bindAddress the bind address for the locator
    * @param distributedSystemProperties optional properties to configure the 
distributed system
    *        (e.g., mcast addr/port, other locators)
    * @param workingDirectory the working directory to use for any files
    */
   public static InternalLocator createLocator(int port, LoggingSession 
loggingSession, File logFile,
-      InternalLogWriter logWriter, InternalLogWriter securityLogWriter, 
InetAddress bindAddress,
-      String hostnameForClients, Properties distributedSystemProperties, Path 
workingDirectory) {
+      InternalLogWriter logWriter,
+      InternalLogWriter securityLogWriter,
+      HostAddress bindAddress,
+      String hostnameForClients,
+      Properties distributedSystemProperties,
+      Path workingDirectory) {
     synchronized (locatorLock) {
       if (hasLocator()) {
         throw new IllegalStateException(
@@ -336,7 +344,7 @@ public class InternalLocator extends Locator implements 
ConnectListener, LogConf
    * @param hostnameForClients the name to give to clients for connecting to 
this locator
    */
   public static InternalLocator startLocator(int port, File logFile, 
InternalLogWriter logWriter,
-      InternalLogWriter securityLogWriter, InetAddress bindAddress, boolean 
startDistributedSystem,
+      InternalLogWriter securityLogWriter, HostAddress bindAddress, boolean 
startDistributedSystem,
       Properties distributedSystemProperties, String hostnameForClients)
       throws IOException {
     return startLocator(port, logFile, logWriter, securityLogWriter, 
bindAddress,
@@ -355,6 +363,7 @@ public class InternalLocator extends Locator implements 
ConnectListener, LogConf
    * @param logFile the file that log messages should be written to
    * @param logWriter a log writer that should be used (logFile parameter is 
ignored)
    * @param securityLogWriter the logWriter to be used for security related 
log messages
+   * @param bindAddress the bind address for the locator
    * @param startDistributedSystem if true, a distributed system is started
    * @param distributedSystemProperties optional properties to configure the 
distributed system
    *        (e.g., mcast
@@ -363,8 +372,11 @@ public class InternalLocator extends Locator implements 
ConnectListener, LogConf
    * @param workingDirectory the working directory to use for any files
    */
   public static InternalLocator startLocator(int port, File logFile, 
InternalLogWriter logWriter,
-      InternalLogWriter securityLogWriter, InetAddress bindAddress, boolean 
startDistributedSystem,
-      Properties distributedSystemProperties, String hostnameForClients, Path 
workingDirectory)
+      InternalLogWriter securityLogWriter,
+      HostAddress bindAddress,
+      boolean startDistributedSystem,
+      Properties distributedSystemProperties,
+      String hostnameForClients, Path workingDirectory)
       throws IOException {
     System.setProperty(FORCE_LOCATOR_DM_TYPE, "true");
     InternalLocator newLocator = null;
@@ -469,11 +481,17 @@ public class InternalLocator extends Locator implements 
ConnectListener, LogConf
    */
   @VisibleForTesting
   InternalLocator(int port, LoggingSession loggingSession, File logFile,
-      InternalLogWriter logWriter, InternalLogWriter securityLogWriter, 
InetAddress bindAddress,
-      String hostnameForClients, Properties distributedSystemProperties,
+      InternalLogWriter logWriter, InternalLogWriter securityLogWriter,
+      HostAddress hostAddress, String hostnameForClients,
+      Properties distributedSystemProperties,
       DistributionConfigImpl distributionConfig, Path workingDirectory) {
     this.logFile = logFile;
-    this.bindAddress = bindAddress;
+    this.hostAddress = hostAddress;
+    // bindAddress is superceded by hostAddress but must be kept for Locator 
API backward
+    // compatibility
+    if (hostAddress != null) {
+      this.bindAddress = hostAddress.getAddress();
+    }
     this.hostnameForClients = hostnameForClients;
 
     this.workingDirectory = workingDirectory;
@@ -483,8 +501,8 @@ public class InternalLocator extends Locator implements 
ConnectListener, LogConf
 
     // set bind-address explicitly only if not wildcard and let any explicit
     // value in distributedSystemProperties take precedence
-    if (bindAddress != null && !bindAddress.isAnyLocalAddress()) {
-      env.setProperty(BIND_ADDRESS, bindAddress.getHostAddress());
+    if (hostAddress != null) {
+      env.setProperty(BIND_ADDRESS, hostAddress.getHostName());
     }
 
     if (distributedSystemProperties != null) {
@@ -558,7 +576,7 @@ public class InternalLocator extends Locator implements 
ConnectListener, LogConf
               executor)
               .setConfig(config)
               .setPort(port)
-              .setBindAddress(bindAddress)
+              .setBindAddress(hostAddress)
               .setProtocolChecker(new ProtocolCheckerImpl(this, new 
ClientProtocolServiceLoader()))
               .setFallbackHandler(handler)
               .setLocatorsAreCoordinators(shouldLocatorsBeCoordinators())
@@ -678,7 +696,7 @@ public class InternalLocator extends Locator implements 
ConnectListener, LogConf
    */
   @Deprecated
   public static InternalLocator startLocator(int locatorPort, File logFile,
-      InternalLogWriter logWriter, InternalLogWriter securityLogWriter, 
InetAddress bindAddress,
+      InternalLogWriter logWriter, InternalLogWriter securityLogWriter, 
HostAddress bindAddress,
       Properties distributedSystemProperties, boolean peerLocator, boolean 
serverLocator,
       String hostnameForClients, boolean b1) throws IOException {
     return startLocator(locatorPort, logFile, logWriter, securityLogWriter, 
bindAddress, true,
@@ -701,8 +719,8 @@ public class InternalLocator extends Locator implements 
ConnectListener, LogConf
     } else {
 
       StringBuilder sb = new StringBuilder(100);
-      if (bindAddress != null) {
-        sb.append(bindAddress.getHostAddress());
+      if (hostAddress != null && 
!StringUtils.isEmpty(hostAddress.getHostName())) {
+        sb.append(hostAddress.getHostName());
       } else {
         sb.append(LocalHostUtil.getLocalHost().getCanonicalHostName());
       }
@@ -891,8 +909,9 @@ public class InternalLocator extends Locator implements 
ConnectListener, LogConf
       }
     }
 
-    ServerLocator serverLocator = new ServerLocator(getPort(), bindAddress, 
hostnameForClients,
-        logFile, productUseLog, getConfig().getName(), distributedSystem, 
locatorStats);
+    ServerLocator serverLocator =
+        new ServerLocator(getPort(), getBindAddressString(), 
hostnameForClients,
+            logFile, productUseLog, getConfig().getName(), distributedSystem, 
locatorStats);
     restartHandlers.add(serverLocator);
     membershipLocator.addHandler(LocatorListRequest.class, serverLocator);
     membershipLocator.addHandler(ClientConnectionRequest.class, serverLocator);
@@ -1430,6 +1449,13 @@ public class InternalLocator extends Locator implements 
ConnectListener, LogConf
     return membershipLocator.isHandled(messageClass);
   }
 
+  public String getBindAddressString() {
+    if (hostAddress != null) {
+      return hostAddress.getHostName();
+    }
+    return null;
+  }
+
   class FetchSharedConfigStatus implements 
Callable<SharedConfigurationStatusResponse> {
 
     @Override
diff --git 
a/geode-core/src/main/java/org/apache/geode/distributed/internal/ServerLocator.java
 
b/geode-core/src/main/java/org/apache/geode/distributed/internal/ServerLocator.java
index 4442073..6e6dfaa 100755
--- 
a/geode-core/src/main/java/org/apache/geode/distributed/internal/ServerLocator.java
+++ 
b/geode-core/src/main/java/org/apache/geode/distributed/internal/ServerLocator.java
@@ -16,7 +16,6 @@ package org.apache.geode.distributed.internal;
 
 import java.io.File;
 import java.io.IOException;
-import java.net.InetAddress;
 import java.util.ArrayList;
 import java.util.Arrays;
 import java.util.Collections;
@@ -108,15 +107,15 @@ public class ServerLocator implements TcpHandler, 
RestartHandler, DistributionAd
     return loadSnapshot;
   }
 
-  public ServerLocator(int port, InetAddress bindAddress, String 
hostNameForClients, File logFile,
+  public ServerLocator(int port, String bindAddress, String 
hostNameForClients, File logFile,
       ProductUseLog productUseLogWriter, String memberName, 
InternalDistributedSystem ds,
       LocatorStats stats) throws IOException {
     this.port = port;
 
-    if (bindAddress == null) {
+    if (bindAddress == null || bindAddress.isEmpty()) {
       this.hostName = LocalHostUtil.getCanonicalLocalHostName();
     } else {
-      this.hostName = bindAddress.getHostAddress();
+      this.hostName = bindAddress;
     }
 
     if (hostNameForClients != null && !hostNameForClients.equals("")) {
diff --git 
a/geode-core/src/main/java/org/apache/geode/distributed/internal/membership/adapter/ServiceConfig.java
 
b/geode-core/src/main/java/org/apache/geode/distributed/internal/membership/adapter/ServiceConfig.java
index 8788f34..de56882 100644
--- 
a/geode-core/src/main/java/org/apache/geode/distributed/internal/membership/adapter/ServiceConfig.java
+++ 
b/geode-core/src/main/java/org/apache/geode/distributed/internal/membership/adapter/ServiceConfig.java
@@ -66,10 +66,9 @@ public class ServiceConfig implements MembershipConfig {
 
     joinTimeout = Long.getLong("p2p.joinTimeout", 
defaultJoinTimeout).longValue();
 
-    // if network partition detection is enabled, we must connect to the 
locators
-    // more frequently in order to make sure we're not isolated from them
     SocketCreator.resolve_dns = true;
-    if (theConfig.getEnableNetworkPartitionDetection()) {
+    if (theConfig.getEnableNetworkPartitionDetection() &&
+        !theConfig.getSSLEndPointIdentificationEnabled()) {
       if (!SocketCreator.FORCE_DNS_USE) {
         SocketCreator.resolve_dns = false;
       }
diff --git 
a/geode-core/src/main/java/org/apache/geode/internal/DistributionLocator.java 
b/geode-core/src/main/java/org/apache/geode/internal/DistributionLocator.java
index 731459c..8815a6a 100644
--- 
a/geode-core/src/main/java/org/apache/geode/internal/DistributionLocator.java
+++ 
b/geode-core/src/main/java/org/apache/geode/internal/DistributionLocator.java
@@ -18,7 +18,6 @@ package org.apache.geode.internal;
 import java.io.File;
 import java.io.IOException;
 import java.net.InetAddress;
-import java.util.Properties;
 
 import org.apache.logging.log4j.Logger;
 
@@ -26,6 +25,7 @@ import org.apache.geode.SystemFailure;
 import org.apache.geode.annotations.internal.MakeNotStatic;
 import org.apache.geode.distributed.internal.InternalDistributedSystem;
 import org.apache.geode.distributed.internal.InternalLocator;
+import org.apache.geode.distributed.internal.tcpserver.HostAddress;
 import org.apache.geode.logging.internal.executors.LoggingThread;
 import org.apache.geode.logging.internal.log4j.api.LogService;
 import org.apache.geode.util.internal.GeodeGlossary;
@@ -109,9 +109,7 @@ public class DistributionLocator {
     SystemFailure.loadEmergencyClasses();
 
     final int port = parsePort(args[0]);
-    InetAddress address = null;
-    boolean peerLocator = true;
-    boolean serverLocator = true;
+    HostAddress hostAddress = null;
     String hostnameForClients = null;
     try {
       if (args.length > 1 && !args[1].equals("")) {
@@ -121,43 +119,37 @@ public class DistributionLocator {
                   args[1]));
           ExitCode.FATAL.doSystemExit();
         }
-        address = InetAddress.getByName(args[1]);
+        hostAddress = new HostAddress(args[1]);
+        // do a look-up to ensure that the name can be resolved to an address
+        InetAddress.getByName(args[1]);
       } else {
         // address = null; // was InetAddress.getLocalHost(); (redundant 
assignment)
       }
-      if (args.length > 2) {
-        peerLocator = "true".equalsIgnoreCase(args[2]);
-      }
-      if (args.length > 3) {
-        serverLocator = "true".equalsIgnoreCase(args[3]);
-      }
       if (args.length > 4) {
         hostnameForClients = args[4];
       }
 
+      final InetAddress inetAddress = hostAddress == null ? null : 
hostAddress.getAddress();
       if 
(!Boolean.getBoolean(InternalDistributedSystem.DISABLE_SHUTDOWN_HOOK_PROPERTY)) 
{
-        final InetAddress faddress = address;
         Runtime.getRuntime()
             .addShutdownHook(new LoggingThread("LocatorShutdownThread", false, 
() -> {
               try {
-                DistributionLocator.shutdown(port, faddress);
+                DistributionLocator.shutdown(port, inetAddress);
               } catch (IOException e) {
                 e.printStackTrace();
               }
             }));
       }
 
-      lockFile = ManagerInfo.setLocatorStarting(directory, port, address);
+      lockFile = ManagerInfo.setLocatorStarting(directory, port, inetAddress);
       lockFile.deleteOnExit();
 
+      InetAddress address = hostAddress == null ? null : 
hostAddress.getAddress();
       try {
-
         InternalLocator locator = InternalLocator.startLocator(port, new 
File(DEFAULT_LOG_FILE),
-            null, null, address, true, (Properties) null, hostnameForClients);
-
+            null, null, hostAddress, true, null, hostnameForClients);
         ManagerInfo.setLocatorStarted(directory, port, address);
         locator.waitToStop();
-
       } finally {
         shutdown(port, address);
       }
@@ -168,7 +160,7 @@ public class DistributionLocator {
 
     } catch (java.net.BindException ex) {
       logger.fatal("Could not bind locator to {}[{}]",
-          new Object[] {address, port});
+          new Object[] {hostAddress, port});
       ExitCode.FATAL.doSystemExit();
 
     } catch (Exception ex) {
diff --git 
a/geode-core/src/main/java/org/apache/geode/internal/admin/remote/DistributionLocatorId.java
 
b/geode-core/src/main/java/org/apache/geode/internal/admin/remote/DistributionLocatorId.java
index 3af2017..b0e9eb9 100644
--- 
a/geode-core/src/main/java/org/apache/geode/internal/admin/remote/DistributionLocatorId.java
+++ 
b/geode-core/src/main/java/org/apache/geode/internal/admin/remote/DistributionLocatorId.java
@@ -26,6 +26,7 @@ import org.apache.commons.lang3.StringUtils;
 import org.apache.geode.InternalGemFireException;
 import org.apache.geode.distributed.Locator;
 import org.apache.geode.distributed.internal.DistributionConfig;
+import org.apache.geode.distributed.internal.InternalLocator;
 import org.apache.geode.distributed.internal.tcpserver.HostAndPort;
 import org.apache.geode.internal.inet.LocalHostUtil;
 import org.apache.geode.internal.net.SSLConfig;
@@ -173,7 +174,11 @@ public class DistributionLocatorId implements 
java.io.Serializable {
 
   public DistributionLocatorId(InetAddress address, Locator locator) {
     this(address, locator.getPort(),
-        locator.getBindAddress() == null ? null : 
locator.getBindAddress().getHostAddress(), null,
+        (((InternalLocator) locator).getBindAddressString() != null
+            ? ((InternalLocator) locator).getBindAddressString()
+            : (locator.getBindAddress() != null ? 
locator.getBindAddress().getHostAddress()
+                : null)),
+        null,
         locator.getHostnameForClients());
   }
 
diff --git 
a/geode-core/src/main/java/org/apache/geode/internal/net/SocketCreator.java 
b/geode-core/src/main/java/org/apache/geode/internal/net/SocketCreator.java
index e9e3775..f4fa405 100755
--- a/geode-core/src/main/java/org/apache/geode/internal/net/SocketCreator.java
+++ b/geode-core/src/main/java/org/apache/geode/internal/net/SocketCreator.java
@@ -62,7 +62,6 @@ import javax.net.ssl.TrustManagerFactory;
 import javax.net.ssl.X509ExtendedKeyManager;
 
 import org.apache.commons.lang3.StringUtils;
-import org.apache.commons.validator.routines.InetAddressValidator;
 import org.apache.logging.log4j.Logger;
 
 import org.apache.geode.GemFireConfigException;
@@ -837,17 +836,6 @@ public class SocketCreator extends TcpSocketCreatorImpl {
     }
 
     String hostName = addr.getHostName();
-    if (this.sslConfig.doEndpointIdentification()
-        && InetAddressValidator.getInstance().isValid(hostName)) {
-      // endpoint validation typically uses a hostname in the sniServer 
parameter that the handshake
-      // will compare against the subject alternative addresses in the 
server's certificate. Here
-      // we attempt to get a hostname instead of the proffered numeric address
-      try {
-        hostName = InetAddress.getByName(hostName).getCanonicalHostName();
-      } catch (UnknownHostException e) {
-        // ignore - we'll see what happens with endpoint validation using a 
numeric address...
-      }
-    }
     serverNames.add(new SNIHostName(hostName));
     modifiedParams.setServerNames(serverNames);
     return true;
diff --git 
a/geode-core/src/main/java/org/apache/geode/internal/tcp/Connection.java 
b/geode-core/src/main/java/org/apache/geode/internal/tcp/Connection.java
index 68cd5d6..95e1d73 100644
--- a/geode-core/src/main/java/org/apache/geode/internal/tcp/Connection.java
+++ b/geode-core/src/main/java/org/apache/geode/internal/tcp/Connection.java
@@ -1736,8 +1736,14 @@ public class Connection implements Runnable {
   private void createIoFilter(SocketChannel channel, boolean clientSocket) 
throws IOException {
     if (getConduit().useSSL() && channel != null) {
       InetSocketAddress address = (InetSocketAddress) 
channel.getRemoteAddress();
+      String hostName;
+      if (remoteAddr != null) {
+        hostName = remoteAddr.getHostName();
+      } else {
+        hostName = SocketCreator.getHostName(address.getAddress());
+      }
       SSLEngine engine =
-          
getConduit().getSocketCreator().createSSLEngine(address.getHostString(),
+          getConduit().getSocketCreator().createSSLEngine(hostName,
               address.getPort(), clientSocket);
 
       final int packetBufferSize = engine.getSession().getPacketBufferSize();
diff --git 
a/geode-core/src/test/java/org/apache/geode/distributed/internal/InternalLocatorTest.java
 
b/geode-core/src/test/java/org/apache/geode/distributed/internal/InternalLocatorTest.java
index fd678c8..8c79dd3 100644
--- 
a/geode-core/src/test/java/org/apache/geode/distributed/internal/InternalLocatorTest.java
+++ 
b/geode-core/src/test/java/org/apache/geode/distributed/internal/InternalLocatorTest.java
@@ -33,6 +33,7 @@ import org.junit.Test;
 
 import org.apache.geode.cache.RegionShortcut;
 import org.apache.geode.cache.internal.HttpService;
+import org.apache.geode.distributed.internal.tcpserver.HostAddress;
 import org.apache.geode.internal.AvailablePortHelper;
 import org.apache.geode.internal.cache.InternalCacheForClientAccess;
 import org.apache.geode.internal.cache.InternalRegionFactory;
@@ -74,7 +75,7 @@ public class InternalLocatorTest {
     when(agentUtil.findWarLocation("geode-web-management")).thenReturn(uri);
     BaseManagementService.setManagementService(cache, managementService);
 
-    internalLocator = new InternalLocator(0, loggingSession, null, null, null, 
null,
+    internalLocator = new InternalLocator(0, loggingSession, null, null, null, 
(HostAddress) null,
         null, null, distributionConfig, null);
   }
 
diff --git 
a/geode-gfsh/src/main/java/org/apache/geode/management/internal/cli/commands/StartLocatorCommand.java
 
b/geode-gfsh/src/main/java/org/apache/geode/management/internal/cli/commands/StartLocatorCommand.java
index 859e1d8..d5c5532 100644
--- 
a/geode-gfsh/src/main/java/org/apache/geode/management/internal/cli/commands/StartLocatorCommand.java
+++ 
b/geode-gfsh/src/main/java/org/apache/geode/management/internal/cli/commands/StartLocatorCommand.java
@@ -17,7 +17,6 @@ package org.apache.geode.management.internal.cli.commands;
 
 import java.io.File;
 import java.io.IOException;
-import java.net.InetAddress;
 import java.util.ArrayList;
 import java.util.Arrays;
 import java.util.List;
@@ -314,9 +313,9 @@ public class StartLocatorCommand extends OfflineGfshCommand 
{
 
     infoResult.addLine(locatorState.toString());
     String locatorHostName;
-    InetAddress bindAddr = locatorLauncher.getBindAddress();
+    String bindAddr = locatorLauncher.getBindAddressString();
     if (bindAddr != null) {
-      locatorHostName = bindAddr.getCanonicalHostName();
+      locatorHostName = bindAddr;
     } else {
       locatorHostName = 
StringUtils.defaultIfBlank(locatorLauncher.getHostnameForClients(),
           HostUtils.getLocalHost());
@@ -481,8 +480,8 @@ public class StartLocatorCommand extends OfflineGfshCommand 
{
       commandLine.add(launcher.getMemberName());
     }
 
-    if (launcher.getBindAddress() != null) {
-      commandLine.add("--bind-address=" + 
launcher.getBindAddress().getHostAddress());
+    if (launcher.getBindAddressString() != null) {
+      commandLine.add("--bind-address=" + launcher.getBindAddressString());
     }
 
     if (launcher.isDebugging() || isDebugging()) {
diff --git 
a/geode-gfsh/src/main/java/org/apache/geode/management/internal/cli/shell/JmxOperationInvoker.java
 
b/geode-gfsh/src/main/java/org/apache/geode/management/internal/cli/shell/JmxOperationInvoker.java
index 9aaa142..5dd0a2c 100644
--- 
a/geode-gfsh/src/main/java/org/apache/geode/management/internal/cli/shell/JmxOperationInvoker.java
+++ 
b/geode-gfsh/src/main/java/org/apache/geode/management/internal/cli/shell/JmxOperationInvoker.java
@@ -130,8 +130,9 @@ public class JmxOperationInvoker implements 
OperationInvoker {
       env.put("com.sun.jndi.rmi.factory.socket", new 
ContextAwareSSLRMIClientSocketFactory());
     }
 
+    final String hostName = checkAndConvertToCompatibleIPv6Syntax(host);
     this.url = new JMXServiceURL(MessageFormat.format(JMX_URL_FORMAT,
-        checkAndConvertToCompatibleIPv6Syntax(host), String.valueOf(port)));
+        hostName, String.valueOf(port)));
     this.connector = JMXConnectorFactory.connect(url, env);
     this.mbsc = connector.getMBeanServerConnection();
     this.connector.addConnectionNotificationListener(new 
JMXConnectionListener(this), null, null);
diff --git 
a/geode-membership/src/integrationTest/java/org/apache/geode/distributed/internal/membership/gms/locator/GMSLocatorRecoveryIntegrationTest.java
 
b/geode-membership/src/integrationTest/java/org/apache/geode/distributed/internal/membership/gms/locator/GMSLocatorRecoveryIntegrationTest.java
index 83163d6..f9b92cb 100644
--- 
a/geode-membership/src/integrationTest/java/org/apache/geode/distributed/internal/membership/gms/locator/GMSLocatorRecoveryIntegrationTest.java
+++ 
b/geode-membership/src/integrationTest/java/org/apache/geode/distributed/internal/membership/gms/locator/GMSLocatorRecoveryIntegrationTest.java
@@ -49,6 +49,7 @@ import 
org.apache.geode.distributed.internal.membership.gms.MemberIdentifierImpl
 import 
org.apache.geode.distributed.internal.membership.gms.MembershipLocatorStatisticsNoOp;
 import org.apache.geode.distributed.internal.membership.gms.Services;
 import 
org.apache.geode.distributed.internal.membership.gms.util.MemberIdentifierUtil;
+import org.apache.geode.distributed.internal.tcpserver.HostAddress;
 import org.apache.geode.distributed.internal.tcpserver.TcpClient;
 import org.apache.geode.distributed.internal.tcpserver.TcpServer;
 import org.apache.geode.distributed.internal.tcpserver.TcpSocketCreatorImpl;
@@ -154,7 +155,7 @@ public class GMSLocatorRecoveryIntegrationTest {
     final TcpSocketCreatorImpl socketCreator = new TcpSocketCreatorImpl();
     locator = MembershipLocatorBuilder.newLocatorBuilder(socketCreator, 
serializer,
         temporaryFolder.getRoot().toPath(), executorServiceSupplier)
-        .setBindAddress(localHost).create();
+        .setBindAddress(new HostAddress(localHost)).create();
     final int port = locator.start();
 
     try {
@@ -182,7 +183,7 @@ public class GMSLocatorRecoveryIntegrationTest {
 
       // now create a peer location handler that should recover from our real 
locator and know
       // that real locator's identifier
-      GMSLocator gmsLocator = new GMSLocator(localHost,
+      GMSLocator gmsLocator = new GMSLocator(new HostAddress(localHost),
           membership.getLocalMember().getHost() + "[" + port + "]", true, true,
           new MembershipLocatorStatisticsNoOp(), "", 
temporaryFolder.getRoot().toPath(),
           locatorClient,
diff --git 
a/geode-membership/src/integrationTest/java/org/apache/geode/distributed/internal/membership/gms/membership/GMSJoinLeaveJUnitTest.java
 
b/geode-membership/src/integrationTest/java/org/apache/geode/distributed/internal/membership/gms/membership/GMSJoinLeaveJUnitTest.java
index c2d3271..ff39fea 100644
--- 
a/geode-membership/src/integrationTest/java/org/apache/geode/distributed/internal/membership/gms/membership/GMSJoinLeaveJUnitTest.java
+++ 
b/geode-membership/src/integrationTest/java/org/apache/geode/distributed/internal/membership/gms/membership/GMSJoinLeaveJUnitTest.java
@@ -1533,7 +1533,7 @@ public class GMSJoinLeaveJUnitTest {
     assertThatThrownBy(gmsJoinLeave::join)
         .isInstanceOf(MembershipConfigurationException.class)
         .hasMessageContaining(
-            "Could not contact any of the locators: 
[HostAndPort[locator1:12345], HostAndPort[locator2:54321]]")
+            "Could not contact any of the locators: [locator1:12345, 
locator2:54321]")
         .hasCauseInstanceOf(IOException.class);
   }
 
diff --git 
a/geode-membership/src/main/java/org/apache/geode/distributed/internal/membership/api/MembershipLocatorBuilder.java
 
b/geode-membership/src/main/java/org/apache/geode/distributed/internal/membership/api/MembershipLocatorBuilder.java
index 3c7704c..131e1eb 100644
--- 
a/geode-membership/src/main/java/org/apache/geode/distributed/internal/membership/api/MembershipLocatorBuilder.java
+++ 
b/geode-membership/src/main/java/org/apache/geode/distributed/internal/membership/api/MembershipLocatorBuilder.java
@@ -14,13 +14,13 @@
  */
 package org.apache.geode.distributed.internal.membership.api;
 
-import java.net.InetAddress;
 import java.net.UnknownHostException;
 import java.nio.file.Path;
 import java.util.concurrent.ExecutorService;
 import java.util.function.Supplier;
 
 import 
org.apache.geode.distributed.internal.membership.gms.MembershipLocatorBuilderImpl;
+import org.apache.geode.distributed.internal.tcpserver.HostAddress;
 import org.apache.geode.distributed.internal.tcpserver.ProtocolChecker;
 import org.apache.geode.distributed.internal.tcpserver.TcpHandler;
 import org.apache.geode.distributed.internal.tcpserver.TcpSocketCreator;
@@ -29,7 +29,7 @@ import 
org.apache.geode.internal.serialization.DSFIDSerializer;
 public interface MembershipLocatorBuilder<ID extends MemberIdentifier> {
   MembershipLocatorBuilder<ID> setPort(int port);
 
-  MembershipLocatorBuilder<ID> setBindAddress(InetAddress bindAddress);
+  MembershipLocatorBuilder<ID> setBindAddress(HostAddress bindAddress);
 
   MembershipLocatorBuilder<ID> setConfig(MembershipConfig membershipConfig);
 
diff --git 
a/geode-membership/src/main/java/org/apache/geode/distributed/internal/membership/gms/GMSMemberData.java
 
b/geode-membership/src/main/java/org/apache/geode/distributed/internal/membership/gms/GMSMemberData.java
index 9f0ba77..cd7ea44 100644
--- 
a/geode-membership/src/main/java/org/apache/geode/distributed/internal/membership/gms/GMSMemberData.java
+++ 
b/geode-membership/src/main/java/org/apache/geode/distributed/internal/membership/gms/GMSMemberData.java
@@ -586,8 +586,6 @@ public class GMSMemberData implements MemberData, 
Comparable<GMSMemberData> {
 
     this.inetAddr = StaticSerialization.readInetAddress(in);
     if (this.inetAddr != null) {
-      // use address as hostname at this level. getHostName() will do a 
reverse-dns lookup,
-      // which is very expensive
       this.hostName = inetAddr.getHostAddress();
     }
     this.udpPort = in.readInt();
diff --git 
a/geode-membership/src/main/java/org/apache/geode/distributed/internal/membership/gms/MembershipLocatorBuilderImpl.java
 
b/geode-membership/src/main/java/org/apache/geode/distributed/internal/membership/gms/MembershipLocatorBuilderImpl.java
index 4ee8847..98be6b4 100644
--- 
a/geode-membership/src/main/java/org/apache/geode/distributed/internal/membership/gms/MembershipLocatorBuilderImpl.java
+++ 
b/geode-membership/src/main/java/org/apache/geode/distributed/internal/membership/gms/MembershipLocatorBuilderImpl.java
@@ -14,7 +14,6 @@
  */
 package org.apache.geode.distributed.internal.membership.gms;
 
-import java.net.InetAddress;
 import java.net.UnknownHostException;
 import java.nio.file.Path;
 import java.util.concurrent.ExecutorService;
@@ -27,6 +26,7 @@ import 
org.apache.geode.distributed.internal.membership.api.MembershipLocator;
 import 
org.apache.geode.distributed.internal.membership.api.MembershipLocatorBuilder;
 import 
org.apache.geode.distributed.internal.membership.api.MembershipLocatorStatistics;
 import 
org.apache.geode.distributed.internal.membership.gms.locator.MembershipLocatorImpl;
+import org.apache.geode.distributed.internal.tcpserver.HostAddress;
 import org.apache.geode.distributed.internal.tcpserver.ProtocolChecker;
 import org.apache.geode.distributed.internal.tcpserver.TcpHandler;
 import org.apache.geode.distributed.internal.tcpserver.TcpSocketCreator;
@@ -37,7 +37,7 @@ public final class MembershipLocatorBuilderImpl<ID extends 
MemberIdentifier> imp
     MembershipLocatorBuilder<ID> {
   private final DSFIDSerializer serializer;
   private int port = 0;
-  private InetAddress bindAddress = null;
+  private HostAddress bindAddress = null;
   private ProtocolChecker protocolChecker = (socket, input, firstByte) -> 
false;
   private TcpHandler fallbackHandler = new TcpHandlerNoOp();
   private MembershipLocatorStatistics locatorStats = new 
MembershipLocatorStatisticsNoOp();
@@ -65,7 +65,7 @@ public final class MembershipLocatorBuilderImpl<ID extends 
MemberIdentifier> imp
   }
 
   @Override
-  public MembershipLocatorBuilder<ID> setBindAddress(InetAddress bindAddress) {
+  public MembershipLocatorBuilder<ID> setBindAddress(HostAddress bindAddress) {
     this.bindAddress = bindAddress;
     return this;
   }
diff --git 
a/geode-membership/src/main/java/org/apache/geode/distributed/internal/membership/gms/locator/GMSLocator.java
 
b/geode-membership/src/main/java/org/apache/geode/distributed/internal/membership/gms/locator/GMSLocator.java
index c7c38b0..50e1e69 100644
--- 
a/geode-membership/src/main/java/org/apache/geode/distributed/internal/membership/gms/locator/GMSLocator.java
+++ 
b/geode-membership/src/main/java/org/apache/geode/distributed/internal/membership/gms/locator/GMSLocator.java
@@ -22,7 +22,6 @@ import java.io.FileOutputStream;
 import java.io.IOException;
 import java.io.ObjectInputStream;
 import java.io.ObjectOutputStream;
-import java.net.InetAddress;
 import java.nio.file.Path;
 import java.util.ArrayList;
 import java.util.Collection;
@@ -45,6 +44,7 @@ import 
org.apache.geode.distributed.internal.membership.gms.GMSUtil;
 import org.apache.geode.distributed.internal.membership.gms.Services;
 import org.apache.geode.distributed.internal.membership.gms.interfaces.Locator;
 import 
org.apache.geode.distributed.internal.membership.gms.messenger.GMSMemberWrapper;
+import org.apache.geode.distributed.internal.tcpserver.HostAddress;
 import org.apache.geode.distributed.internal.tcpserver.HostAndPort;
 import org.apache.geode.distributed.internal.tcpserver.TcpClient;
 import org.apache.geode.distributed.internal.tcpserver.TcpHandler;
@@ -108,7 +108,7 @@ public class GMSLocator<ID extends MemberIdentifier> 
implements Locator<ID>, Tcp
    * @param objectSerializer a serializer used to persist the membership view
    * @param objectDeserializer a deserializer used to recover the membership 
view
    */
-  public GMSLocator(InetAddress bindAddress, String locatorString, boolean 
usePreferredCoordinators,
+  public GMSLocator(HostAddress bindAddress, String locatorString, boolean 
usePreferredCoordinators,
       boolean networkPartitionDetectionEnabled, MembershipLocatorStatistics 
locatorStats,
       String securityUDPDHAlgo, Path workingDirectory, final TcpClient 
locatorClient,
       ObjectSerializer objectSerializer,
@@ -121,7 +121,8 @@ public class GMSLocator<ID extends MemberIdentifier> 
implements Locator<ID>, Tcp
     if (this.locatorString == null || this.locatorString.isEmpty()) {
       locators = new ArrayList<>(0);
     } else {
-      locators = GMSUtil.parseLocators(locatorString, bindAddress);
+      locators = GMSUtil.parseLocators(locatorString,
+          bindAddress == null ? null : bindAddress.getAddress());
     }
     this.locatorStats = locatorStats;
     this.workingDirectory = workingDirectory;
diff --git 
a/geode-membership/src/main/java/org/apache/geode/distributed/internal/membership/gms/locator/MembershipLocatorImpl.java
 
b/geode-membership/src/main/java/org/apache/geode/distributed/internal/membership/gms/locator/MembershipLocatorImpl.java
index d351d64..6a5d59a 100644
--- 
a/geode-membership/src/main/java/org/apache/geode/distributed/internal/membership/gms/locator/MembershipLocatorImpl.java
+++ 
b/geode-membership/src/main/java/org/apache/geode/distributed/internal/membership/gms/locator/MembershipLocatorImpl.java
@@ -38,6 +38,7 @@ import 
org.apache.geode.distributed.internal.membership.api.MembershipLocator;
 import 
org.apache.geode.distributed.internal.membership.api.MembershipLocatorStatistics;
 import org.apache.geode.distributed.internal.membership.gms.GMSMembership;
 import org.apache.geode.distributed.internal.membership.gms.Services;
+import org.apache.geode.distributed.internal.tcpserver.HostAddress;
 import org.apache.geode.distributed.internal.tcpserver.HostAndPort;
 import org.apache.geode.distributed.internal.tcpserver.ProtocolChecker;
 import org.apache.geode.distributed.internal.tcpserver.TcpClient;
@@ -61,7 +62,7 @@ public class MembershipLocatorImpl<ID extends 
MemberIdentifier> implements Membe
   private final GMSLocator<ID> gmsLocator;
   private final TcpClient locatorClient;
 
-  public MembershipLocatorImpl(int port, InetAddress bindAddress,
+  public MembershipLocatorImpl(int port, HostAddress bindAddress,
       ProtocolChecker protocolChecker,
       Supplier<ExecutorService> executorServiceSupplier,
       TcpSocketCreator socketCreator,
@@ -77,9 +78,10 @@ public class MembershipLocatorImpl<ID extends 
MemberIdentifier> implements Membe
             () -> System.currentTimeMillis(), x -> Thread.sleep(x));
     String host = bindAddress == null ? LocalHostUtil.getLocalHostName()
         : bindAddress.getHostName();
+    InetAddress inetAddress = bindAddress == null ? null : 
bindAddress.getAddress();
     String threadName = "Distribution Locator on " + host + ": " + port;
 
-    this.server = new TcpServer(port, bindAddress, handler,
+    this.server = new TcpServer(port, inetAddress, handler,
         threadName, protocolChecker,
         locatorStats::getStatTime,
         executorServiceSupplier,
@@ -93,7 +95,7 @@ public class MembershipLocatorImpl<ID extends 
MemberIdentifier> implements Membe
         objectSerializer,
         objectDeserializer, Socket::new);
     gmsLocator =
-        new GMSLocator<>(bindAddress, config.getLocators(), 
locatorsAreCoordinators,
+        new GMSLocator<ID>(bindAddress, config.getLocators(), 
locatorsAreCoordinators,
             config.isNetworkPartitionDetectionEnabled(),
             locatorStats, config.getSecurityUDPDHAlgo(), workingDirectory, 
locatorClient,
             objectSerializer,
diff --git 
a/geode-membership/src/main/java/org/apache/geode/distributed/internal/membership/gms/messenger/JGroupsMessenger.java
 
b/geode-membership/src/main/java/org/apache/geode/distributed/internal/membership/gms/messenger/JGroupsMessenger.java
index 9120acf..12b98a8 100644
--- 
a/geode-membership/src/main/java/org/apache/geode/distributed/internal/membership/gms/messenger/JGroupsMessenger.java
+++ 
b/geode-membership/src/main/java/org/apache/geode/distributed/internal/membership/gms/messenger/JGroupsMessenger.java
@@ -558,9 +558,10 @@ public class JGroupsMessenger<ID extends MemberIdentifier> 
implements Messenger<
         || !config.getStartLocator().isEmpty();
 
     // establish the DistributedSystem's address
-    String hostname =
-        !config.isNetworkPartitionDetectionEnabled() ? 
jgAddress.getInetAddress().getHostName()
-            : jgAddress.getInetAddress().getHostAddress();
+    String hostname = config.getBindAddress();
+    if (hostname == null || hostname.isEmpty()) {
+      hostname = jgAddress.getInetAddress().getHostName();
+    }
     GMSMemberData gmsMember = new GMSMemberData(jgAddress.getInetAddress(),
         hostname, jgAddress.getPort(),
         OSProcess.getId(), (byte) services.getConfig().getVmKind(),
diff --git 
a/geode-tcp-server/src/main/java/org/apache/geode/distributed/internal/tcpserver/HostAddress.java
 
b/geode-tcp-server/src/main/java/org/apache/geode/distributed/internal/tcpserver/HostAddress.java
new file mode 100644
index 0000000..9f32dfd
--- /dev/null
+++ 
b/geode-tcp-server/src/main/java/org/apache/geode/distributed/internal/tcpserver/HostAddress.java
@@ -0,0 +1,56 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more 
contributor license
+ * agreements. See the NOTICE file distributed with this work for additional 
information regarding
+ * copyright ownership. The ASF licenses this file to You under the Apache 
License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance with the 
License. You may obtain a
+ * copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software 
distributed under the License
+ * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 
KIND, either express
+ * or implied. See the License for the specific language governing permissions 
and limitations under
+ * the License.
+ */
+package org.apache.geode.distributed.internal.tcpserver;
+
+import java.net.InetAddress;
+import java.net.InetSocketAddress;
+
+
+/**
+ * HostAddress is a holder of a host name/address. It is the primary
+ * way to specify a host address that may or may not be resolvable to an 
InetAddress.
+ * <p>
+ * This class preserves the hostName string passed in to its constructor that 
takes a
+ * hostName string and will respond with that string when asked for a hostName.
+ *
+ * @See HostAndPort which can hold both a host name and a port
+ */
+public class HostAddress extends InetSocketWrapper {
+
+  public HostAddress(String hostName) {
+    super(hostName, 0);
+  }
+
+  public HostAddress(InetAddress address) {
+    if (address == null) {
+      throw new IllegalArgumentException("null parameters are not allowed");
+    }
+    inetSocketAddress = new InetSocketAddress(address, 0);
+  }
+
+  public HostAddress(HostAndPort hostAndPort) {
+    hostName = hostAndPort.hostName;
+    inetSocketAddress = hostAndPort.inetSocketAddress;
+  }
+
+  @Override
+  public String toString() {
+    if (hostName != null) {
+      return hostName;
+    } else {
+      return inetSocketAddress.getAddress().toString();
+    }
+  }
+}
diff --git 
a/geode-tcp-server/src/main/java/org/apache/geode/distributed/internal/tcpserver/HostAndPort.java
 
b/geode-tcp-server/src/main/java/org/apache/geode/distributed/internal/tcpserver/HostAndPort.java
index 6bc062f..072fd5a 100644
--- 
a/geode-tcp-server/src/main/java/org/apache/geode/distributed/internal/tcpserver/HostAndPort.java
+++ 
b/geode-tcp-server/src/main/java/org/apache/geode/distributed/internal/tcpserver/HostAndPort.java
@@ -19,9 +19,6 @@ import java.io.DataOutput;
 import java.io.IOException;
 import java.net.InetAddress;
 import java.net.InetSocketAddress;
-import java.util.Objects;
-
-import org.apache.commons.validator.routines.InetAddressValidator;
 
 import org.apache.geode.internal.serialization.DataSerializableFixedID;
 import org.apache.geode.internal.serialization.DeserializationContext;
@@ -33,6 +30,9 @@ import 
org.apache.geode.internal.serialization.StaticSerialization;
  * HostAndPort is a holder of a host name/address and a port. It is the primary
  * way to specify a connection endpoint in the socket-creator methods.
  * <p>
+ * This class preserves the hostName string passed in to its constructor that 
takes a
+ * hostName string and will respond with that string when asked for a hostName.
+ * <p>
  * Note: This class is serializable for testing. A number of client/server and 
WAN tests
  * transmit PoolAttributes between unit test JVMs using RMI. PoolAttributes are
  * Externalizable for this purpose and use Geode serialization to transmit 
HostAndPort
@@ -43,73 +43,20 @@ import 
org.apache.geode.internal.serialization.StaticSerialization;
  * @see ClientSocketCreator
  * @see AdvancedSocketCreator
  * @see TcpClient
+ * @see HostAddress
  */
-public class HostAndPort implements DataSerializableFixedID {
-
-  private InetSocketAddress socketInetAddress;
+public class HostAndPort extends InetSocketWrapper implements 
DataSerializableFixedID {
 
   public HostAndPort() {
     // serialization constructor
   }
 
   public HostAndPort(String hostName, int port) {
-    if (hostName == null) {
-      socketInetAddress = new InetSocketAddress(port);
-    } else if (InetAddressValidator.getInstance().isValid(hostName)) {
-      // numeric address - use as-is
-      socketInetAddress = new InetSocketAddress(hostName, port);
-    } else {
-      // non-numeric address - resolve hostname when needed
-      socketInetAddress = InetSocketAddress.createUnresolved(hostName, port);
-    }
-  }
-
-  /**
-   * Returns an InetSocketAddress for this host and port. An attempt is made 
to resolve the
-   * host name but if resolution fails an unresolved InetSocketAddress is 
returned. This return
-   * value will not hold an InetAddress, so calling getAddress() on it will 
return null.
-   */
-  public InetSocketAddress getSocketInetAddress() {
-    if (socketInetAddress.isUnresolved()) {
-      // note that this leaves the InetAddress null if the hostname isn't 
resolvable
-      return new InetSocketAddress(socketInetAddress.getHostString(), 
socketInetAddress.getPort());
-    } else {
-      return this.socketInetAddress;
-    }
-  }
-
-  public String getHostName() {
-    return socketInetAddress.getHostString();
+    super(hostName, port);
   }
 
   public int getPort() {
-    return socketInetAddress.getPort();
-  }
-
-  @Override
-  public int hashCode() {
-    return socketInetAddress.hashCode();
-  }
-
-  @Override
-  public boolean equals(Object o) {
-    if (this == o) {
-      return true;
-    }
-    if (o == null || getClass() != o.getClass()) {
-      return false;
-    }
-    HostAndPort that = (HostAndPort) o;
-    return Objects.equals(socketInetAddress, that.socketInetAddress);
-  }
-
-  @Override
-  public String toString() {
-    return getClass().getSimpleName() + "[" + socketInetAddress + "]";
-  }
-
-  public InetAddress getAddress() {
-    return getSocketInetAddress().getAddress();
+    return inetSocketAddress.getPort();
   }
 
   @Override
@@ -119,13 +66,13 @@ public class HostAndPort implements 
DataSerializableFixedID {
 
   @Override
   public void toData(DataOutput out, SerializationContext context) throws 
IOException {
-    if (socketInetAddress.isUnresolved()) {
+    if (inetSocketAddress.isUnresolved()) {
       out.writeByte(0);
       StaticSerialization.writeString(getHostName(), out);
       out.writeInt(getPort());
     } else {
       out.writeByte(1);
-      StaticSerialization.writeInetAddress(socketInetAddress.getAddress(), 
out);
+      StaticSerialization.writeInetAddress(inetSocketAddress.getAddress(), 
out);
       out.writeInt(getPort());
     }
   }
@@ -133,20 +80,20 @@ public class HostAndPort implements 
DataSerializableFixedID {
   @Override
   public void fromData(DataInput in, DeserializationContext context)
       throws IOException, ClassNotFoundException {
-    InetAddress address = null;
+    InetAddress address;
     byte flags = in.readByte();
     if ((flags & 1) == 0) {
       String hostName = StaticSerialization.readString(in);
       int port = in.readInt();
       if (hostName == null || hostName.isEmpty()) {
-        socketInetAddress = new InetSocketAddress(port);
+        inetSocketAddress = new InetSocketAddress(port);
       } else {
-        socketInetAddress = InetSocketAddress.createUnresolved(hostName, port);
+        inetSocketAddress = InetSocketAddress.createUnresolved(hostName, port);
       }
     } else {
       address = StaticSerialization.readInetAddress(in);
       int port = in.readInt();
-      socketInetAddress = new InetSocketAddress(address, port);
+      inetSocketAddress = new InetSocketAddress(address, port);
     }
   }
 
@@ -154,6 +101,4 @@ public class HostAndPort implements DataSerializableFixedID 
{
   public KnownVersion[] getSerializationVersions() {
     return null;
   }
-
-
 }
diff --git 
a/geode-tcp-server/src/main/java/org/apache/geode/distributed/internal/tcpserver/InetSocketWrapper.java
 
b/geode-tcp-server/src/main/java/org/apache/geode/distributed/internal/tcpserver/InetSocketWrapper.java
new file mode 100644
index 0000000..168fc3f
--- /dev/null
+++ 
b/geode-tcp-server/src/main/java/org/apache/geode/distributed/internal/tcpserver/InetSocketWrapper.java
@@ -0,0 +1,100 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more 
contributor license
+ * agreements. See the NOTICE file distributed with this work for additional 
information regarding
+ * copyright ownership. The ASF licenses this file to You under the Apache 
License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance with the 
License. You may obtain a
+ * copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software 
distributed under the License
+ * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 
KIND, either express
+ * or implied. See the License for the specific language governing permissions 
and limitations under
+ * the License.
+ */
+package org.apache.geode.distributed.internal.tcpserver;
+
+import java.net.InetAddress;
+import java.net.InetSocketAddress;
+import java.util.Objects;
+
+import org.apache.commons.validator.routines.InetAddressValidator;
+
+class InetSocketWrapper {
+  String hostName;
+  protected InetSocketAddress inetSocketAddress;
+  private InetSocketAddress attemptedToResolve;
+
+  protected InetSocketWrapper() {}
+
+  protected InetSocketWrapper(String hostName, int port) {
+    // preserve the hostName string since InetSocketAddress will throw it away 
if it's a numeric
+    // address. Invoking getHostName on the InetSocketAddress would possibly 
return a different
+    // string.
+    this.hostName = hostName;
+    if (hostName == null) {
+      inetSocketAddress = new InetSocketAddress(port);
+    } else if (InetAddressValidator.getInstance().isValid(hostName)) {
+      // numeric address - use as-is
+      inetSocketAddress = new InetSocketAddress(hostName, port);
+    } else {
+      // non-numeric address - resolve hostname when needed
+      inetSocketAddress = InetSocketAddress.createUnresolved(hostName, port);
+    }
+  }
+
+  public String getHostName() {
+    if (hostName != null) {
+      return hostName;
+    }
+    return inetSocketAddress.getHostName();
+  }
+
+  public InetAddress getAddress() {
+    return getSocketInetAddress().getAddress();
+  }
+
+  @Override
+  public int hashCode() {
+    return inetSocketAddress.hashCode();
+  }
+
+  @Override
+  public boolean equals(Object o) {
+    if (this == o) {
+      return true;
+    }
+    if (o == null || getClass() != o.getClass()) {
+      return false;
+    }
+    InetSocketWrapper that = (InetSocketWrapper) o;
+    return Objects.equals(inetSocketAddress, that.inetSocketAddress);
+  }
+
+  /**
+   * Returns an InetSocketAddress for this host and port. An attempt is made 
to resolve the
+   * host name but if resolution fails an unresolved InetSocketAddress is 
returned. This return
+   * value will not hold an InetAddress, so calling getAddress() on it will 
return null.
+   */
+  public InetSocketAddress getSocketInetAddress() {
+    if (attemptedToResolve == null) {
+      attemptedToResolve = basicGetInetSocketAddress();
+    }
+    return attemptedToResolve;
+  }
+
+  private InetSocketAddress basicGetInetSocketAddress() {
+    if (inetSocketAddress.isUnresolved()) {
+      // note that this leaves the InetAddress null if the hostname isn't 
resolvable
+      return new InetSocketAddress(inetSocketAddress.getHostString(), 
inetSocketAddress.getPort());
+    } else {
+      return inetSocketAddress;
+    }
+  }
+
+  @Override
+  public String toString() {
+    return inetSocketAddress.toString();
+  }
+
+}
diff --git 
a/geode-wan/src/distributedTest/java/org/apache/geode/internal/cache/wan/WANTestBase.java
 
b/geode-wan/src/distributedTest/java/org/apache/geode/internal/cache/wan/WANTestBase.java
index 413dcad..cc745d8 100644
--- 
a/geode-wan/src/distributedTest/java/org/apache/geode/internal/cache/wan/WANTestBase.java
+++ 
b/geode-wan/src/distributedTest/java/org/apache/geode/internal/cache/wan/WANTestBase.java
@@ -52,7 +52,6 @@ import static org.junit.Assert.fail;
 import java.io.File;
 import java.io.IOException;
 import java.io.Serializable;
-import java.net.InetAddress;
 import java.net.InetSocketAddress;
 import java.util.ArrayList;
 import java.util.Arrays;
@@ -382,7 +381,7 @@ public class WANTestBase extends DistributedTestCase {
     props.setProperty(DISTRIBUTED_SYSTEM_ID, "" + dsId);
     props.setProperty(LOCATORS, "localhost[" + localPort + "]");
     props.setProperty(REMOTE_LOCATORS, "localhost[" + remoteLocPort + "]");
-    Locator locator = Locator.startLocatorAndDS(0, null, 
InetAddress.getByName("0.0.0.0"), props,
+    Locator locator = Locator.startLocatorAndDS(0, null, null, props,
         true, true, hostnameForClients);
     return locator.getPort();
   }

Reply via email to