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

vy pushed a commit to branch verifyHostName
in repository https://gitbox.apache.org/repos/asf/logging-log4j2.git

commit bc40056ffd0ead76b31c5f629b82ab7c2962974f
Author: Volkan Yazıcı <[email protected]>
AuthorDate: Tue Dec 2 10:46:05 2025 +0100

    Fix host name verification in `SslSocketManager`
---
 .../log4j/core/net/ssl/SslSocketManagerTest.java   |   62 +-
 .../net/ssl/internal/InetAddressValidatorTest.java | 1082 ++++++++++++++++++++
 .../logging/log4j/core/net/SslSocketManager.java   |   61 +-
 .../log4j/core/net/ssl/SslConfiguration.java       |   12 +-
 .../net/ssl/internal/InetAddressValidator.java     |  171 ++++
 5 files changed, 1356 insertions(+), 32 deletions(-)

diff --git 
a/log4j-core-test/src/test/java/org/apache/logging/log4j/core/net/ssl/SslSocketManagerTest.java
 
b/log4j-core-test/src/test/java/org/apache/logging/log4j/core/net/ssl/SslSocketManagerTest.java
index 85db9e8f0c..e9a748202c 100644
--- 
a/log4j-core-test/src/test/java/org/apache/logging/log4j/core/net/ssl/SslSocketManagerTest.java
+++ 
b/log4j-core-test/src/test/java/org/apache/logging/log4j/core/net/ssl/SslSocketManagerTest.java
@@ -16,30 +16,64 @@
  */
 package org.apache.logging.log4j.core.net.ssl;
 
-import static org.junit.jupiter.api.Assertions.assertDoesNotThrow;
+import static org.assertj.core.api.Assertions.assertThat;
+import static org.assertj.core.api.Assertions.assertThatCode;
 
+import javax.net.ssl.SNIHostName;
+import javax.net.ssl.SSLParameters;
+import javax.net.ssl.SSLSocket;
+import org.apache.logging.log4j.core.Layout;
 import org.apache.logging.log4j.core.layout.PatternLayout;
 import org.apache.logging.log4j.core.net.SslSocketManager;
+import org.apache.logging.log4j.test.junit.UsingStatusListener;
 import org.junit.jupiter.api.Test;
 import org.junitpioneer.jupiter.Issue;
 
 class SslSocketManagerTest {
-    @Issue("https://github.com/apache/logging-log4j2/issues/3947";)
+
+    private static final String HOST_NAME = "apache.org";
+
+    private static final int HOST_PORT = 443;
+
+    private static final Layout<?> LAYOUT = 
PatternLayout.createDefaultLayout();
+
     @Test
-    void shouldNotThrowExceptionWhenConfiguringTrustStore() {
-        final TrustStoreConfiguration trustStoreConfiguration = 
assertDoesNotThrow(() -> new TrustStoreConfiguration(
+    @Issue("https://github.com/apache/logging-log4j2/issues/3947";)
+    @UsingStatusListener // Suppresses `StatusLogger` output, unless there is 
a failure
+    void should_not_throw_exception_when_configuration_without_KeyStore() 
throws Exception {
+        final TrustStoreConfiguration trustStoreConfig = new 
TrustStoreConfiguration(
                 SslKeyStoreConstants.TRUSTSTORE_LOCATION,
                 SslKeyStoreConstants::TRUSTSTORE_PWD,
                 SslKeyStoreConstants.TRUSTSTORE_TYPE,
-                null));
-        final SslConfiguration sslConfiguration =
-                SslConfiguration.createSSLConfiguration(null, null, 
trustStoreConfiguration);
-        assertDoesNotThrow(() -> {
-            // noinspection EmptyTryBlock (try-with-resources to close 
`SslSocketManager`, even on failure
-            try (final SslSocketManager ignored = 
SslSocketManager.getSocketManager(
-                    sslConfiguration, "localhost", 0, 0, 0, true, 
PatternLayout.createDefaultLayout(), 8192, null)) {
-                // Do nothing
-            }
-        });
+                null);
+        final SslConfiguration sslConfig = 
SslConfiguration.createSSLConfiguration(null, null, trustStoreConfig);
+        assertThatCode(() -> {
+                    // noinspection EmptyTryBlock
+                    try (final SslSocketManager ignored = 
createSocketManager(sslConfig)) {
+                        // Do nothing
+                    }
+                })
+                .doesNotThrowAnyException();
+    }
+
+    @Test
+    void host_name_verification_should_take_effect() {
+        final SslConfiguration sslConfig = 
SslConfiguration.createSSLConfiguration(
+                null,
+                null,
+                null,
+                // Explicitly enable hostname verification
+                true);
+        try (final SslSocketManager ssm = createSocketManager(sslConfig)) {
+            final SSLSocket sslSocket = (SSLSocket) ssm.getSocket();
+            final SSLParameters sslParams = sslSocket.getSSLParameters();
+            
assertThat(sslParams.getEndpointIdentificationAlgorithm()).isEqualTo("HTTPS");
+            assertThat(sslParams.getServerNames()).containsOnly(new 
SNIHostName(HOST_NAME));
+        }
+    }
+
+    private static SslSocketManager createSocketManager(final SslConfiguration 
sslConfig) {
+        return SslSocketManager.getSocketManager(
+                sslConfig, SslSocketManagerTest.HOST_NAME, HOST_PORT, 0, 0, 
true, LAYOUT, 8192, null);
     }
 }
diff --git 
a/log4j-core-test/src/test/java/org/apache/logging/log4j/core/net/ssl/internal/InetAddressValidatorTest.java
 
b/log4j-core-test/src/test/java/org/apache/logging/log4j/core/net/ssl/internal/InetAddressValidatorTest.java
new file mode 100644
index 0000000000..4cb3be2eaf
--- /dev/null
+++ 
b/log4j-core-test/src/test/java/org/apache/logging/log4j/core/net/ssl/internal/InetAddressValidatorTest.java
@@ -0,0 +1,1082 @@
+/*
+ * 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.logging.log4j.core.net.ssl.internal;
+
+import static 
org.apache.logging.log4j.core.net.ssl.internal.InetAddressValidator.isValid;
+import static 
org.apache.logging.log4j.core.net.ssl.internal.InetAddressValidator.isValidInet6Address;
+import static org.junit.jupiter.api.Assertions.assertFalse;
+import static org.junit.jupiter.api.Assertions.assertTrue;
+
+import org.junit.jupiter.api.Test;
+
+/**
+ * @see <a 
href="https://github.com/apache/commons-validator/blob/7c27355d86f7dc5a4a548658745b85c9f0d5b99f/src/test/java/org/apache/commons/validator/routines/InetAddressValidatorTest.java";><code>InetAddressValidatorTest</code>
 of Apache Commons Validator</a>
+ */
+class InetAddressValidatorTest {
+
+    /**
+     * Test obviously broken IPs.
+     */
+    @Test
+    void testBrokenInetAddresses() {
+        assertFalse(isValid("124.14.32.abc"), "IP with characters should be 
invalid");
+        // TODO: there is some debate as to whether leading zeros should be 
allowed
+        // They are ambiguous: does the leading 0 mean octal?
+        assertFalse(isValid("124.14.32.01"), "IP with leading zeroes should be 
invalid");
+        assertFalse(isValid("23.64.12"), "IP with three groups should be 
invalid");
+        assertFalse(isValid("26.34.23.77.234"), "IP with five groups should be 
invalid");
+        assertFalse(isValidInet6Address(""), "IP empty string should be 
invalid"); // empty string
+    }
+
+    /**
+     * Test valid and invalid IPs from each address class.
+     */
+    @Test
+    void testInetAddressesByClass() {
+        assertTrue(isValid("24.25.231.12"), "class A IP should be valid");
+        assertFalse(isValid("2.41.32.324"), "illegal class A IP should be 
invalid");
+
+        assertTrue(isValid("135.14.44.12"), "class B IP should be valid");
+        assertFalse(isValid("154.123.441.123"), "illegal class B IP should be 
invalid");
+
+        assertTrue(isValid("213.25.224.32"), "class C IP should be valid");
+        assertFalse(isValid("201.543.23.11"), "illegal class C IP should be 
invalid");
+
+        assertTrue(isValid("229.35.159.6"), "class D IP should be valid");
+        assertFalse(isValid("231.54.11.987"), "illegal class D IP should be 
invalid");
+
+        assertTrue(isValid("248.85.24.92"), "class E IP should be valid");
+        assertFalse(isValid("250.21.323.48"), "illegal class E IP should be 
invalid");
+    }
+
+    /**
+     * Test IPs that point to real, well-known hosts (without actually looking 
them up).
+     */
+    @Test
+    void testInetAddressesFromTheWild() {
+        assertTrue(isValid("140.211.11.130"), "www.apache.org IP should be 
valid");
+        assertTrue(isValid("72.14.253.103"), "www.l.google.com IP should be 
valid");
+        assertTrue(isValid("199.232.41.5"), "fsf.org IP should be valid");
+        assertTrue(isValid("216.35.123.87"), "appscs.ign.com IP should be 
valid");
+    }
+
+    /**
+     * Test IPv6 addresses.
+     * <p>
+     * These tests were ported from a <a 
href="https://download.dartware.com/thirdparty/test-ipv6-regex.pl";>Perl 
script</a>.
+     * </p>
+     */
+    @Test
+    void testIPv6() {
+        // The original Perl script contained a lot of duplicate tests.
+        // I removed the duplicates I noticed, but there may be more.
+        assertFalse(isValidInet6Address(""), "IPV6 empty string should be 
invalid"); // empty string
+        assertTrue(isValidInet6Address("::1"), "IPV6 ::1 should be valid"); // 
loopback, compressed, non-routable
+        assertTrue(isValidInet6Address("::"), "IPV6 :: should be valid"); // 
unspecified, compressed, non-routable
+        assertTrue(isValidInet6Address("0:0:0:0:0:0:0:1"), "IPV6 
0:0:0:0:0:0:0:1 should be valid"); // loopback, full
+        assertTrue(isValidInet6Address("0:0:0:0:0:0:0:0"), "IPV6 
0:0:0:0:0:0:0:0 should be valid"); // unspecified, full
+        assertTrue(
+                isValidInet6Address("2001:DB8:0:0:8:800:200C:417A"),
+                "IPV6 2001:DB8:0:0:8:800:200C:417A should be valid"); // 
unicast, full
+        assertTrue(
+                isValidInet6Address("FF01:0:0:0:0:0:0:101"),
+                "IPV6 FF01:0:0:0:0:0:0:101 should be valid"); // multicast, 
full
+        assertTrue(
+                isValidInet6Address("2001:DB8::8:800:200C:417A"),
+                "IPV6 2001:DB8::8:800:200C:417A should be valid"); // unicast, 
compressed
+        assertTrue(isValidInet6Address("FF01::101"), "IPV6 FF01::101 should be 
valid"); // multicast, compressed
+        assertFalse(
+                isValidInet6Address("2001:DB8:0:0:8:800:200C:417A:221"),
+                "IPV6 2001:DB8:0:0:8:800:200C:417A:221 should be invalid"); // 
unicast,
+        // full
+        assertFalse(
+                isValidInet6Address("FF01::101::2"), "IPV6 FF01::101::2 should 
be invalid"); // multicast, compressed
+        assertTrue(isValidInet6Address("fe80::217:f2ff:fe07:ed62"), "IPV6 
fe80::217:f2ff:fe07:ed62 should be valid");
+        assertTrue(
+                isValidInet6Address("2001:0000:1234:0000:0000:C1C0:ABCD:0876"),
+                "IPV6 2001:0000:1234:0000:0000:C1C0:ABCD:0876 should be 
valid");
+        assertTrue(
+                isValidInet6Address("3ffe:0b00:0000:0000:0001:0000:0000:000a"),
+                "IPV6 3ffe:0b00:0000:0000:0001:0000:0000:000a should be 
valid");
+        assertTrue(
+                isValidInet6Address("FF02:0000:0000:0000:0000:0000:0000:0001"),
+                "IPV6 FF02:0000:0000:0000:0000:0000:0000:0001 should be 
valid");
+        assertTrue(
+                isValidInet6Address("0000:0000:0000:0000:0000:0000:0000:0001"),
+                "IPV6 0000:0000:0000:0000:0000:0000:0000:0001 should be 
valid");
+        assertTrue(
+                isValidInet6Address("0000:0000:0000:0000:0000:0000:0000:0000"),
+                "IPV6 0000:0000:0000:0000:0000:0000:0000:0000 should be 
valid");
+        assertFalse(
+                
isValidInet6Address("02001:0000:1234:0000:0000:C1C0:ABCD:0876"),
+                "IPV6 02001:0000:1234:0000:0000:C1C0:ABCD:0876 should be 
invalid"); // extra 0 not allowed!
+        assertFalse(
+                
isValidInet6Address("2001:0000:1234:0000:00001:C1C0:ABCD:0876"),
+                "IPV6 2001:0000:1234:0000:00001:C1C0:ABCD:0876 should be 
invalid"); // extra 0 not allowed!
+        assertFalse(
+                isValidInet6Address("2001:0000:1234:0000:0000:C1C0:ABCD:0876 
0"),
+                "IPV6 2001:0000:1234:0000:0000:C1C0:ABCD:0876 0 should be 
invalid"); // junk after valid address
+        assertFalse(
+                isValidInet6Address("2001:0000:1234: 
0000:0000:C1C0:ABCD:0876"),
+                "IPV6 2001:0000:1234: 0000:0000:C1C0:ABCD:0876 should be 
invalid"); // internal space
+        assertFalse(
+                isValidInet6Address("3ffe:0b00:0000:0001:0000:0000:000a"),
+                "IPV6 3ffe:0b00:0000:0001:0000:0000:000a should be invalid"); 
// seven
+        // segments
+        assertFalse(
+                
isValidInet6Address("FF02:0000:0000:0000:0000:0000:0000:0000:0001"),
+                "IPV6 FF02:0000:0000:0000:0000:0000:0000:0000:0001 should be 
invalid"); // nine segments
+        assertFalse(isValidInet6Address("3ffe:b00::1::a"), "IPV6 
3ffe:b00::1::a should be invalid"); // double "::"
+        assertFalse(
+                isValidInet6Address("::1111:2222:3333:4444:5555:6666::"),
+                "IPV6 ::1111:2222:3333:4444:5555:6666:: should be invalid"); 
// double
+        // "::"
+        assertTrue(isValidInet6Address("2::10"), "IPV6 2::10 should be valid");
+        assertTrue(isValidInet6Address("ff02::1"), "IPV6 ff02::1 should be 
valid");
+        assertTrue(isValidInet6Address("fe80::"), "IPV6 fe80:: should be 
valid");
+        assertTrue(isValidInet6Address("2002::"), "IPV6 2002:: should be 
valid");
+        assertTrue(isValidInet6Address("2001:db8::"), "IPV6 2001:db8:: should 
be valid");
+        assertTrue(isValidInet6Address("2001:0db8:1234::"), "IPV6 
2001:0db8:1234:: should be valid");
+        assertTrue(isValidInet6Address("::ffff:0:0"), "IPV6 ::ffff:0:0 should 
be valid");
+        assertTrue(isValidInet6Address("1:2:3:4:5:6:7:8"), "IPV6 
1:2:3:4:5:6:7:8 should be valid");
+        assertTrue(isValidInet6Address("1:2:3:4:5:6::8"), "IPV6 1:2:3:4:5:6::8 
should be valid");
+        assertTrue(isValidInet6Address("1:2:3:4:5::8"), "IPV6 1:2:3:4:5::8 
should be valid");
+        assertTrue(isValidInet6Address("1:2:3:4::8"), "IPV6 1:2:3:4::8 should 
be valid");
+        assertTrue(isValidInet6Address("1:2:3::8"), "IPV6 1:2:3::8 should be 
valid");
+        assertTrue(isValidInet6Address("1:2::8"), "IPV6 1:2::8 should be 
valid");
+        assertTrue(isValidInet6Address("1::8"), "IPV6 1::8 should be valid");
+        assertTrue(isValidInet6Address("1::2:3:4:5:6:7"), "IPV6 1::2:3:4:5:6:7 
should be valid");
+        assertTrue(isValidInet6Address("1::2:3:4:5:6"), "IPV6 1::2:3:4:5:6 
should be valid");
+        assertTrue(isValidInet6Address("1::2:3:4:5"), "IPV6 1::2:3:4:5 should 
be valid");
+        assertTrue(isValidInet6Address("1::2:3:4"), "IPV6 1::2:3:4 should be 
valid");
+        assertTrue(isValidInet6Address("1::2:3"), "IPV6 1::2:3 should be 
valid");
+        assertTrue(isValidInet6Address("::2:3:4:5:6:7:8"), "IPV6 
::2:3:4:5:6:7:8 should be valid");
+        assertTrue(isValidInet6Address("::2:3:4:5:6:7"), "IPV6 ::2:3:4:5:6:7 
should be valid");
+        assertTrue(isValidInet6Address("::2:3:4:5:6"), "IPV6 ::2:3:4:5:6 
should be valid");
+        assertTrue(isValidInet6Address("::2:3:4:5"), "IPV6 ::2:3:4:5 should be 
valid");
+        assertTrue(isValidInet6Address("::2:3:4"), "IPV6 ::2:3:4 should be 
valid");
+        assertTrue(isValidInet6Address("::2:3"), "IPV6 ::2:3 should be valid");
+        assertTrue(isValidInet6Address("::8"), "IPV6 ::8 should be valid");
+        assertTrue(isValidInet6Address("1:2:3:4:5:6::"), "IPV6 1:2:3:4:5:6:: 
should be valid");
+        assertTrue(isValidInet6Address("1:2:3:4:5::"), "IPV6 1:2:3:4:5:: 
should be valid");
+        assertTrue(isValidInet6Address("1:2:3:4::"), "IPV6 1:2:3:4:: should be 
valid");
+        assertTrue(isValidInet6Address("1:2:3::"), "IPV6 1:2:3:: should be 
valid");
+        assertTrue(isValidInet6Address("1:2::"), "IPV6 1:2:: should be valid");
+        assertTrue(isValidInet6Address("1::"), "IPV6 1:: should be valid");
+        assertTrue(isValidInet6Address("1:2:3:4:5::7:8"), "IPV6 1:2:3:4:5::7:8 
should be valid");
+        assertFalse(isValidInet6Address("1:2:3::4:5::7:8"), "IPV6 
1:2:3::4:5::7:8 should be invalid"); // Double "::"
+        assertFalse(isValidInet6Address("12345::6:7:8"), "IPV6 12345::6:7:8 
should be invalid");
+        assertTrue(isValidInet6Address("1:2:3:4::7:8"), "IPV6 1:2:3:4::7:8 
should be valid");
+        assertTrue(isValidInet6Address("1:2:3::7:8"), "IPV6 1:2:3::7:8 should 
be valid");
+        assertTrue(isValidInet6Address("1:2::7:8"), "IPV6 1:2::7:8 should be 
valid");
+        assertTrue(isValidInet6Address("1::7:8"), "IPV6 1::7:8 should be 
valid");
+        // IPv4 addresses as dotted-quads
+        assertTrue(isValidInet6Address("1:2:3:4:5:6:1.2.3.4"), "IPV6 
1:2:3:4:5:6:1.2.3.4 should be valid");
+        assertTrue(isValidInet6Address("1:2:3:4:5::1.2.3.4"), "IPV6 
1:2:3:4:5::1.2.3.4 should be valid");
+        assertTrue(isValidInet6Address("1:2:3:4::1.2.3.4"), "IPV6 
1:2:3:4::1.2.3.4 should be valid");
+        assertTrue(isValidInet6Address("1:2:3::1.2.3.4"), "IPV6 1:2:3::1.2.3.4 
should be valid");
+        assertTrue(isValidInet6Address("1:2::1.2.3.4"), "IPV6 1:2::1.2.3.4 
should be valid");
+        assertTrue(isValidInet6Address("1::1.2.3.4"), "IPV6 1::1.2.3.4 should 
be valid");
+        assertTrue(isValidInet6Address("1:2:3:4::5:1.2.3.4"), "IPV6 
1:2:3:4::5:1.2.3.4 should be valid");
+        assertTrue(isValidInet6Address("1:2:3::5:1.2.3.4"), "IPV6 
1:2:3::5:1.2.3.4 should be valid");
+        assertTrue(isValidInet6Address("1:2::5:1.2.3.4"), "IPV6 1:2::5:1.2.3.4 
should be valid");
+        assertTrue(isValidInet6Address("1::5:1.2.3.4"), "IPV6 1::5:1.2.3.4 
should be valid");
+        assertTrue(isValidInet6Address("1::5:11.22.33.44"), "IPV6 
1::5:11.22.33.44 should be valid");
+        assertFalse(isValidInet6Address("1::5:400.2.3.4"), "IPV6 
1::5:400.2.3.4 should be invalid");
+        assertFalse(isValidInet6Address("1::5:260.2.3.4"), "IPV6 
1::5:260.2.3.4 should be invalid");
+        assertFalse(isValidInet6Address("1::5:256.2.3.4"), "IPV6 
1::5:256.2.3.4 should be invalid");
+        assertFalse(isValidInet6Address("1::5:1.256.3.4"), "IPV6 
1::5:1.256.3.4 should be invalid");
+        assertFalse(isValidInet6Address("1::5:1.2.256.4"), "IPV6 
1::5:1.2.256.4 should be invalid");
+        assertFalse(isValidInet6Address("1::5:1.2.3.256"), "IPV6 
1::5:1.2.3.256 should be invalid");
+        assertFalse(isValidInet6Address("1::5:300.2.3.4"), "IPV6 
1::5:300.2.3.4 should be invalid");
+        assertFalse(isValidInet6Address("1::5:1.300.3.4"), "IPV6 
1::5:1.300.3.4 should be invalid");
+        assertFalse(isValidInet6Address("1::5:1.2.300.4"), "IPV6 
1::5:1.2.300.4 should be invalid");
+        assertFalse(isValidInet6Address("1::5:1.2.3.300"), "IPV6 
1::5:1.2.3.300 should be invalid");
+        assertFalse(isValidInet6Address("1::5:900.2.3.4"), "IPV6 
1::5:900.2.3.4 should be invalid");
+        assertFalse(isValidInet6Address("1::5:1.900.3.4"), "IPV6 
1::5:1.900.3.4 should be invalid");
+        assertFalse(isValidInet6Address("1::5:1.2.900.4"), "IPV6 
1::5:1.2.900.4 should be invalid");
+        assertFalse(isValidInet6Address("1::5:1.2.3.900"), "IPV6 
1::5:1.2.3.900 should be invalid");
+        assertFalse(isValidInet6Address("1::5:300.300.300.300"), "IPV6 
1::5:300.300.300.300 should be invalid");
+        assertFalse(isValidInet6Address("1::5:3000.30.30.30"), "IPV6 
1::5:3000.30.30.30 should be invalid");
+        assertFalse(isValidInet6Address("1::400.2.3.4"), "IPV6 1::400.2.3.4 
should be invalid");
+        assertFalse(isValidInet6Address("1::260.2.3.4"), "IPV6 1::260.2.3.4 
should be invalid");
+        assertFalse(isValidInet6Address("1::256.2.3.4"), "IPV6 1::256.2.3.4 
should be invalid");
+        assertFalse(isValidInet6Address("1::1.256.3.4"), "IPV6 1::1.256.3.4 
should be invalid");
+        assertFalse(isValidInet6Address("1::1.2.256.4"), "IPV6 1::1.2.256.4 
should be invalid");
+        assertFalse(isValidInet6Address("1::1.2.3.256"), "IPV6 1::1.2.3.256 
should be invalid");
+        assertFalse(isValidInet6Address("1::300.2.3.4"), "IPV6 1::300.2.3.4 
should be invalid");
+        assertFalse(isValidInet6Address("1::1.300.3.4"), "IPV6 1::1.300.3.4 
should be invalid");
+        assertFalse(isValidInet6Address("1::1.2.300.4"), "IPV6 1::1.2.300.4 
should be invalid");
+        assertFalse(isValidInet6Address("1::1.2.3.300"), "IPV6 1::1.2.3.300 
should be invalid");
+        assertFalse(isValidInet6Address("1::900.2.3.4"), "IPV6 1::900.2.3.4 
should be invalid");
+        assertFalse(isValidInet6Address("1::1.900.3.4"), "IPV6 1::1.900.3.4 
should be invalid");
+        assertFalse(isValidInet6Address("1::1.2.900.4"), "IPV6 1::1.2.900.4 
should be invalid");
+        assertFalse(isValidInet6Address("1::1.2.3.900"), "IPV6 1::1.2.3.900 
should be invalid");
+        assertFalse(isValidInet6Address("1::300.300.300.300"), "IPV6 
1::300.300.300.300 should be invalid");
+        assertFalse(isValidInet6Address("1::3000.30.30.30"), "IPV6 
1::3000.30.30.30 should be invalid");
+        assertFalse(isValidInet6Address("::400.2.3.4"), "IPV6 ::400.2.3.4 
should be invalid");
+        assertFalse(isValidInet6Address("::260.2.3.4"), "IPV6 ::260.2.3.4 
should be invalid");
+        assertFalse(isValidInet6Address("::256.2.3.4"), "IPV6 ::256.2.3.4 
should be invalid");
+        assertFalse(isValidInet6Address("::1.256.3.4"), "IPV6 ::1.256.3.4 
should be invalid");
+        assertFalse(isValidInet6Address("::1.2.256.4"), "IPV6 ::1.2.256.4 
should be invalid");
+        assertFalse(isValidInet6Address("::1.2.3.256"), "IPV6 ::1.2.3.256 
should be invalid");
+        assertFalse(isValidInet6Address("::300.2.3.4"), "IPV6 ::300.2.3.4 
should be invalid");
+        assertFalse(isValidInet6Address("::1.300.3.4"), "IPV6 ::1.300.3.4 
should be invalid");
+        assertFalse(isValidInet6Address("::1.2.300.4"), "IPV6 ::1.2.300.4 
should be invalid");
+        assertFalse(isValidInet6Address("::1.2.3.300"), "IPV6 ::1.2.3.300 
should be invalid");
+        assertFalse(isValidInet6Address("::900.2.3.4"), "IPV6 ::900.2.3.4 
should be invalid");
+        assertFalse(isValidInet6Address("::1.900.3.4"), "IPV6 ::1.900.3.4 
should be invalid");
+        assertFalse(isValidInet6Address("::1.2.900.4"), "IPV6 ::1.2.900.4 
should be invalid");
+        assertFalse(isValidInet6Address("::1.2.3.900"), "IPV6 ::1.2.3.900 
should be invalid");
+        assertFalse(isValidInet6Address("::300.300.300.300"), "IPV6 
::300.300.300.300 should be invalid");
+        assertFalse(isValidInet6Address("::3000.30.30.30"), "IPV6 
::3000.30.30.30 should be invalid");
+        assertTrue(
+                isValidInet6Address("fe80::217:f2ff:254.7.237.98"), "IPV6 
fe80::217:f2ff:254.7.237.98 should be valid");
+        assertTrue(isValidInet6Address("::ffff:192.168.1.26"), "IPV6 
::ffff:192.168.1.26 should be valid");
+        assertFalse(
+                isValidInet6Address("2001:1:1:1:1:1:255Z255X255Y255"),
+                "IPV6 2001:1:1:1:1:1:255Z255X255Y255 should be invalid"); // 
garbage
+        // instead of "."
+        // in IPv4
+        assertFalse(isValidInet6Address("::ffff:192x168.1.26"), "IPV6 
::ffff:192x168.1.26 should be invalid"); // ditto
+        assertTrue(isValidInet6Address("::ffff:192.168.1.1"), "IPV6 
::ffff:192.168.1.1 should be valid");
+        assertTrue(
+                isValidInet6Address("0:0:0:0:0:0:13.1.68.3"),
+                "IPV6 0:0:0:0:0:0:13.1.68.3 should be valid"); // 
IPv4-compatible IPv6 address, full,
+        // deprecated
+        assertTrue(
+                isValidInet6Address("0:0:0:0:0:FFFF:129.144.52.38"),
+                "IPV6 0:0:0:0:0:FFFF:129.144.52.38 should be valid"); // 
IPv4-mapped IPv6
+        // address, full
+        assertTrue(
+                isValidInet6Address("::13.1.68.3"),
+                "IPV6 ::13.1.68.3 should be valid"); // IPv4-compatible IPv6 
address, compressed, deprecated
+        assertTrue(
+                isValidInet6Address("::FFFF:129.144.52.38"),
+                "IPV6 ::FFFF:129.144.52.38 should be valid"); // IPv4-mapped 
IPv6 address, compressed
+        assertTrue(
+                isValidInet6Address("fe80:0:0:0:204:61ff:254.157.241.86"),
+                "IPV6 fe80:0:0:0:204:61ff:254.157.241.86 should be valid");
+        assertTrue(
+                isValidInet6Address("fe80::204:61ff:254.157.241.86"),
+                "IPV6 fe80::204:61ff:254.157.241.86 should be valid");
+        assertTrue(isValidInet6Address("::ffff:12.34.56.78"), "IPV6 
::ffff:12.34.56.78 should be valid");
+        assertFalse(isValidInet6Address("::ffff:2.3.4"), "IPV6 ::ffff:2.3.4 
should be invalid");
+        assertFalse(isValidInet6Address("::ffff:257.1.2.3"), "IPV6 
::ffff:257.1.2.3 should be invalid");
+        assertFalse(isValidInet6Address("1.2.3.4"), "IPV6 1.2.3.4 should be 
invalid");
+        assertFalse(
+                isValidInet6Address("1.2.3.4:1111:2222:3333:4444::5555"),
+                "IPV6 1.2.3.4:1111:2222:3333:4444::5555 should be invalid");
+        assertFalse(
+                isValidInet6Address("1.2.3.4:1111:2222:3333::5555"),
+                "IPV6 1.2.3.4:1111:2222:3333::5555 should be invalid");
+        assertFalse(isValidInet6Address("1.2.3.4:1111:2222::5555"), "IPV6 
1.2.3.4:1111:2222::5555 should be invalid");
+        assertFalse(isValidInet6Address("1.2.3.4:1111::5555"), "IPV6 
1.2.3.4:1111::5555 should be invalid");
+        assertFalse(isValidInet6Address("1.2.3.4::5555"), "IPV6 1.2.3.4::5555 
should be invalid");
+        assertFalse(isValidInet6Address("1.2.3.4::"), "IPV6 1.2.3.4:: should 
be invalid");
+        // Testing IPv4 addresses represented as dotted-quads
+        // Leading zeroes in IPv4 addresses not allowed: some systems treat 
the leading "0" in ".086" as the start of an
+        // octal number
+        // Update: The BNF in RFC-3986 explicitly defines the dec-octet (for 
IPv4 addresses) not to have a leading zero
+        assertFalse(
+                
isValidInet6Address("fe80:0000:0000:0000:0204:61ff:254.157.241.086"),
+                "IPV6 fe80:0000:0000:0000:0204:61ff:254.157.241.086 should be 
invalid");
+        assertTrue(
+                isValidInet6Address("::ffff:192.0.2.128"),
+                "IPV6 ::ffff:192.0.2.128 should be valid"); // but this is OK, 
since there's a single
+        // digit
+        assertFalse(
+                isValidInet6Address("XXXX:XXXX:XXXX:XXXX:XXXX:XXXX:1.2.3.4"),
+                "IPV6 XXXX:XXXX:XXXX:XXXX:XXXX:XXXX:1.2.3.4 should be 
invalid");
+        assertFalse(
+                
isValidInet6Address("1111:2222:3333:4444:5555:6666:00.00.00.00"),
+                "IPV6 1111:2222:3333:4444:5555:6666:00.00.00.00 should be 
invalid");
+        assertFalse(
+                
isValidInet6Address("1111:2222:3333:4444:5555:6666:000.000.000.000"),
+                "IPV6 1111:2222:3333:4444:5555:6666:000.000.000.000 should be 
invalid");
+        assertFalse(
+                
isValidInet6Address("1111:2222:3333:4444:5555:6666:256.256.256.256"),
+                "IPV6 1111:2222:3333:4444:5555:6666:256.256.256.256 should be 
invalid");
+        assertTrue(
+                isValidInet6Address("fe80:0000:0000:0000:0204:61ff:fe9d:f156"),
+                "IPV6 fe80:0000:0000:0000:0204:61ff:fe9d:f156 should be 
valid");
+        assertTrue(
+                isValidInet6Address("fe80:0:0:0:204:61ff:fe9d:f156"),
+                "IPV6 fe80:0:0:0:204:61ff:fe9d:f156 should be valid");
+        assertTrue(isValidInet6Address("fe80::204:61ff:fe9d:f156"), "IPV6 
fe80::204:61ff:fe9d:f156 should be valid");
+        assertFalse(isValidInet6Address(":"), "IPV6 : should be invalid");
+        assertTrue(isValidInet6Address("::ffff:c000:280"), "IPV6 
::ffff:c000:280 should be valid");
+        assertFalse(
+                isValidInet6Address("1111:2222:3333:4444::5555:"), "IPV6 
1111:2222:3333:4444::5555: should be invalid");
+        assertFalse(isValidInet6Address("1111:2222:3333::5555:"), "IPV6 
1111:2222:3333::5555: should be invalid");
+        assertFalse(isValidInet6Address("1111:2222::5555:"), "IPV6 
1111:2222::5555: should be invalid");
+        assertFalse(isValidInet6Address("1111::5555:"), "IPV6 1111::5555: 
should be invalid");
+        assertFalse(isValidInet6Address("::5555:"), "IPV6 ::5555: should be 
invalid");
+        assertFalse(isValidInet6Address(":::"), "IPV6 ::: should be invalid");
+        assertFalse(isValidInet6Address("1111:"), "IPV6 1111: should be 
invalid");
+        assertFalse(
+                isValidInet6Address(":1111:2222:3333:4444::5555"), "IPV6 
:1111:2222:3333:4444::5555 should be invalid");
+        assertFalse(isValidInet6Address(":1111:2222:3333::5555"), "IPV6 
:1111:2222:3333::5555 should be invalid");
+        assertFalse(isValidInet6Address(":1111:2222::5555"), "IPV6 
:1111:2222::5555 should be invalid");
+        assertFalse(isValidInet6Address(":1111::5555"), "IPV6 :1111::5555 
should be invalid");
+        assertFalse(isValidInet6Address(":::5555"), "IPV6 :::5555 should be 
invalid");
+        assertTrue(
+                isValidInet6Address("2001:0db8:85a3:0000:0000:8a2e:0370:7334"),
+                "IPV6 2001:0db8:85a3:0000:0000:8a2e:0370:7334 should be 
valid");
+        assertTrue(
+                isValidInet6Address("2001:db8:85a3:0:0:8a2e:370:7334"),
+                "IPV6 2001:db8:85a3:0:0:8a2e:370:7334 should be valid");
+        assertTrue(
+                isValidInet6Address("2001:db8:85a3::8a2e:370:7334"),
+                "IPV6 2001:db8:85a3::8a2e:370:7334 should be valid");
+        assertTrue(
+                isValidInet6Address("2001:0db8:0000:0000:0000:0000:1428:57ab"),
+                "IPV6 2001:0db8:0000:0000:0000:0000:1428:57ab should be 
valid");
+        assertTrue(
+                isValidInet6Address("2001:0db8:0000:0000:0000::1428:57ab"),
+                "IPV6 2001:0db8:0000:0000:0000::1428:57ab should be valid");
+        assertTrue(
+                isValidInet6Address("2001:0db8:0:0:0:0:1428:57ab"), "IPV6 
2001:0db8:0:0:0:0:1428:57ab should be valid");
+        assertTrue(isValidInet6Address("2001:0db8:0:0::1428:57ab"), "IPV6 
2001:0db8:0:0::1428:57ab should be valid");
+        assertTrue(isValidInet6Address("2001:0db8::1428:57ab"), "IPV6 
2001:0db8::1428:57ab should be valid");
+        assertTrue(isValidInet6Address("2001:db8::1428:57ab"), "IPV6 
2001:db8::1428:57ab should be valid");
+        assertTrue(isValidInet6Address("::ffff:0c22:384e"), "IPV6 
::ffff:0c22:384e should be valid");
+        assertTrue(
+                isValidInet6Address("2001:0db8:1234:0000:0000:0000:0000:0000"),
+                "IPV6 2001:0db8:1234:0000:0000:0000:0000:0000 should be 
valid");
+        assertTrue(
+                isValidInet6Address("2001:0db8:1234:ffff:ffff:ffff:ffff:ffff"),
+                "IPV6 2001:0db8:1234:ffff:ffff:ffff:ffff:ffff should be 
valid");
+        assertTrue(isValidInet6Address("2001:db8:a::123"), "IPV6 
2001:db8:a::123 should be valid");
+        assertFalse(isValidInet6Address("123"), "IPV6 123 should be invalid");
+        assertFalse(isValidInet6Address("ldkfj"), "IPV6 ldkfj should be 
invalid");
+        assertFalse(isValidInet6Address("2001::FFD3::57ab"), "IPV6 
2001::FFD3::57ab should be invalid");
+        assertFalse(
+                isValidInet6Address("2001:db8:85a3::8a2e:37023:7334"),
+                "IPV6 2001:db8:85a3::8a2e:37023:7334 should be invalid");
+        assertFalse(
+                isValidInet6Address("2001:db8:85a3::8a2e:370k:7334"),
+                "IPV6 2001:db8:85a3::8a2e:370k:7334 should be invalid");
+        assertFalse(isValidInet6Address("1:2:3:4:5:6:7:8:9"), "IPV6 
1:2:3:4:5:6:7:8:9 should be invalid");
+        assertFalse(isValidInet6Address("1::2::3"), "IPV6 1::2::3 should be 
invalid");
+        assertFalse(isValidInet6Address("1:::3:4:5"), "IPV6 1:::3:4:5 should 
be invalid");
+        assertFalse(isValidInet6Address("1:2:3::4:5:6:7:8:9"), "IPV6 
1:2:3::4:5:6:7:8:9 should be invalid");
+        assertTrue(
+                isValidInet6Address("1111:2222:3333:4444:5555:6666:7777:8888"),
+                "IPV6 1111:2222:3333:4444:5555:6666:7777:8888 should be 
valid");
+        assertTrue(
+                isValidInet6Address("1111:2222:3333:4444:5555:6666:7777::"),
+                "IPV6 1111:2222:3333:4444:5555:6666:7777:: should be valid");
+        assertTrue(
+                isValidInet6Address("1111:2222:3333:4444:5555:6666::"),
+                "IPV6 1111:2222:3333:4444:5555:6666:: should be valid");
+        assertTrue(
+                isValidInet6Address("1111:2222:3333:4444:5555::"), "IPV6 
1111:2222:3333:4444:5555:: should be valid");
+        assertTrue(isValidInet6Address("1111:2222:3333:4444::"), "IPV6 
1111:2222:3333:4444:: should be valid");
+        assertTrue(isValidInet6Address("1111:2222:3333::"), "IPV6 
1111:2222:3333:: should be valid");
+        assertTrue(isValidInet6Address("1111:2222::"), "IPV6 1111:2222:: 
should be valid");
+        assertTrue(isValidInet6Address("1111::"), "IPV6 1111:: should be 
valid");
+        assertTrue(
+                isValidInet6Address("1111:2222:3333:4444:5555:6666::8888"),
+                "IPV6 1111:2222:3333:4444:5555:6666::8888 should be valid");
+        assertTrue(
+                isValidInet6Address("1111:2222:3333:4444:5555::8888"),
+                "IPV6 1111:2222:3333:4444:5555::8888 should be valid");
+        assertTrue(isValidInet6Address("1111:2222:3333:4444::8888"), "IPV6 
1111:2222:3333:4444::8888 should be valid");
+        assertTrue(isValidInet6Address("1111:2222:3333::8888"), "IPV6 
1111:2222:3333::8888 should be valid");
+        assertTrue(isValidInet6Address("1111:2222::8888"), "IPV6 
1111:2222::8888 should be valid");
+        assertTrue(isValidInet6Address("1111::8888"), "IPV6 1111::8888 should 
be valid");
+        assertTrue(isValidInet6Address("::8888"), "IPV6 ::8888 should be 
valid");
+        assertTrue(
+                isValidInet6Address("1111:2222:3333:4444:5555::7777:8888"),
+                "IPV6 1111:2222:3333:4444:5555::7777:8888 should be valid");
+        assertTrue(
+                isValidInet6Address("1111:2222:3333:4444::7777:8888"),
+                "IPV6 1111:2222:3333:4444::7777:8888 should be valid");
+        assertTrue(isValidInet6Address("1111:2222:3333::7777:8888"), "IPV6 
1111:2222:3333::7777:8888 should be valid");
+        assertTrue(isValidInet6Address("1111:2222::7777:8888"), "IPV6 
1111:2222::7777:8888 should be valid");
+        assertTrue(isValidInet6Address("1111::7777:8888"), "IPV6 
1111::7777:8888 should be valid");
+        assertTrue(isValidInet6Address("::7777:8888"), "IPV6 ::7777:8888 
should be valid");
+        assertTrue(
+                isValidInet6Address("1111:2222:3333:4444::6666:7777:8888"),
+                "IPV6 1111:2222:3333:4444::6666:7777:8888 should be valid");
+        assertTrue(
+                isValidInet6Address("1111:2222:3333::6666:7777:8888"),
+                "IPV6 1111:2222:3333::6666:7777:8888 should be valid");
+        assertTrue(isValidInet6Address("1111:2222::6666:7777:8888"), "IPV6 
1111:2222::6666:7777:8888 should be valid");
+        assertTrue(isValidInet6Address("1111::6666:7777:8888"), "IPV6 
1111::6666:7777:8888 should be valid");
+        assertTrue(isValidInet6Address("::6666:7777:8888"), "IPV6 
::6666:7777:8888 should be valid");
+        assertTrue(
+                isValidInet6Address("1111:2222:3333::5555:6666:7777:8888"),
+                "IPV6 1111:2222:3333::5555:6666:7777:8888 should be valid");
+        assertTrue(
+                isValidInet6Address("1111:2222::5555:6666:7777:8888"),
+                "IPV6 1111:2222::5555:6666:7777:8888 should be valid");
+        assertTrue(isValidInet6Address("1111::5555:6666:7777:8888"), "IPV6 
1111::5555:6666:7777:8888 should be valid");
+        assertTrue(isValidInet6Address("::5555:6666:7777:8888"), "IPV6 
::5555:6666:7777:8888 should be valid");
+        assertTrue(
+                isValidInet6Address("1111:2222::4444:5555:6666:7777:8888"),
+                "IPV6 1111:2222::4444:5555:6666:7777:8888 should be valid");
+        assertTrue(
+                isValidInet6Address("1111::4444:5555:6666:7777:8888"),
+                "IPV6 1111::4444:5555:6666:7777:8888 should be valid");
+        assertTrue(
+                isValidInet6Address("::4444:5555:6666:7777:8888"), "IPV6 
::4444:5555:6666:7777:8888 should be valid");
+        assertTrue(
+                isValidInet6Address("1111::3333:4444:5555:6666:7777:8888"),
+                "IPV6 1111::3333:4444:5555:6666:7777:8888 should be valid");
+        assertTrue(
+                isValidInet6Address("::3333:4444:5555:6666:7777:8888"),
+                "IPV6 ::3333:4444:5555:6666:7777:8888 should be valid");
+        assertTrue(
+                isValidInet6Address("::2222:3333:4444:5555:6666:7777:8888"),
+                "IPV6 ::2222:3333:4444:5555:6666:7777:8888 should be valid");
+        assertTrue(
+                
isValidInet6Address("1111:2222:3333:4444:5555:6666:123.123.123.123"),
+                "IPV6 1111:2222:3333:4444:5555:6666:123.123.123.123 should be 
valid");
+        assertTrue(
+                
isValidInet6Address("1111:2222:3333:4444:5555::123.123.123.123"),
+                "IPV6 1111:2222:3333:4444:5555::123.123.123.123 should be 
valid");
+        assertTrue(
+                isValidInet6Address("1111:2222:3333:4444::123.123.123.123"),
+                "IPV6 1111:2222:3333:4444::123.123.123.123 should be valid");
+        assertTrue(
+                isValidInet6Address("1111:2222:3333::123.123.123.123"),
+                "IPV6 1111:2222:3333::123.123.123.123 should be valid");
+        assertTrue(
+                isValidInet6Address("1111:2222::123.123.123.123"), "IPV6 
1111:2222::123.123.123.123 should be valid");
+        assertTrue(isValidInet6Address("1111::123.123.123.123"), "IPV6 
1111::123.123.123.123 should be valid");
+        assertTrue(isValidInet6Address("::123.123.123.123"), "IPV6 
::123.123.123.123 should be valid");
+        assertTrue(
+                
isValidInet6Address("1111:2222:3333:4444::6666:123.123.123.123"),
+                "IPV6 1111:2222:3333:4444::6666:123.123.123.123 should be 
valid");
+        assertTrue(
+                isValidInet6Address("1111:2222:3333::6666:123.123.123.123"),
+                "IPV6 1111:2222:3333::6666:123.123.123.123 should be valid");
+        assertTrue(
+                isValidInet6Address("1111:2222::6666:123.123.123.123"),
+                "IPV6 1111:2222::6666:123.123.123.123 should be valid");
+        assertTrue(
+                isValidInet6Address("1111::6666:123.123.123.123"), "IPV6 
1111::6666:123.123.123.123 should be valid");
+        assertTrue(isValidInet6Address("::6666:123.123.123.123"), "IPV6 
::6666:123.123.123.123 should be valid");
+        assertTrue(
+                
isValidInet6Address("1111:2222:3333::5555:6666:123.123.123.123"),
+                "IPV6 1111:2222:3333::5555:6666:123.123.123.123 should be 
valid");
+        assertTrue(
+                isValidInet6Address("1111:2222::5555:6666:123.123.123.123"),
+                "IPV6 1111:2222::5555:6666:123.123.123.123 should be valid");
+        assertTrue(
+                isValidInet6Address("1111::5555:6666:123.123.123.123"),
+                "IPV6 1111::5555:6666:123.123.123.123 should be valid");
+        assertTrue(
+                isValidInet6Address("::5555:6666:123.123.123.123"), "IPV6 
::5555:6666:123.123.123.123 should be valid");
+        assertTrue(
+                
isValidInet6Address("1111:2222::4444:5555:6666:123.123.123.123"),
+                "IPV6 1111:2222::4444:5555:6666:123.123.123.123 should be 
valid");
+        assertTrue(
+                isValidInet6Address("1111::4444:5555:6666:123.123.123.123"),
+                "IPV6 1111::4444:5555:6666:123.123.123.123 should be valid");
+        assertTrue(
+                isValidInet6Address("::4444:5555:6666:123.123.123.123"),
+                "IPV6 ::4444:5555:6666:123.123.123.123 should be valid");
+        assertTrue(
+                
isValidInet6Address("1111::3333:4444:5555:6666:123.123.123.123"),
+                "IPV6 1111::3333:4444:5555:6666:123.123.123.123 should be 
valid");
+        assertTrue(
+                
isValidInet6Address("::2222:3333:4444:5555:6666:123.123.123.123"),
+                "IPV6 ::2222:3333:4444:5555:6666:123.123.123.123 should be 
valid");
+        // Trying combinations of "0" and "::"
+        // These are all syntactically correct, but are bad form
+        // because "0" adjacent to "::" should be combined into "::"
+        assertTrue(isValidInet6Address("::0:0:0:0:0:0:0"), "IPV6 
::0:0:0:0:0:0:0 should be valid");
+        assertTrue(isValidInet6Address("::0:0:0:0:0:0"), "IPV6 ::0:0:0:0:0:0 
should be valid");
+        assertTrue(isValidInet6Address("::0:0:0:0:0"), "IPV6 ::0:0:0:0:0 
should be valid");
+        assertTrue(isValidInet6Address("::0:0:0:0"), "IPV6 ::0:0:0:0 should be 
valid");
+        assertTrue(isValidInet6Address("::0:0:0"), "IPV6 ::0:0:0 should be 
valid");
+        assertTrue(isValidInet6Address("::0:0"), "IPV6 ::0:0 should be valid");
+        assertTrue(isValidInet6Address("::0"), "IPV6 ::0 should be valid");
+        assertTrue(isValidInet6Address("0:0:0:0:0:0:0::"), "IPV6 
0:0:0:0:0:0:0:: should be valid");
+        assertTrue(isValidInet6Address("0:0:0:0:0:0::"), "IPV6 0:0:0:0:0:0:: 
should be valid");
+        assertTrue(isValidInet6Address("0:0:0:0:0::"), "IPV6 0:0:0:0:0:: 
should be valid");
+        assertTrue(isValidInet6Address("0:0:0:0::"), "IPV6 0:0:0:0:: should be 
valid");
+        assertTrue(isValidInet6Address("0:0:0::"), "IPV6 0:0:0:: should be 
valid");
+        assertTrue(isValidInet6Address("0:0::"), "IPV6 0:0:: should be valid");
+        assertTrue(isValidInet6Address("0::"), "IPV6 0:: should be valid");
+        // Invalid data
+        assertFalse(
+                isValidInet6Address("XXXX:XXXX:XXXX:XXXX:XXXX:XXXX:XXXX:XXXX"),
+                "IPV6 XXXX:XXXX:XXXX:XXXX:XXXX:XXXX:XXXX:XXXX should be 
invalid");
+        // Too many components
+        assertFalse(
+                
isValidInet6Address("1111:2222:3333:4444:5555:6666:7777:8888:9999"),
+                "IPV6 1111:2222:3333:4444:5555:6666:7777:8888:9999 should be 
invalid");
+        assertFalse(
+                
isValidInet6Address("1111:2222:3333:4444:5555:6666:7777:8888::"),
+                "IPV6 1111:2222:3333:4444:5555:6666:7777:8888:: should be 
invalid");
+        assertFalse(
+                
isValidInet6Address("::2222:3333:4444:5555:6666:7777:8888:9999"),
+                "IPV6 ::2222:3333:4444:5555:6666:7777:8888:9999 should be 
invalid");
+        // Too few components
+        assertFalse(
+                isValidInet6Address("1111:2222:3333:4444:5555:6666:7777"),
+                "IPV6 1111:2222:3333:4444:5555:6666:7777 should be invalid");
+        assertFalse(
+                isValidInet6Address("1111:2222:3333:4444:5555:6666"),
+                "IPV6 1111:2222:3333:4444:5555:6666 should be invalid");
+        assertFalse(isValidInet6Address("1111:2222:3333:4444:5555"), "IPV6 
1111:2222:3333:4444:5555 should be invalid");
+        assertFalse(isValidInet6Address("1111:2222:3333:4444"), "IPV6 
1111:2222:3333:4444 should be invalid");
+        assertFalse(isValidInet6Address("1111:2222:3333"), "IPV6 
1111:2222:3333 should be invalid");
+        assertFalse(isValidInet6Address("1111:2222"), "IPV6 1111:2222 should 
be invalid");
+        assertFalse(isValidInet6Address("1111"), "IPV6 1111 should be 
invalid");
+        // Missing :
+        assertFalse(
+                isValidInet6Address("11112222:3333:4444:5555:6666:7777:8888"),
+                "IPV6 11112222:3333:4444:5555:6666:7777:8888 should be 
invalid");
+        assertFalse(
+                isValidInet6Address("1111:22223333:4444:5555:6666:7777:8888"),
+                "IPV6 1111:22223333:4444:5555:6666:7777:8888 should be 
invalid");
+        assertFalse(
+                isValidInet6Address("1111:2222:33334444:5555:6666:7777:8888"),
+                "IPV6 1111:2222:33334444:5555:6666:7777:8888 should be 
invalid");
+        assertFalse(
+                isValidInet6Address("1111:2222:3333:44445555:6666:7777:8888"),
+                "IPV6 1111:2222:3333:44445555:6666:7777:8888 should be 
invalid");
+        assertFalse(
+                isValidInet6Address("1111:2222:3333:4444:55556666:7777:8888"),
+                "IPV6 1111:2222:3333:4444:55556666:7777:8888 should be 
invalid");
+        assertFalse(
+                isValidInet6Address("1111:2222:3333:4444:5555:66667777:8888"),
+                "IPV6 1111:2222:3333:4444:5555:66667777:8888 should be 
invalid");
+        assertFalse(
+                isValidInet6Address("1111:2222:3333:4444:5555:6666:77778888"),
+                "IPV6 1111:2222:3333:4444:5555:6666:77778888 should be 
invalid");
+        // Missing : intended for ::
+        assertFalse(
+                
isValidInet6Address("1111:2222:3333:4444:5555:6666:7777:8888:"),
+                "IPV6 1111:2222:3333:4444:5555:6666:7777:8888: should be 
invalid");
+        assertFalse(
+                isValidInet6Address("1111:2222:3333:4444:5555:6666:7777:"),
+                "IPV6 1111:2222:3333:4444:5555:6666:7777: should be invalid");
+        assertFalse(
+                isValidInet6Address("1111:2222:3333:4444:5555:6666:"),
+                "IPV6 1111:2222:3333:4444:5555:6666: should be invalid");
+        assertFalse(
+                isValidInet6Address("1111:2222:3333:4444:5555:"), "IPV6 
1111:2222:3333:4444:5555: should be invalid");
+        assertFalse(isValidInet6Address("1111:2222:3333:4444:"), "IPV6 
1111:2222:3333:4444: should be invalid");
+        assertFalse(isValidInet6Address("1111:2222:3333:"), "IPV6 
1111:2222:3333: should be invalid");
+        assertFalse(isValidInet6Address("1111:2222:"), "IPV6 1111:2222: should 
be invalid");
+        assertFalse(isValidInet6Address(":8888"), "IPV6 :8888 should be 
invalid");
+        assertFalse(isValidInet6Address(":7777:8888"), "IPV6 :7777:8888 should 
be invalid");
+        assertFalse(isValidInet6Address(":6666:7777:8888"), "IPV6 
:6666:7777:8888 should be invalid");
+        assertFalse(isValidInet6Address(":5555:6666:7777:8888"), "IPV6 
:5555:6666:7777:8888 should be invalid");
+        assertFalse(
+                isValidInet6Address(":4444:5555:6666:7777:8888"), "IPV6 
:4444:5555:6666:7777:8888 should be invalid");
+        assertFalse(
+                isValidInet6Address(":3333:4444:5555:6666:7777:8888"),
+                "IPV6 :3333:4444:5555:6666:7777:8888 should be invalid");
+        assertFalse(
+                isValidInet6Address(":2222:3333:4444:5555:6666:7777:8888"),
+                "IPV6 :2222:3333:4444:5555:6666:7777:8888 should be invalid");
+        assertFalse(
+                
isValidInet6Address(":1111:2222:3333:4444:5555:6666:7777:8888"),
+                "IPV6 :1111:2222:3333:4444:5555:6666:7777:8888 should be 
invalid");
+        // :::
+        assertFalse(
+                isValidInet6Address(":::2222:3333:4444:5555:6666:7777:8888"),
+                "IPV6 :::2222:3333:4444:5555:6666:7777:8888 should be 
invalid");
+        assertFalse(
+                isValidInet6Address("1111:::3333:4444:5555:6666:7777:8888"),
+                "IPV6 1111:::3333:4444:5555:6666:7777:8888 should be invalid");
+        assertFalse(
+                isValidInet6Address("1111:2222:::4444:5555:6666:7777:8888"),
+                "IPV6 1111:2222:::4444:5555:6666:7777:8888 should be invalid");
+        assertFalse(
+                isValidInet6Address("1111:2222:3333:::5555:6666:7777:8888"),
+                "IPV6 1111:2222:3333:::5555:6666:7777:8888 should be invalid");
+        assertFalse(
+                isValidInet6Address("1111:2222:3333:4444:::6666:7777:8888"),
+                "IPV6 1111:2222:3333:4444:::6666:7777:8888 should be invalid");
+        assertFalse(
+                isValidInet6Address("1111:2222:3333:4444:5555:::7777:8888"),
+                "IPV6 1111:2222:3333:4444:5555:::7777:8888 should be invalid");
+        assertFalse(
+                isValidInet6Address("1111:2222:3333:4444:5555:6666:::8888"),
+                "IPV6 1111:2222:3333:4444:5555:6666:::8888 should be invalid");
+        assertFalse(
+                isValidInet6Address("1111:2222:3333:4444:5555:6666:7777:::"),
+                "IPV6 1111:2222:3333:4444:5555:6666:7777::: should be 
invalid");
+        // Double ::
+        assertFalse(
+                isValidInet6Address("::2222::4444:5555:6666:7777:8888"),
+                "IPV6 ::2222::4444:5555:6666:7777:8888 should be invalid");
+        assertFalse(
+                isValidInet6Address("::2222:3333::5555:6666:7777:8888"),
+                "IPV6 ::2222:3333::5555:6666:7777:8888 should be invalid");
+        assertFalse(
+                isValidInet6Address("::2222:3333:4444::6666:7777:8888"),
+                "IPV6 ::2222:3333:4444::6666:7777:8888 should be invalid");
+        assertFalse(
+                isValidInet6Address("::2222:3333:4444:5555::7777:8888"),
+                "IPV6 ::2222:3333:4444:5555::7777:8888 should be invalid");
+        assertFalse(
+                isValidInet6Address("::2222:3333:4444:5555:7777::8888"),
+                "IPV6 ::2222:3333:4444:5555:7777::8888 should be invalid");
+        assertFalse(
+                isValidInet6Address("::2222:3333:4444:5555:7777:8888::"),
+                "IPV6 ::2222:3333:4444:5555:7777:8888:: should be invalid");
+        assertFalse(
+                isValidInet6Address("1111::3333::5555:6666:7777:8888"),
+                "IPV6 1111::3333::5555:6666:7777:8888 should be invalid");
+        assertFalse(
+                isValidInet6Address("1111::3333:4444::6666:7777:8888"),
+                "IPV6 1111::3333:4444::6666:7777:8888 should be invalid");
+        assertFalse(
+                isValidInet6Address("1111::3333:4444:5555::7777:8888"),
+                "IPV6 1111::3333:4444:5555::7777:8888 should be invalid");
+        assertFalse(
+                isValidInet6Address("1111::3333:4444:5555:6666::8888"),
+                "IPV6 1111::3333:4444:5555:6666::8888 should be invalid");
+        assertFalse(
+                isValidInet6Address("1111::3333:4444:5555:6666:7777::"),
+                "IPV6 1111::3333:4444:5555:6666:7777:: should be invalid");
+        assertFalse(
+                isValidInet6Address("1111:2222::4444::6666:7777:8888"),
+                "IPV6 1111:2222::4444::6666:7777:8888 should be invalid");
+        assertFalse(
+                isValidInet6Address("1111:2222::4444:5555::7777:8888"),
+                "IPV6 1111:2222::4444:5555::7777:8888 should be invalid");
+        assertFalse(
+                isValidInet6Address("1111:2222::4444:5555:6666::8888"),
+                "IPV6 1111:2222::4444:5555:6666::8888 should be invalid");
+        assertFalse(
+                isValidInet6Address("1111:2222::4444:5555:6666:7777::"),
+                "IPV6 1111:2222::4444:5555:6666:7777:: should be invalid");
+        assertFalse(
+                isValidInet6Address("1111:2222:3333::5555::7777:8888"),
+                "IPV6 1111:2222:3333::5555::7777:8888 should be invalid");
+        assertFalse(
+                isValidInet6Address("1111:2222:3333::5555:6666::8888"),
+                "IPV6 1111:2222:3333::5555:6666::8888 should be invalid");
+        assertFalse(
+                isValidInet6Address("1111:2222:3333::5555:6666:7777::"),
+                "IPV6 1111:2222:3333::5555:6666:7777:: should be invalid");
+        assertFalse(
+                isValidInet6Address("1111:2222:3333:4444::6666::8888"),
+                "IPV6 1111:2222:3333:4444::6666::8888 should be invalid");
+        assertFalse(
+                isValidInet6Address("1111:2222:3333:4444::6666:7777::"),
+                "IPV6 1111:2222:3333:4444::6666:7777:: should be invalid");
+        assertFalse(
+                isValidInet6Address("1111:2222:3333:4444:5555::7777::"),
+                "IPV6 1111:2222:3333:4444:5555::7777:: should be invalid");
+        // Too many components"
+        assertFalse(
+                
isValidInet6Address("1111:2222:3333:4444:5555:6666:7777:8888:1.2.3.4"),
+                "IPV6 1111:2222:3333:4444:5555:6666:7777:8888:1.2.3.4 should 
be invalid");
+        assertFalse(
+                
isValidInet6Address("1111:2222:3333:4444:5555:6666:7777:1.2.3.4"),
+                "IPV6 1111:2222:3333:4444:5555:6666:7777:1.2.3.4 should be 
invalid");
+        assertFalse(
+                isValidInet6Address("1111:2222:3333:4444:5555:6666::1.2.3.4"),
+                "IPV6 1111:2222:3333:4444:5555:6666::1.2.3.4 should be 
invalid");
+        assertFalse(
+                isValidInet6Address("::2222:3333:4444:5555:6666:7777:1.2.3.4"),
+                "IPV6 ::2222:3333:4444:5555:6666:7777:1.2.3.4 should be 
invalid");
+        assertFalse(
+                isValidInet6Address("1111:2222:3333:4444:5555:6666:1.2.3.4.5"),
+                "IPV6 1111:2222:3333:4444:5555:6666:1.2.3.4.5 should be 
invalid");
+        // Too few components
+        assertFalse(
+                isValidInet6Address("1111:2222:3333:4444:5555:1.2.3.4"),
+                "IPV6 1111:2222:3333:4444:5555:1.2.3.4 should be invalid");
+        assertFalse(
+                isValidInet6Address("1111:2222:3333:4444:1.2.3.4"),
+                "IPV6 1111:2222:3333:4444:1.2.3.4 should be invalid");
+        assertFalse(isValidInet6Address("1111:2222:3333:1.2.3.4"), "IPV6 
1111:2222:3333:1.2.3.4 should be invalid");
+        assertFalse(isValidInet6Address("1111:2222:1.2.3.4"), "IPV6 
1111:2222:1.2.3.4 should be invalid");
+        assertFalse(isValidInet6Address("1111:1.2.3.4"), "IPV6 1111:1.2.3.4 
should be invalid");
+        assertFalse(isValidInet6Address("1.2.3.4"), "IPV6 1.2.3.4 should be 
invalid");
+        // Missing :
+        assertFalse(
+                isValidInet6Address("11112222:3333:4444:5555:6666:1.2.3.4"),
+                "IPV6 11112222:3333:4444:5555:6666:1.2.3.4 should be invalid");
+        assertFalse(
+                isValidInet6Address("1111:22223333:4444:5555:6666:1.2.3.4"),
+                "IPV6 1111:22223333:4444:5555:6666:1.2.3.4 should be invalid");
+        assertFalse(
+                isValidInet6Address("1111:2222:33334444:5555:6666:1.2.3.4"),
+                "IPV6 1111:2222:33334444:5555:6666:1.2.3.4 should be invalid");
+        assertFalse(
+                isValidInet6Address("1111:2222:3333:44445555:6666:1.2.3.4"),
+                "IPV6 1111:2222:3333:44445555:6666:1.2.3.4 should be invalid");
+        assertFalse(
+                isValidInet6Address("1111:2222:3333:4444:55556666:1.2.3.4"),
+                "IPV6 1111:2222:3333:4444:55556666:1.2.3.4 should be invalid");
+        assertFalse(
+                isValidInet6Address("1111:2222:3333:4444:5555:66661.2.3.4"),
+                "IPV6 1111:2222:3333:4444:5555:66661.2.3.4 should be invalid");
+        // Missing .
+        assertFalse(
+                
isValidInet6Address("1111:2222:3333:4444:5555:6666:255255.255.255"),
+                "IPV6 1111:2222:3333:4444:5555:6666:255255.255.255 should be 
invalid");
+        assertFalse(
+                
isValidInet6Address("1111:2222:3333:4444:5555:6666:255.255255.255"),
+                "IPV6 1111:2222:3333:4444:5555:6666:255.255255.255 should be 
invalid");
+        assertFalse(
+                
isValidInet6Address("1111:2222:3333:4444:5555:6666:255.255.255255"),
+                "IPV6 1111:2222:3333:4444:5555:6666:255.255.255255 should be 
invalid");
+        // Missing : intended for ::
+        assertFalse(isValidInet6Address(":1.2.3.4"), "IPV6 :1.2.3.4 should be 
invalid");
+        assertFalse(isValidInet6Address(":6666:1.2.3.4"), "IPV6 :6666:1.2.3.4 
should be invalid");
+        assertFalse(isValidInet6Address(":5555:6666:1.2.3.4"), "IPV6 
:5555:6666:1.2.3.4 should be invalid");
+        assertFalse(isValidInet6Address(":4444:5555:6666:1.2.3.4"), "IPV6 
:4444:5555:6666:1.2.3.4 should be invalid");
+        assertFalse(
+                isValidInet6Address(":3333:4444:5555:6666:1.2.3.4"),
+                "IPV6 :3333:4444:5555:6666:1.2.3.4 should be invalid");
+        assertFalse(
+                isValidInet6Address(":2222:3333:4444:5555:6666:1.2.3.4"),
+                "IPV6 :2222:3333:4444:5555:6666:1.2.3.4 should be invalid");
+        assertFalse(
+                isValidInet6Address(":1111:2222:3333:4444:5555:6666:1.2.3.4"),
+                "IPV6 :1111:2222:3333:4444:5555:6666:1.2.3.4 should be 
invalid");
+        // :::
+        assertFalse(
+                isValidInet6Address(":::2222:3333:4444:5555:6666:1.2.3.4"),
+                "IPV6 :::2222:3333:4444:5555:6666:1.2.3.4 should be invalid");
+        assertFalse(
+                isValidInet6Address("1111:::3333:4444:5555:6666:1.2.3.4"),
+                "IPV6 1111:::3333:4444:5555:6666:1.2.3.4 should be invalid");
+        assertFalse(
+                isValidInet6Address("1111:2222:::4444:5555:6666:1.2.3.4"),
+                "IPV6 1111:2222:::4444:5555:6666:1.2.3.4 should be invalid");
+        assertFalse(
+                isValidInet6Address("1111:2222:3333:::5555:6666:1.2.3.4"),
+                "IPV6 1111:2222:3333:::5555:6666:1.2.3.4 should be invalid");
+        assertFalse(
+                isValidInet6Address("1111:2222:3333:4444:::6666:1.2.3.4"),
+                "IPV6 1111:2222:3333:4444:::6666:1.2.3.4 should be invalid");
+        assertFalse(
+                isValidInet6Address("1111:2222:3333:4444:5555:::1.2.3.4"),
+                "IPV6 1111:2222:3333:4444:5555:::1.2.3.4 should be invalid");
+        // Double ::
+        assertFalse(
+                isValidInet6Address("::2222::4444:5555:6666:1.2.3.4"),
+                "IPV6 ::2222::4444:5555:6666:1.2.3.4 should be invalid");
+        assertFalse(
+                isValidInet6Address("::2222:3333::5555:6666:1.2.3.4"),
+                "IPV6 ::2222:3333::5555:6666:1.2.3.4 should be invalid");
+        assertFalse(
+                isValidInet6Address("::2222:3333:4444::6666:1.2.3.4"),
+                "IPV6 ::2222:3333:4444::6666:1.2.3.4 should be invalid");
+        assertFalse(
+                isValidInet6Address("::2222:3333:4444:5555::1.2.3.4"),
+                "IPV6 ::2222:3333:4444:5555::1.2.3.4 should be invalid");
+        assertFalse(
+                isValidInet6Address("1111::3333::5555:6666:1.2.3.4"),
+                "IPV6 1111::3333::5555:6666:1.2.3.4 should be invalid");
+        assertFalse(
+                isValidInet6Address("1111::3333:4444::6666:1.2.3.4"),
+                "IPV6 1111::3333:4444::6666:1.2.3.4 should be invalid");
+        assertFalse(
+                isValidInet6Address("1111::3333:4444:5555::1.2.3.4"),
+                "IPV6 1111::3333:4444:5555::1.2.3.4 should be invalid");
+        assertFalse(
+                isValidInet6Address("1111:2222::4444::6666:1.2.3.4"),
+                "IPV6 1111:2222::4444::6666:1.2.3.4 should be invalid");
+        assertFalse(
+                isValidInet6Address("1111:2222::4444:5555::1.2.3.4"),
+                "IPV6 1111:2222::4444:5555::1.2.3.4 should be invalid");
+        assertFalse(
+                isValidInet6Address("1111:2222:3333::5555::1.2.3.4"),
+                "IPV6 1111:2222:3333::5555::1.2.3.4 should be invalid");
+        // Missing parts
+        assertFalse(isValidInet6Address("::."), "IPV6 ::. should be invalid");
+        assertFalse(isValidInet6Address("::.."), "IPV6 ::.. should be 
invalid");
+        assertFalse(isValidInet6Address("::..."), "IPV6 ::... should be 
invalid");
+        assertFalse(isValidInet6Address("::1..."), "IPV6 ::1... should be 
invalid");
+        assertFalse(isValidInet6Address("::1.2.."), "IPV6 ::1.2.. should be 
invalid");
+        assertFalse(isValidInet6Address("::1.2.3."), "IPV6 ::1.2.3. should be 
invalid");
+        assertFalse(isValidInet6Address("::.2.."), "IPV6 ::.2.. should be 
invalid");
+        assertFalse(isValidInet6Address("::.2.3."), "IPV6 ::.2.3. should be 
invalid");
+        assertFalse(isValidInet6Address("::.2.3.4"), "IPV6 ::.2.3.4 should be 
invalid");
+        assertFalse(isValidInet6Address("::..3."), "IPV6 ::..3. should be 
invalid");
+        assertFalse(isValidInet6Address("::..3.4"), "IPV6 ::..3.4 should be 
invalid");
+        assertFalse(isValidInet6Address("::...4"), "IPV6 ::...4 should be 
invalid");
+        // Extra : in front
+        assertFalse(
+                isValidInet6Address(":1111:2222:3333:4444:5555:6666:7777::"),
+                "IPV6 :1111:2222:3333:4444:5555:6666:7777:: should be 
invalid");
+        assertFalse(
+                isValidInet6Address(":1111:2222:3333:4444:5555:6666::"),
+                "IPV6 :1111:2222:3333:4444:5555:6666:: should be invalid");
+        assertFalse(
+                isValidInet6Address(":1111:2222:3333:4444:5555::"),
+                "IPV6 :1111:2222:3333:4444:5555:: should be invalid");
+        assertFalse(isValidInet6Address(":1111:2222:3333:4444::"), "IPV6 
:1111:2222:3333:4444:: should be invalid");
+        assertFalse(isValidInet6Address(":1111:2222:3333::"), "IPV6 
:1111:2222:3333:: should be invalid");
+        assertFalse(isValidInet6Address(":1111:2222::"), "IPV6 :1111:2222:: 
should be invalid");
+        assertFalse(isValidInet6Address(":1111::"), "IPV6 :1111:: should be 
invalid");
+        assertFalse(
+                isValidInet6Address(":1111:2222:3333:4444:5555:6666::8888"),
+                "IPV6 :1111:2222:3333:4444:5555:6666::8888 should be invalid");
+        assertFalse(
+                isValidInet6Address(":1111:2222:3333:4444:5555::8888"),
+                "IPV6 :1111:2222:3333:4444:5555::8888 should be invalid");
+        assertFalse(
+                isValidInet6Address(":1111:2222:3333:4444::8888"), "IPV6 
:1111:2222:3333:4444::8888 should be invalid");
+        assertFalse(isValidInet6Address(":1111:2222:3333::8888"), "IPV6 
:1111:2222:3333::8888 should be invalid");
+        assertFalse(isValidInet6Address(":1111:2222::8888"), "IPV6 
:1111:2222::8888 should be invalid");
+        assertFalse(isValidInet6Address(":1111::8888"), "IPV6 :1111::8888 
should be invalid");
+        assertFalse(isValidInet6Address(":::8888"), "IPV6 :::8888 should be 
invalid");
+        assertFalse(
+                isValidInet6Address(":1111:2222:3333:4444:5555::7777:8888"),
+                "IPV6 :1111:2222:3333:4444:5555::7777:8888 should be invalid");
+        assertFalse(
+                isValidInet6Address(":1111:2222:3333:4444::7777:8888"),
+                "IPV6 :1111:2222:3333:4444::7777:8888 should be invalid");
+        assertFalse(
+                isValidInet6Address(":1111:2222:3333::7777:8888"), "IPV6 
:1111:2222:3333::7777:8888 should be invalid");
+        assertFalse(isValidInet6Address(":1111:2222::7777:8888"), "IPV6 
:1111:2222::7777:8888 should be invalid");
+        assertFalse(isValidInet6Address(":1111::7777:8888"), "IPV6 
:1111::7777:8888 should be invalid");
+        assertFalse(isValidInet6Address(":::7777:8888"), "IPV6 :::7777:8888 
should be invalid");
+        assertFalse(
+                isValidInet6Address(":1111:2222:3333:4444::6666:7777:8888"),
+                "IPV6 :1111:2222:3333:4444::6666:7777:8888 should be invalid");
+        assertFalse(
+                isValidInet6Address(":1111:2222:3333::6666:7777:8888"),
+                "IPV6 :1111:2222:3333::6666:7777:8888 should be invalid");
+        assertFalse(
+                isValidInet6Address(":1111:2222::6666:7777:8888"), "IPV6 
:1111:2222::6666:7777:8888 should be invalid");
+        assertFalse(isValidInet6Address(":1111::6666:7777:8888"), "IPV6 
:1111::6666:7777:8888 should be invalid");
+        assertFalse(isValidInet6Address(":::6666:7777:8888"), "IPV6 
:::6666:7777:8888 should be invalid");
+        assertFalse(
+                isValidInet6Address(":1111:2222:3333::5555:6666:7777:8888"),
+                "IPV6 :1111:2222:3333::5555:6666:7777:8888 should be invalid");
+        assertFalse(
+                isValidInet6Address(":1111:2222::5555:6666:7777:8888"),
+                "IPV6 :1111:2222::5555:6666:7777:8888 should be invalid");
+        assertFalse(
+                isValidInet6Address(":1111::5555:6666:7777:8888"), "IPV6 
:1111::5555:6666:7777:8888 should be invalid");
+        assertFalse(isValidInet6Address(":::5555:6666:7777:8888"), "IPV6 
:::5555:6666:7777:8888 should be invalid");
+        assertFalse(
+                isValidInet6Address(":1111:2222::4444:5555:6666:7777:8888"),
+                "IPV6 :1111:2222::4444:5555:6666:7777:8888 should be invalid");
+        assertFalse(
+                isValidInet6Address(":1111::4444:5555:6666:7777:8888"),
+                "IPV6 :1111::4444:5555:6666:7777:8888 should be invalid");
+        assertFalse(
+                isValidInet6Address(":::4444:5555:6666:7777:8888"),
+                "IPV6 :::4444:5555:6666:7777:8888 should be invalid");
+        assertFalse(
+                isValidInet6Address(":1111::3333:4444:5555:6666:7777:8888"),
+                "IPV6 :1111::3333:4444:5555:6666:7777:8888 should be invalid");
+        assertFalse(
+                isValidInet6Address(":::3333:4444:5555:6666:7777:8888"),
+                "IPV6 :::3333:4444:5555:6666:7777:8888 should be invalid");
+        assertFalse(
+                isValidInet6Address(":::2222:3333:4444:5555:6666:7777:8888"),
+                "IPV6 :::2222:3333:4444:5555:6666:7777:8888 should be 
invalid");
+        assertFalse(
+                isValidInet6Address(":1111:2222:3333:4444:5555:6666:1.2.3.4"),
+                "IPV6 :1111:2222:3333:4444:5555:6666:1.2.3.4 should be 
invalid");
+        assertFalse(
+                isValidInet6Address(":1111:2222:3333:4444:5555::1.2.3.4"),
+                "IPV6 :1111:2222:3333:4444:5555::1.2.3.4 should be invalid");
+        assertFalse(
+                isValidInet6Address(":1111:2222:3333:4444::1.2.3.4"),
+                "IPV6 :1111:2222:3333:4444::1.2.3.4 should be invalid");
+        assertFalse(isValidInet6Address(":1111:2222:3333::1.2.3.4"), "IPV6 
:1111:2222:3333::1.2.3.4 should be invalid");
+        assertFalse(isValidInet6Address(":1111:2222::1.2.3.4"), "IPV6 
:1111:2222::1.2.3.4 should be invalid");
+        assertFalse(isValidInet6Address(":1111::1.2.3.4"), "IPV6 
:1111::1.2.3.4 should be invalid");
+        assertFalse(isValidInet6Address(":::1.2.3.4"), "IPV6 :::1.2.3.4 should 
be invalid");
+        assertFalse(
+                isValidInet6Address(":1111:2222:3333:4444::6666:1.2.3.4"),
+                "IPV6 :1111:2222:3333:4444::6666:1.2.3.4 should be invalid");
+        assertFalse(
+                isValidInet6Address(":1111:2222:3333::6666:1.2.3.4"),
+                "IPV6 :1111:2222:3333::6666:1.2.3.4 should be invalid");
+        assertFalse(isValidInet6Address(":1111:2222::6666:1.2.3.4"), "IPV6 
:1111:2222::6666:1.2.3.4 should be invalid");
+        assertFalse(isValidInet6Address(":1111::6666:1.2.3.4"), "IPV6 
:1111::6666:1.2.3.4 should be invalid");
+        assertFalse(isValidInet6Address(":::6666:1.2.3.4"), "IPV6 
:::6666:1.2.3.4 should be invalid");
+        assertFalse(
+                isValidInet6Address(":1111:2222:3333::5555:6666:1.2.3.4"),
+                "IPV6 :1111:2222:3333::5555:6666:1.2.3.4 should be invalid");
+        assertFalse(
+                isValidInet6Address(":1111:2222::5555:6666:1.2.3.4"),
+                "IPV6 :1111:2222::5555:6666:1.2.3.4 should be invalid");
+        assertFalse(isValidInet6Address(":1111::5555:6666:1.2.3.4"), "IPV6 
:1111::5555:6666:1.2.3.4 should be invalid");
+        assertFalse(isValidInet6Address(":::5555:6666:1.2.3.4"), "IPV6 
:::5555:6666:1.2.3.4 should be invalid");
+        assertFalse(
+                isValidInet6Address(":1111:2222::4444:5555:6666:1.2.3.4"),
+                "IPV6 :1111:2222::4444:5555:6666:1.2.3.4 should be invalid");
+        assertFalse(
+                isValidInet6Address(":1111::4444:5555:6666:1.2.3.4"),
+                "IPV6 :1111::4444:5555:6666:1.2.3.4 should be invalid");
+        assertFalse(
+                isValidInet6Address(":::4444:5555:6666:1.2.3.4"), "IPV6 
:::4444:5555:6666:1.2.3.4 should be invalid");
+        assertFalse(
+                isValidInet6Address(":1111::3333:4444:5555:6666:1.2.3.4"),
+                "IPV6 :1111::3333:4444:5555:6666:1.2.3.4 should be invalid");
+        assertFalse(
+                isValidInet6Address(":::2222:3333:4444:5555:6666:1.2.3.4"),
+                "IPV6 :::2222:3333:4444:5555:6666:1.2.3.4 should be invalid");
+        // Extra : at end
+        assertFalse(
+                isValidInet6Address("1111:2222:3333:4444:5555:6666:7777:::"),
+                "IPV6 1111:2222:3333:4444:5555:6666:7777::: should be 
invalid");
+        assertFalse(
+                isValidInet6Address("1111:2222:3333:4444:5555:6666:::"),
+                "IPV6 1111:2222:3333:4444:5555:6666::: should be invalid");
+        assertFalse(
+                isValidInet6Address("1111:2222:3333:4444:5555:::"),
+                "IPV6 1111:2222:3333:4444:5555::: should be invalid");
+        assertFalse(isValidInet6Address("1111:2222:3333:4444:::"), "IPV6 
1111:2222:3333:4444::: should be invalid");
+        assertFalse(isValidInet6Address("1111:2222:3333:::"), "IPV6 
1111:2222:3333::: should be invalid");
+        assertFalse(isValidInet6Address("1111:2222:::"), "IPV6 1111:2222::: 
should be invalid");
+        assertFalse(isValidInet6Address("1111:::"), "IPV6 1111::: should be 
invalid");
+        assertFalse(
+                isValidInet6Address("1111:2222:3333:4444:5555:6666::8888:"),
+                "IPV6 1111:2222:3333:4444:5555:6666::8888: should be invalid");
+        assertFalse(
+                isValidInet6Address("1111:2222:3333:4444:5555::8888:"),
+                "IPV6 1111:2222:3333:4444:5555::8888: should be invalid");
+        assertFalse(
+                isValidInet6Address("1111:2222:3333:4444::8888:"), "IPV6 
1111:2222:3333:4444::8888: should be invalid");
+        assertFalse(isValidInet6Address("1111:2222:3333::8888:"), "IPV6 
1111:2222:3333::8888: should be invalid");
+        assertFalse(isValidInet6Address("1111:2222::8888:"), "IPV6 
1111:2222::8888: should be invalid");
+        assertFalse(isValidInet6Address("1111::8888:"), "IPV6 1111::8888: 
should be invalid");
+        assertFalse(isValidInet6Address("::8888:"), "IPV6 ::8888: should be 
invalid");
+        assertFalse(
+                isValidInet6Address("1111:2222:3333:4444:5555::7777:8888:"),
+                "IPV6 1111:2222:3333:4444:5555::7777:8888: should be invalid");
+        assertFalse(
+                isValidInet6Address("1111:2222:3333:4444::7777:8888:"),
+                "IPV6 1111:2222:3333:4444::7777:8888: should be invalid");
+        assertFalse(
+                isValidInet6Address("1111:2222:3333::7777:8888:"), "IPV6 
1111:2222:3333::7777:8888: should be invalid");
+        assertFalse(isValidInet6Address("1111:2222::7777:8888:"), "IPV6 
1111:2222::7777:8888: should be invalid");
+        assertFalse(isValidInet6Address("1111::7777:8888:"), "IPV6 
1111::7777:8888: should be invalid");
+        assertFalse(isValidInet6Address("::7777:8888:"), "IPV6 ::7777:8888: 
should be invalid");
+        assertFalse(
+                isValidInet6Address("1111:2222:3333:4444::6666:7777:8888:"),
+                "IPV6 1111:2222:3333:4444::6666:7777:8888: should be invalid");
+        assertFalse(
+                isValidInet6Address("1111:2222:3333::6666:7777:8888:"),
+                "IPV6 1111:2222:3333::6666:7777:8888: should be invalid");
+        assertFalse(
+                isValidInet6Address("1111:2222::6666:7777:8888:"), "IPV6 
1111:2222::6666:7777:8888: should be invalid");
+        assertFalse(isValidInet6Address("1111::6666:7777:8888:"), "IPV6 
1111::6666:7777:8888: should be invalid");
+        assertFalse(isValidInet6Address("::6666:7777:8888:"), "IPV6 
::6666:7777:8888: should be invalid");
+        assertFalse(
+                isValidInet6Address("1111:2222:3333::5555:6666:7777:8888:"),
+                "IPV6 1111:2222:3333::5555:6666:7777:8888: should be invalid");
+        assertFalse(
+                isValidInet6Address("1111:2222::5555:6666:7777:8888:"),
+                "IPV6 1111:2222::5555:6666:7777:8888: should be invalid");
+        assertFalse(
+                isValidInet6Address("1111::5555:6666:7777:8888:"), "IPV6 
1111::5555:6666:7777:8888: should be invalid");
+        assertFalse(isValidInet6Address("::5555:6666:7777:8888:"), "IPV6 
::5555:6666:7777:8888: should be invalid");
+        assertFalse(
+                isValidInet6Address("1111:2222::4444:5555:6666:7777:8888:"),
+                "IPV6 1111:2222::4444:5555:6666:7777:8888: should be invalid");
+        assertFalse(
+                isValidInet6Address("1111::4444:5555:6666:7777:8888:"),
+                "IPV6 1111::4444:5555:6666:7777:8888: should be invalid");
+        assertFalse(
+                isValidInet6Address("::4444:5555:6666:7777:8888:"),
+                "IPV6 ::4444:5555:6666:7777:8888: should be invalid");
+        assertFalse(
+                isValidInet6Address("1111::3333:4444:5555:6666:7777:8888:"),
+                "IPV6 1111::3333:4444:5555:6666:7777:8888: should be invalid");
+        assertFalse(
+                isValidInet6Address("::3333:4444:5555:6666:7777:8888:"),
+                "IPV6 ::3333:4444:5555:6666:7777:8888: should be invalid");
+        assertFalse(
+                isValidInet6Address("::2222:3333:4444:5555:6666:7777:8888:"),
+                "IPV6 ::2222:3333:4444:5555:6666:7777:8888: should be 
invalid");
+        assertTrue(isValidInet6Address("0:a:b:c:d:e:f::"), "IPV6 
0:a:b:c:d:e:f:: should be valid");
+        assertTrue(
+                isValidInet6Address("::0:a:b:c:d:e:f"),
+                "IPV6 ::0:a:b:c:d:e:f should be valid"); // syntactically 
correct, but bad form (::0:...
+        // could be combined)
+        assertTrue(isValidInet6Address("a:b:c:d:e:f:0::"), "IPV6 
a:b:c:d:e:f:0:: should be valid");
+        assertFalse(isValidInet6Address("':10.0.0.1"), "IPV6 ':10.0.0.1 should 
be invalid");
+    }
+
+    /**
+     * Test reserved IPs.
+     */
+    @Test
+    void testReservedInetAddresses() {
+        assertTrue(isValid("127.0.0.1"), "localhost IP should be valid");
+        assertTrue(isValid("255.255.255.255"), "broadcast IP should be valid");
+    }
+
+    @Test
+    void testValidator335() {
+        assertTrue(
+                isValid("2001:0438:FFFE:0000:0000:0000:0000:0A35"),
+                "2001:0438:FFFE:0000:0000:0000:0000:0A35 should be valid");
+    }
+
+    @Test
+    void testValidator419() {
+        String addr;
+        addr = "0:0:0:0:0:0:13.1.68.3";
+        assertTrue(isValid(addr));
+        addr = "0:0:0:0:0:FFFF:129.144.52.38";
+        assertTrue(isValid(addr), addr);
+        addr = "::13.1.68.3";
+        assertTrue(isValid(addr), addr);
+        addr = "::FFFF:129.144.52.38";
+        assertTrue(isValid(addr), addr);
+
+        addr = "::ffff:192.168.1.1:192.168.1.1";
+        assertFalse(isValid(addr), addr);
+        addr = "::192.168.1.1:192.168.1.1";
+        assertFalse(isValid(addr), addr);
+    }
+
+    /**
+     * Inet6Address may also contain a scope id.
+     */
+    @Test
+    void testValidator445() {
+        final String[] valid = {
+            "2001:0000:1234:0000:0000:C1C0:ABCD:0876",
+            "2001:0000:1234:0000:0000:C1C0:ABCD:0876/123",
+            "2001:0000:1234:0000:0000:C1C0:ABCD:0876/0",
+            "2001:0000:1234:0000:0000:C1C0:ABCD:0876%0",
+            "2001:0000:1234:0000:0000:C1C0:ABCD:0876%abcdefgh",
+        };
+        final String[] invalid = {
+            "2001:0000:1234:0000:0000:C1C0:ABCD:0876/129", // too big
+            "2001:0000:1234:0000:0000:C1C0:ABCD:0876/-0", // sign not allowed
+            "2001:0000:1234:0000:0000:C1C0:ABCD:0876/+0", // sign not allowed
+            "2001:0000:1234:0000:0000:C1C0:ABCD:0876/10O", // non-digit
+            "2001:0000:1234:0000:0000:C1C0:ABCD:0876/0%0", // /bits before 
%node-id
+            "2001:0000:1234:0000:0000:C1C0:ABCD:0876%abc defgh", // space in 
node id
+            "2001:0000:1234:0000:0000:C1C0:ABCD:0876%abc%defgh", // '%' in 
node id
+        };
+        for (final String item : valid) {
+            assertTrue(isValid(item), item + " should be valid");
+        }
+        for (final String item : invalid) {
+            assertFalse(isValid(item), item + " should be invalid");
+        }
+    }
+}
diff --git 
a/log4j-core/src/main/java/org/apache/logging/log4j/core/net/SslSocketManager.java
 
b/log4j-core/src/main/java/org/apache/logging/log4j/core/net/SslSocketManager.java
index 994f11bbce..70f8e89d28 100644
--- 
a/log4j-core/src/main/java/org/apache/logging/log4j/core/net/SslSocketManager.java
+++ 
b/log4j-core/src/main/java/org/apache/logging/log4j/core/net/SslSocketManager.java
@@ -30,19 +30,22 @@ import java.util.List;
 import java.util.Objects;
 import java.util.stream.Collectors;
 import java.util.stream.Stream;
+import javax.net.ssl.SNIHostName;
 import javax.net.ssl.SSLContext;
+import javax.net.ssl.SSLParameters;
 import javax.net.ssl.SSLSocket;
 import javax.net.ssl.SSLSocketFactory;
 import org.apache.logging.log4j.core.Layout;
 import org.apache.logging.log4j.core.net.ssl.SslConfiguration;
+import org.apache.logging.log4j.core.net.ssl.internal.InetAddressValidator;
 import org.apache.logging.log4j.util.Strings;
 
-/**
- *
- */
 public class SslSocketManager extends TcpSocketManager {
+
     public static final int DEFAULT_PORT = 6514;
+
     private static final SslSocketManagerFactory FACTORY = new 
SslSocketManagerFactory();
+
     private final SslConfiguration sslConfig;
 
     /**
@@ -285,10 +288,7 @@ public class SslSocketManager extends TcpSocketManager {
 
     @Override
     protected Socket createSocket(final InetSocketAddress socketAddress) 
throws IOException {
-        final SSLSocketFactory socketFactory = 
createSslSocketFactory(sslConfig);
-        final Socket newSocket = socketFactory.createSocket();
-        newSocket.connect(socketAddress, getConnectTimeoutMillis());
-        return newSocket;
+        return createSocket(getHost(), socketAddress, 
getConnectTimeoutMillis(), sslConfig, getSocketOptions());
     }
 
     private static SSLSocketFactory createSslSocketFactory(final 
SslConfiguration sslConf) {
@@ -333,32 +333,65 @@ public class SslSocketManager extends TcpSocketManager {
             for (InetSocketAddress socketAddress : socketAddresses) {
                 try {
                     return SslSocketManager.createSocket(
-                            socketAddress, data.connectTimeoutMillis, 
data.sslConfiguration, data.socketOptions);
+                            data.host,
+                            socketAddress,
+                            data.connectTimeoutMillis,
+                            data.sslConfiguration,
+                            data.socketOptions);
                 } catch (IOException ex) {
-                    ioe = ex;
+                    final String message = String.format(
+                            "failed create a socket to `%s:%s` that is 
resolved to address `%s`",
+                            data.host, data.port, socketAddress);
+                    final IOException newEx = new IOException(message, ex);
+                    if (ioe == null) {
+                        ioe = newEx;
+                    } else {
+                        ioe.addSuppressed(newEx);
+                    }
                 }
             }
             throw new IOException(errorMessage(data, socketAddresses), ioe);
         }
     }
 
-    static Socket createSocket(
+    private static Socket createSocket(
+            final String hostName,
             final InetSocketAddress socketAddress,
             final int connectTimeoutMillis,
             final SslConfiguration sslConfiguration,
             final SocketOptions socketOptions)
             throws IOException {
+
+        // Create the `SSLSocket`
         final SSLSocketFactory socketFactory = 
createSslSocketFactory(sslConfiguration);
         final SSLSocket socket = (SSLSocket) socketFactory.createSocket();
+
+        // Apply socket options before `connect()`
         if (socketOptions != null) {
-            // Not sure which options must be applied before or after the 
connect() call.
             socketOptions.apply(socket);
         }
+
+        // Connect the socket
         socket.connect(socketAddress, connectTimeoutMillis);
-        if (socketOptions != null) {
-            // Not sure which options must be applied before or after the 
connect() call.
-            socketOptions.apply(socket);
+
+        // Verify the host name
+        if (sslConfiguration.isVerifyHostName()) {
+            // Allowed endpoint identification algorithms: HTTPS and LDAPS.
+            // 
https://docs.oracle.com/en/java/javase/17/docs/specs/security/standard-names.html#endpoint-identification-algorithms
+            final SSLParameters sslParameters = socket.getSSLParameters();
+            sslParameters.setEndpointIdentificationAlgorithm("HTTPS");
+            // Literal IPv4 and IPv6 addresses are not permitted in "HostName".
+            // https://www.rfc-editor.org/rfc/rfc6066.html#section-3
+            if (!InetAddressValidator.isValid(hostName)) {
+                sslParameters.setServerNames(Collections.singletonList(new 
SNIHostName(hostName)));
+            }
+            socket.setSSLParameters(sslParameters);
         }
+
+        // Force the handshake right after `connect()` instead of waiting for 
read/write to trigger it indirectly at a
+        // later stage
+        socket.startHandshake();
+
         return socket;
     }
 }
diff --git 
a/log4j-core/src/main/java/org/apache/logging/log4j/core/net/ssl/SslConfiguration.java
 
b/log4j-core/src/main/java/org/apache/logging/log4j/core/net/ssl/SslConfiguration.java
index 41e2fc1031..a27febcabb 100644
--- 
a/log4j-core/src/main/java/org/apache/logging/log4j/core/net/ssl/SslConfiguration.java
+++ 
b/log4j-core/src/main/java/org/apache/logging/log4j/core/net/ssl/SslConfiguration.java
@@ -132,8 +132,8 @@ public class SslConfiguration {
             @Nullable final TrustStoreConfiguration trustStoreConfig) {
         try {
             final SSLContext sslContext = SSLContext.getInstance(protocol);
-            final KeyManager[] keyManagers = loadKeyManagers(keyStoreConfig);
-            final TrustManager[] trustManagers = 
loadTrustManagers(trustStoreConfig);
+            @Nullable final KeyManager[] keyManagers = 
loadKeyManagers(keyStoreConfig);
+            @Nullable final TrustManager[] trustManagers = 
loadTrustManagers(trustStoreConfig);
             sslContext.init(keyManagers, trustManagers, null);
             return sslContext;
         } catch (final Exception error) {
@@ -144,9 +144,11 @@ public class SslConfiguration {
         }
     }
 
+    @Nullable
+    @NullUnmarked
     private static KeyManager[] loadKeyManagers(@Nullable final 
KeyStoreConfiguration config) throws Exception {
         if (config == null) {
-            return new KeyManager[0];
+            return null;
         }
         final KeyManagerFactory factory = 
KeyManagerFactory.getInstance(config.getKeyManagerFactoryAlgorithm());
         final char[] password = config.getPasswordAsCharArray();
@@ -158,9 +160,11 @@ public class SslConfiguration {
         return factory.getKeyManagers();
     }
 
+    @Nullable
+    @NullUnmarked
     private static TrustManager[] loadTrustManagers(@Nullable final 
TrustStoreConfiguration config) throws Exception {
         if (config == null) {
-            return new TrustManager[0];
+            return null;
         }
         final TrustManagerFactory factory = 
TrustManagerFactory.getInstance(config.getTrustManagerFactoryAlgorithm());
         factory.init(config.getKeyStore());
diff --git 
a/log4j-core/src/main/java/org/apache/logging/log4j/core/net/ssl/internal/InetAddressValidator.java
 
b/log4j-core/src/main/java/org/apache/logging/log4j/core/net/ssl/internal/InetAddressValidator.java
new file mode 100644
index 0000000000..133c8a4043
--- /dev/null
+++ 
b/log4j-core/src/main/java/org/apache/logging/log4j/core/net/ssl/internal/InetAddressValidator.java
@@ -0,0 +1,171 @@
+/*
+ * 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.logging.log4j.core.net.ssl.internal;
+
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.List;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+import org.apache.logging.log4j.util.Strings;
+
+/**
+ * {@link java.net.InetAddress} literal validator.
+ *
+ * @implNote
+ * IP address validation is hard.
+ * IPv6 validation is copied from Apache Commons Validator.
+ * This is an internal class with a very limited usage, and should stay that 
way.
+ * This class should be replaced with {@code 
java.net.InetAddress#ofLiteral(String)} introduced in Java 22.
+ *
+ * @see <a 
href="https://github.com/apache/commons-validator/blob/7c27355d86f7dc5a4a548658745b85c9f0d5b99f/src/main/java/org/apache/commons/validator/routines/InetAddressValidator.java";><code>InetAddressValidator</code>
 of Apache Commons Validator</a>
+ */
+public final class InetAddressValidator {
+
+    private static final Pattern IPV4_PATTERN = 
Pattern.compile("^(\\d{1,3})\\.(\\d{1,3})\\.(\\d{1,3})\\.(\\d{1,3})$");
+
+    /** Max number of hex groups (separated by {@code :}) in an IPV6 address */
+    private static final int IPV6_MAX_HEX_GROUPS = 8;
+
+    /** Max hex digits in each IPv6 group */
+    private static final int IPV6_MAX_HEX_DIGITS_PER_GROUP = 4;
+
+    private static final Pattern DIGITS_PATTERN = Pattern.compile("\\d{1,3}");
+
+    private static final Pattern ID_CHECK_PATTERN = 
Pattern.compile("[^\\s/%]+");
+
+    private InetAddressValidator() {}
+
+    /**
+     * {@return {@code true} if the provided string is a valid IPv4 or IPv6 
address, {@code false} otherwise}.
+     * Verification is performed without any name resolution.
+     *
+     * @param inetAddress the string to validate
+     */
+    public static boolean isValid(final String inetAddress) {
+        return isValidInet4Address(inetAddress) || 
isValidInet6Address(inetAddress);
+    }
+
+    static boolean isValidInet4Address(final String inet4Address) {
+        final Matcher m = IPV4_PATTERN.matcher(inet4Address);
+        if (!m.matches()) {
+            return false;
+        }
+        for (int i = 1; i <= 4; i++) {
+            final String g = m.group(i);
+            if (g.length() > 1 && g.startsWith("0")) {
+                return false;
+            }
+            final int n;
+            try {
+                n = Integer.parseInt(g);
+            } catch (final NumberFormatException ignored) {
+                return false;
+            }
+            if (n > 0xFF) {
+                return false;
+            }
+        }
+        return true;
+    }
+
+    static boolean isValidInet6Address(String inet6Address) {
+        String[] parts;
+        // remove prefix size. This will appear after the zone id (if any)
+        parts = inet6Address.split("/", -1);
+        if (parts.length > 2) {
+            return false; // can only have one prefix specifier
+        }
+        if (parts.length == 2) {
+            if (!DIGITS_PATTERN.matcher(parts[1]).matches()) {
+                return false; // not a valid number
+            }
+            final int bits = Integer.parseInt(parts[1]); // cannot fail 
because of RE check
+            if (bits < 0 || bits > 128) {
+                return false; // out of range
+            }
+        }
+        // remove zone-id
+        parts = parts[0].split("%", -1);
+        // The id syntax is implementation independent, but it presumably 
cannot allow:
+        // whitespace, '/' or '%'
+        if (parts.length > 2
+                || parts.length == 2 && 
!ID_CHECK_PATTERN.matcher(parts[1]).matches()) {
+            return false; // invalid id
+        }
+        inet6Address = parts[0];
+        final boolean containsCompressedZeroes = inet6Address.contains("::");
+        if (containsCompressedZeroes && inet6Address.indexOf("::") != 
inet6Address.lastIndexOf("::")) {
+            return false;
+        }
+        final boolean startsWithCompressed = inet6Address.startsWith("::");
+        final boolean endsWithCompressed = inet6Address.endsWith("::");
+        final boolean endsWithSep = inet6Address.endsWith(":");
+        if (inet6Address.startsWith(":") && !startsWithCompressed || 
endsWithSep && !endsWithCompressed) {
+            return false;
+        }
+        String[] octets = inet6Address.split(":");
+        if (containsCompressedZeroes) {
+            final List<String> octetList = new 
ArrayList<>(Arrays.asList(octets));
+            if (endsWithCompressed) {
+                // String.split() drops ending empty segments
+                octetList.add("");
+            } else if (startsWithCompressed && !octetList.isEmpty()) {
+                octetList.remove(0);
+            }
+            octets = octetList.toArray(new String[0]);
+        }
+        if (octets.length > IPV6_MAX_HEX_GROUPS) {
+            return false;
+        }
+        int validOctets = 0;
+        int emptyOctets = 0; // consecutive empty chunks
+        for (int index = 0; index < octets.length; index++) {
+            final String octet = octets[index];
+            if (Strings.isBlank(octet)) {
+                emptyOctets++;
+                if (emptyOctets > 1) {
+                    return false;
+                }
+            } else {
+                emptyOctets = 0;
+                // Is last chunk an IPv4 address?
+                if (index == octets.length - 1 && octet.contains(".")) {
+                    if (!isValidInet4Address(octet)) {
+                        return false;
+                    }
+                    validOctets += 2;
+                    continue;
+                }
+                if (octet.length() > IPV6_MAX_HEX_DIGITS_PER_GROUP) {
+                    return false;
+                }
+                int octetInt = 0;
+                try {
+                    octetInt = Integer.parseInt(octet, 16);
+                } catch (final NumberFormatException e) {
+                    return false;
+                }
+                if (octetInt < 0 || octetInt > 0xffff) {
+                    return false;
+                }
+            }
+            validOctets++;
+        }
+        return validOctets <= IPV6_MAX_HEX_GROUPS && (validOctets >= 
IPV6_MAX_HEX_GROUPS || containsCompressedZeroes);
+    }
+}


Reply via email to