NetworkUtils/test/dorkbox/netUtil/IpValidationTests.kt

824 lines
36 KiB
Kotlin

/*
* Copyright 2012 The Netty Project
*
* The Netty Project 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 dorkbox.netUtil
import dorkbox.netUtil.ping.Ping
import org.junit.Assert.assertEquals
import org.junit.Assert.assertFalse
import org.junit.Assert.assertNotNull
import org.junit.Assert.assertNull
import org.junit.Assert.assertTrue
import org.junit.Test
import java.net.Inet6Address
import java.net.InetAddress
import java.net.InetSocketAddress
import java.net.UnknownHostException
class IpValidationTests {
companion object {
private val validIpV4Hosts = mapOf(
"192.168.1.0" to "c0a80100",
"10.255.255.254" to "0afffffe",
"172.18.5.4" to "ac120504",
"0.0.0.0" to "00000000",
"127.0.0.1" to "7f000001",
"255.255.255.255" to "ffffffff",
"1.2.3.4" to "01020304")
private val invalidIpV4Hosts = mapOf(
"1.256.3.4" to null,
"256.0.0.1" to null,
"1.1.1.1.1" to null,
"x.255.255.255" to null,
"0.1:0.0" to null,
"0.1.0.0:" to null,
"127.0.0." to null,
"1.2..4" to null,
"192.0.1" to null,
"192.0.1.1.1" to null,
"192.0.1.a" to null,
"19a.0.1.1" to null,
"a.0.1.1" to null,
".0.1.1" to null,
"127.0.0" to null,
"192.0.1.256" to null,
"0.0.200.259" to null,
"1.1.-1.1" to null,
"1.1. 1.1" to null,
"1.1.1.1 " to null,
"1.1.+1.1" to null,
"0.0x1.0.255" to null,
"0.01x.0.255" to null,
"0.x01.0.255" to null,
"0.-.0.0" to null,
"0..0.0" to null,
"0.A.0.0" to null,
"0.1111.0.0" to null,
"..." to null)
private val validIpV6Hosts = mapOf(
"::ffff:5.6.7.8" to "00000000000000000000ffff05060708",
"fdf8:f53b:82e4::53" to "fdf8f53b82e400000000000000000053",
"fe80::200:5aee:feaa:20a2" to "fe8000000000000002005aeefeaa20a2",
"2001::1" to "20010000000000000000000000000001",
"2001:0000:4136:e378:8000:63bf:3fff:fdd2" to "200100004136e378800063bf3ffffdd2",
"2001:0002:6c::430" to "20010002006c00000000000000000430",
"2001:10:240:ab::a" to "20010010024000ab000000000000000a",
"2002:cb0a:3cdd:1::1" to "2002cb0a3cdd00010000000000000001",
"2001:db8:8:4::2" to "20010db8000800040000000000000002",
"ff01:0:0:0:0:0:0:2" to "ff010000000000000000000000000002",
"[fdf8:f53b:82e4::53]" to "fdf8f53b82e400000000000000000053",
"[fe80::200:5aee:feaa:20a2]" to "fe8000000000000002005aeefeaa20a2",
"[2001::1]" to "20010000000000000000000000000001",
"[2001:0000:4136:e378:8000:63bf:3fff:fdd2]" to "200100004136e378800063bf3ffffdd2",
"0:1:2:3:4:5:6:789a" to "0000000100020003000400050006789a",
"0:1:2:3::f" to "0000000100020003000000000000000f",
"0:0:0:0:0:0:10.0.0.1" to "00000000000000000000ffff0a000001",
"0:0:0:0:0::10.0.0.1" to "00000000000000000000ffff0a000001",
"0:0:0:0::10.0.0.1" to "00000000000000000000ffff0a000001",
"::0:0:0:0:0:10.0.0.1" to "00000000000000000000ffff0a000001",
"0::0:0:0:0:10.0.0.1" to "00000000000000000000ffff0a000001",
"0:0::0:0:0:10.0.0.1" to "00000000000000000000ffff0a000001",
"0:0:0::0:0:10.0.0.1" to "00000000000000000000ffff0a000001",
"0:0:0:0::0:10.0.0.1" to "00000000000000000000ffff0a000001",
"0:0:0:0:0:ffff:10.0.0.1" to "00000000000000000000ffff0a000001",
"::ffff:192.168.0.1" to "00000000000000000000ffffc0a80001",
// Test if various interface names after the percent sign are recognized.
"[::1%1]" to "00000000000000000000000000000001",
"[::1%eth0]" to "00000000000000000000000000000001",
"[::1%%]" to "00000000000000000000000000000001",
"0:0:0:0:0:ffff:10.0.0.1%" to "00000000000000000000ffff0a000001",
"0:0:0:0:0:ffff:10.0.0.1%1" to "00000000000000000000ffff0a000001",
"[0:0:0:0:0:ffff:10.0.0.1%1]" to "00000000000000000000ffff0a000001",
"[0:0:0:0:0::10.0.0.1%1]" to "00000000000000000000ffff0a000001",
"[::0:0:0:0:ffff:10.0.0.1%1]" to "00000000000000000000ffff0a000001",
"::0:0:0:0:ffff:10.0.0.1%1" to "00000000000000000000ffff0a000001",
"::1%1" to "00000000000000000000000000000001",
"::1%eth0" to "00000000000000000000000000000001",
"::1%%" to "00000000000000000000000000000001",
// Tests with leading or trailing compression
"0:0:0:0:0:0:0::" to "00000000000000000000000000000000",
"0:0:0:0:0:0::" to "00000000000000000000000000000000",
"0:0:0:0:0::" to "00000000000000000000000000000000",
"0:0:0:0::" to "00000000000000000000000000000000",
"0:0:0::" to "00000000000000000000000000000000",
"0:0::" to "00000000000000000000000000000000",
"0::" to "00000000000000000000000000000000",
"::" to "00000000000000000000000000000000",
"::0" to "00000000000000000000000000000000",
"::0:0" to "00000000000000000000000000000000",
"::0:0:0" to "00000000000000000000000000000000",
"::0:0:0:0" to "00000000000000000000000000000000",
"::0:0:0:0:0" to "00000000000000000000000000000000",
"::0:0:0:0:0:0" to "00000000000000000000000000000000",
"::0:0:0:0:0:0:0" to "00000000000000000000000000000000")
private val invalidIpV6Hosts = mapOf(
// Test method with garbage.
"Obvious Garbage" to null,
// Test method with preferred style, too many :
"0:1:2:3:4:5:6:7:8" to null,
// Test method with preferred style, not enough :
"0:1:2:3:4:5:6" to null,
// Test method with preferred style, bad digits.
"0:1:2:3:4:5:6:x" to null,
// Test method with preferred style, adjacent :
"0:1:2:3:4:5:6::7" to null,
// Too many : separators trailing
"0:1:2:3:4:5:6:7::" to null,
// Too many : separators leading
"::0:1:2:3:4:5:6:7" to null,
// Too many : separators trailing
"1:2:3:4:5:6:7:" to null,
// Too many : separators leading
":1:2:3:4:5:6:7" to null,
// Compression with : separators trailing
"0:1:2:3:4:5::7:" to null,
"0:1:2:3:4::7:" to null,
"0:1:2:3::7:" to null,
"0:1:2::7:" to null,
"0:1::7:" to null,
"0::7:" to null,
// Compression at start with : separators trailing
"::0:1:2:3:4:5:7:" to null,
"::0:1:2:3:4:7:" to null,
"::0:1:2:3:7:" to null,
"::0:1:2:7:" to null,
"::0:1:7:" to null,
"::7:" to null,
// The : separators leading and trailing
":1:2:3:4:5:6:7:" to null,
":1:2:3:4:5:6:" to null,
":1:2:3:4:5:" to null,
":1:2:3:4:" to null,
":1:2:3:" to null,
":1:2:" to null,
":1:" to null,
// Compression with : separators leading
":1::2:3:4:5:6:7" to null,
":1::3:4:5:6:7" to null,
":1::4:5:6:7" to null,
":1::5:6:7" to null,
":1::6:7" to null,
":1::7" to null,
":1:2:3:4:5:6::7" to null,
":1:3:4:5:6::7" to null,
":1:4:5:6::7" to null,
":1:5:6::7" to null,
":1:6::7" to null,
":1::" to null,
// Compression trailing with : separators leading
":1:2:3:4:5:6:7::" to null,
":1:3:4:5:6:7::" to null,
":1:4:5:6:7::" to null,
":1:5:6:7::" to null,
":1:6:7::" to null,
":1:7::" to null,
// Double compression
"1::2:3:4:5:6::" to null,
"::1:2:3:4:5::6" to null,
"::1:2:3:4:5:6::" to null,
"::1:2:3:4:5::" to null,
"::1:2:3:4::" to null,
"::1:2:3::" to null,
"::1:2::" to null,
"::0::" to null,
"12::0::12" to null,
// Too many : separators leading 0
"0::1:2:3:4:5:6:7" to null,
// Test method with preferred style, too many digits.
"0:1:2:3:4:5:6:789abcdef" to null,
// Test method with compressed style, bad digits.
"0:1:2:3::x" to null,
// Test method with compressed style to too many adjacent :
"0:1:2:::3" to null,
// Test method with compressed style, too many digits.
"0:1:2:3::abcde" to null,
// Test method with compressed style, not enough :
"0:1" to null,
// Test method with ipv4 style, bad ipv6 digits.
"0:0:0:0:0:x:10.0.0.1" to null,
// Test method with ipv4 style, bad ipv4 digits.
"0:0:0:0:0:0:10.0.0.x" to null,
// Test method with ipv4 style, too many ipv6 digits.
"0:0:0:0:0:00000:10.0.0.1" to null,
// Test method with ipv4 style, too many :
"0:0:0:0:0:0:0:10.0.0.1" to null,
// Test method with ipv4 style, not enough :
"0:0:0:0:0:10.0.0.1" to null,
// Test method with ipv4 style, too many .
"0:0:0:0:0:0:10.0.0.0.1" to null,
// Test method with ipv4 style, not enough .
"0:0:0:0:0:0:10.0.1" to null,
// Test method with ipv4 style, adjacent .
"0:0:0:0:0:0:10..0.0.1" to null,
// Test method with ipv4 style, leading .
"0:0:0:0:0:0:.0.0.1" to null,
// Test method with ipv4 style, leading .
"0:0:0:0:0:0:.10.0.0.1" to null,
// Test method with ipv4 style, trailing .
"0:0:0:0:0:0:10.0.0." to null,
// Test method with ipv4 style, trailing .
"0:0:0:0:0:0:10.0.0.1." to null,
// Test method with compressed ipv4 style, bad ipv6 digits.
"::fffx:192.168.0.1" to null,
// Test method with compressed ipv4 style, bad ipv4 digits.
"::ffff:192.168.0.x" to null,
// Test method with compressed ipv4 style, too many adjacent :
":::ffff:192.168.0.1" to null,
// Test method with compressed ipv4 style, too many ipv6 digits.
"::fffff:192.168.0.1" to null,
// Test method with compressed ipv4 style, too many ipv4 digits.
"::ffff:1923.168.0.1" to null,
// Test method with compressed ipv4 style, not enough :
":ffff:192.168.0.1" to null,
// Test method with compressed ipv4 style, too many .
"::ffff:192.168.0.1.2" to null,
// Test method with compressed ipv4 style, not enough .
"::ffff:192.168.0" to null,
// Test method with compressed ipv4 style, adjacent .
"::ffff:192.168..0.1" to null,
// Test method, bad ipv6 digits.
"x:0:0:0:0:0:10.0.0.1" to null,
// Test method, bad ipv4 digits.
"0:0:0:0:0:0:x.0.0.1" to null,
// Test method, too many ipv6 digits.
"00000:0:0:0:0:0:10.0.0.1" to null,
// Test method, too many ipv4 digits.
"0:0:0:0:0:0:10.0.0.1000" to null,
// Test method, too many :
"0:0:0:0:0:0:0:10.0.0.1" to null,
// Test method, not enough :
"0:0:0:0:0:10.0.0.1" to null,
// Test method, out of order trailing :
"0:0:0:0:0:10.0.0.1:" to null,
// Test method, out of order leading :
":0:0:0:0:0:10.0.0.1" to null,
// Test method, out of order leading :
"0:0:0:0::10.0.0.1:" to null,
// Test method, out of order trailing :
":0:0:0:0::10.0.0.1" to null,
// Test method, too many .
"0:0:0:0:0:0:10.0.0.0.1" to null,
// Test method, not enough .
"0:0:0:0:0:0:10.0.1" to null,
// Test method, adjacent .
"0:0:0:0:0:0:10.0.0..1" to null,
// Empty contents
"" to null,
// Invalid single compression
":" to null,
":::" to null,
// Trailing : (max number of : = 8)
"2001:0:4136:e378:8000:63bf:3fff:fdd2:" to null,
// Leading : (max number of : = 8)
":aaaa:bbbb:cccc:dddd:eeee:ffff:1111:2222" to null,
// Invalid character
"1234:2345:3456:4567:5678:6789::X890" to null,
// Trailing . in IPv4
"::ffff:255.255.255.255." to null,
// To many characters in IPv4
"::ffff:0.0.1111.0" to null,
// Test method, adjacent .
"::ffff:0.0..0" to null,
// Not enough IPv4 entries trailing .
"::ffff:127.0.0." to null,
// Invalid trailing IPv4 character
"::ffff:127.0.0.a" to null,
// Invalid leading IPv4 character
"::ffff:a.0.0.1" to null,
// Invalid middle IPv4 character
"::ffff:127.a.0.1" to null,
// Invalid middle IPv4 character
"::ffff:127.0.a.1" to null,
// Not enough IPv4 entries no trailing .
"::ffff:1.2.4" to null,
// Extra IPv4 entry
"::ffff:192.168.0.1.255" to null,
// Not enough IPv6 content
":ffff:192.168.0.1.255" to null,
// Intermixed IPv4 and IPv6 symbols
"::ffff:255.255:255.255." to null,
// Invalid IPv4 mapped address - invalid ipv4 separator
"0:0:0::0:0:00f.0.0.1" to null,
// Invalid IPv4 mapped address - not enough f's
"0:0:0:0:0:fff:1.0.0.1" to null,
// Invalid IPv4 mapped address - not IPv4 mapped, not IPv4 compatible
"0:0:0:0:0:ff00:1.0.0.1" to null,
// Invalid IPv4 mapped address - not IPv4 mapped, not IPv4 compatible
"0:0:0:0:0:ff:1.0.0.1" to null,
// Invalid IPv4 mapped address - too many f's
"0:0:0:0:0:fffff:1.0.0.1" to null,
// Invalid IPv4 mapped address - too many bytes (too many 0's)
"0:0:0:0:0:0:ffff:1.0.0.1" to null,
// Invalid IPv4 mapped address - too many bytes (too many 0's)
"::0:0:0:0:0:ffff:1.0.0.1" to null,
// Invalid IPv4 mapped address - too many bytes (too many 0's)
"0:0:0:0:0:0::1.0.0.1" to null,
// Invalid IPv4 mapped address - too many bytes (too many 0's)
"0:0:0:0:0:00000:1.0.0.1" to null,
// Invalid IPv4 mapped address - too few bytes (not enough 0's)
"0:0:0:0:ffff:1.0.0.1" to null,
// Invalid IPv4 mapped address - too few bytes (not enough 0's)
"ffff:192.168.0.1" to null,
// Invalid IPv4 mapped address - 0's after the mapped ffff indicator
"0:0:0:0:0:ffff::10.0.0.1" to null,
// Invalid IPv4 mapped address - 0's after the mapped ffff indicator
"0:0:0:0:ffff::10.0.0.1" to null,
// Invalid IPv4 mapped address - 0's after the mapped ffff indicator
"0:0:0:ffff::10.0.0.1" to null,
// Invalid IPv4 mapped address - 0's after the mapped ffff indicator
"0:0:ffff::10.0.0.1" to null,
// Invalid IPv4 mapped address - 0's after the mapped ffff indicator
"0:ffff::10.0.0.1" to null,
// Invalid IPv4 mapped address - 0's after the mapped ffff indicator
"ffff::10.0.0.1" to null,
// Invalid IPv4 mapped address - not all 0's before the mapped separator
"1:0:0:0:0:ffff:10.0.0.1" to null,
// Address that is similar to IPv4 mapped, but is invalid
"0:0:0:0:ffff:ffff:1.0.0.1" to null,
// Valid number of separators, but invalid IPv4 format
"::1:2:3:4:5:6.7.8.9" to null,
// Too many digits
"0:0:0:0:0:0:ffff:10.0.0.1" to null,
// Invalid IPv4 format
":1.2.3.4" to null,
// Invalid IPv4 format
"::.2.3.4" to null,
// Invalid IPv4 format
"::ffff:0.1.2." to null)
private val ipv6ToAddressStrings = mapOf(
// From the RFC 5952 http://tools.ietf.org/html/rfc5952#section-4
byteArrayOf(
32, 1, 13, -72,
0, 0, 0, 0,
0, 0, 0, 0,
0, 0, 0, 1
) to "2001:db8::1",
byteArrayOf(
32, 1, 13, -72,
0, 0, 0, 0,
0, 0, 0, 0,
0, 2, 0, 1
) to "2001:db8::2:1",
byteArrayOf(
32, 1, 13, -72,
0, 0, 0, 1,
0, 1, 0, 1,
0, 1, 0, 1
) to "2001:db8:0:1:1:1:1:1",
// Other examples
byteArrayOf(
32, 1, 13, -72,
0, 0, 0, 0,
0, 0, 0, 0,
0, 2, 0, 1
) to "2001:db8::2:1",
byteArrayOf(
32, 1, 0, 0,
0, 0, 0, 1,
0, 0, 0, 0,
0, 0, 0, 1
) to "2001:0:0:1::1",
byteArrayOf(
32, 1, 13, -72,
0, 0, 0, 0,
0, 1, 0, 0,
0, 0, 0, 1
) to "2001:db8::1:0:0:1",
byteArrayOf(
32, 1, 13, -72,
0, 0, 0, 0,
0, 1, 0, 0,
0, 0, 0, 0
) to "2001:db8:0:0:1::",
byteArrayOf(
32, 1, 13, -72,
0, 0, 0, 0,
0, 0, 0, 0,
0, 2, 0, 0
) to "2001:db8::2:0",
byteArrayOf(
0, 0, 0, 0,
0, 0, 0, 0,
0, 0, 0, 0,
0, 0, 0, 1
) to "::1",
byteArrayOf(
0, 0, 0, 0,
0, 0, 0, 1,
0, 0, 0, 0,
0, 0, 0, 1
) to "::1:0:0:0:1",
byteArrayOf(
0, 0, 0, 0,
1, 0, 0, 1,
0, 0, 0, 0,
1, 0, 0, 0
) to "::100:1:0:0:100:0",
byteArrayOf(
32, 1, 0, 0,
65, 54, -29, 120,
-128, 0, 99, -65,
63, -1, -3, -46
) to "2001:0:4136:e378:8000:63bf:3fff:fdd2",
byteArrayOf(
-86, -86, -69, -69,
-52, -52, -35, -35,
-18, -18, -1, -1,
17, 17, 34, 34
) to "aaaa:bbbb:cccc:dddd:eeee:ffff:1111:2222",
byteArrayOf(
0, 0, 0, 0,
0, 0, 0, 0,
0, 0, 0, 0,
0, 0, 0, 0
) to "::"
)
private val ipv4MappedToIPv6AddressStrings = mapOf(
// IPv4 addresses
"255.255.255.255" to "::ffff:255.255.255.255",
"0.0.0.0" to "::ffff:0.0.0.0",
"127.0.0.1" to "::ffff:127.0.0.1",
"1.2.3.4" to "::ffff:1.2.3.4",
"192.168.0.1" to "::ffff:192.168.0.1",
// IPv4 compatible addresses are deprecated [1], so we don't support outputting them, but we do support
// parsing them into IPv4 mapped addresses. These values are treated the same as a plain IPv4 address above.
// [1] https://tools.ietf.org/html/rfc4291#section-2.5.5.1
"0:0:0:0:0:0:255.254.253.252" to "::ffff:255.254.253.252",
"0:0:0:0:0::1.2.3.4" to "::ffff:1.2.3.4",
"0:0:0:0::1.2.3.4" to "::ffff:1.2.3.4",
"::0:0:0:0:0:1.2.3.4" to "::ffff:1.2.3.4",
"0::0:0:0:0:1.2.3.4" to "::ffff:1.2.3.4",
"0:0::0:0:0:1.2.3.4" to "::ffff:1.2.3.4",
"0:0:0::0:0:1.2.3.4" to "::ffff:1.2.3.4",
"0:0:0:0::0:1.2.3.4" to "::ffff:1.2.3.4",
"0:0:0:0:0::1.2.3.4" to "::ffff:1.2.3.4",
"::0:0:0:0:1.2.3.4" to "::ffff:1.2.3.4",
"0::0:0:0:1.2.3.4" to "::ffff:1.2.3.4",
"0:0::0:0:1.2.3.4" to "::ffff:1.2.3.4",
"0:0:0::0:1.2.3.4" to "::ffff:1.2.3.4",
"0:0:0:0::1.2.3.4" to "::ffff:1.2.3.4",
"::0:0:0:0:1.2.3.4" to "::ffff:1.2.3.4",
"0::0:0:0:1.2.3.4" to "::ffff:1.2.3.4",
"0:0::0:0:1.2.3.4" to "::ffff:1.2.3.4",
"0:0:0::0:1.2.3.4" to "::ffff:1.2.3.4",
"0:0:0:0::1.2.3.4" to "::ffff:1.2.3.4",
"::0:0:0:1.2.3.4" to "::ffff:1.2.3.4",
"0::0:0:1.2.3.4" to "::ffff:1.2.3.4",
"0:0::0:1.2.3.4" to "::ffff:1.2.3.4",
"0:0:0::1.2.3.4" to "::ffff:1.2.3.4",
"::0:0:1.2.3.4" to "::ffff:1.2.3.4",
"0::0:1.2.3.4" to "::ffff:1.2.3.4",
"0:0::1.2.3.4" to "::ffff:1.2.3.4",
"::0:1.2.3.4" to "::ffff:1.2.3.4",
"::1.2.3.4" to "::ffff:1.2.3.4",
// IPv4 mapped (fully specified)
"0:0:0:0:0:ffff:1.2.3.4" to "::ffff:1.2.3.4",
// IPv6 addresses
// Fully specified
"2001:0:4136:e378:8000:63bf:3fff:fdd2" to "2001:0:4136:e378:8000:63bf:3fff:fdd2",
"aaaa:bbbb:cccc:dddd:eeee:ffff:1111:2222" to "aaaa:bbbb:cccc:dddd:eeee:ffff:1111:2222",
"0:0:0:0:0:0:0:0" to "::",
"0:0:0:0:0:0:0:1" to "::1",
// Compressing at the beginning
"::1:0:0:0:1" to "::1:0:0:0:1",
"::1:ffff:ffff" to "::1:ffff:ffff",
"::" to "::",
"::1" to "::1",
"::ffff" to "::ffff",
"::ffff:0" to "::ffff:0",
"::ffff:ffff" to "::ffff:ffff",
"::0987:9876:8765" to "::987:9876:8765",
"::0987:9876:8765:7654" to "::987:9876:8765:7654",
"::0987:9876:8765:7654:6543" to "::987:9876:8765:7654:6543",
"::0987:9876:8765:7654:6543:5432" to "::987:9876:8765:7654:6543:5432",
// Note the compression is removed (rfc 5952 section 4.2.2)
"::0987:9876:8765:7654:6543:5432:3210" to "0:987:9876:8765:7654:6543:5432:3210",
// Compressing at the end
// Note the compression is removed (rfc 5952 section 4.2.2)
"2001:db8:abcd:bcde:cdef:def1:ef12::" to "2001:db8:abcd:bcde:cdef:def1:ef12:0",
"2001:db8:abcd:bcde:cdef:def1::" to "2001:db8:abcd:bcde:cdef:def1::",
"2001:db8:abcd:bcde:cdef::" to "2001:db8:abcd:bcde:cdef::",
"2001:db8:abcd:bcde::" to "2001:db8:abcd:bcde::",
"2001:db8:abcd::" to "2001:db8:abcd::",
"2001:1234::" to "2001:1234::",
"2001::" to "2001::",
"0::" to "::",
// Compressing in the middle
"1234:2345::7890" to "1234:2345::7890",
"1234::2345:7890" to "1234::2345:7890",
"1234:2345:3456::7890" to "1234:2345:3456::7890",
"1234:2345::3456:7890" to "1234:2345::3456:7890",
"1234::2345:3456:7890" to "1234::2345:3456:7890",
"1234:2345:3456:4567::7890" to "1234:2345:3456:4567::7890",
"1234:2345:3456::4567:7890" to "1234:2345:3456::4567:7890",
"1234:2345::3456:4567:7890" to "1234:2345::3456:4567:7890",
"1234::2345:3456:4567:7890" to "1234::2345:3456:4567:7890",
"1234:2345:3456:4567:5678::7890" to "1234:2345:3456:4567:5678::7890",
"1234:2345:3456:4567::5678:7890" to "1234:2345:3456:4567::5678:7890",
"1234:2345:3456::4567:5678:7890" to "1234:2345:3456::4567:5678:7890",
"1234:2345::3456:4567:5678:7890" to "1234:2345::3456:4567:5678:7890",
"1234::2345:3456:4567:5678:7890" to "1234::2345:3456:4567:5678:7890",
// Note the compression is removed (rfc 5952 section 4.2.2)
"1234:2345:3456:4567:5678:6789::7890" to "1234:2345:3456:4567:5678:6789:0:7890",
// Note the compression is removed (rfc 5952 section 4.2.2)
"1234:2345:3456:4567:5678::6789:7890" to "1234:2345:3456:4567:5678:0:6789:7890",
// Note the compression is removed (rfc 5952 section 4.2.2)
"1234:2345:3456:4567::5678:6789:7890" to "1234:2345:3456:4567:0:5678:6789:7890",
// Note the compression is removed (rfc 5952 section 4.2.2)
"1234:2345:3456::4567:5678:6789:7890" to "1234:2345:3456:0:4567:5678:6789:7890",
// Note the compression is removed (rfc 5952 section 4.2.2)
"1234:2345::3456:4567:5678:6789:7890" to "1234:2345:0:3456:4567:5678:6789:7890",
// Note the compression is removed (rfc 5952 section 4.2.2)
"1234::2345:3456:4567:5678:6789:7890" to "1234:0:2345:3456:4567:5678:6789:7890",
// IPv4 mapped addresses
"::ffff:255.255.255.255" to "::ffff:255.255.255.255",
"::ffff:0.0.0.0" to "::ffff:0.0.0.0",
"::ffff:127.0.0.1" to "::ffff:127.0.0.1",
"::ffff:1.2.3.4" to "::ffff:1.2.3.4",
"::ffff:192.168.0.1" to "::ffff:192.168.0.1")
private fun assertHexDumpEquals(expected: String?, actual: ByteArray?, message: String) {
assertEquals(message, expected, actual?.toHex())
}
private val hexChars = "0123456789abcdef".toCharArray()
private fun ByteArray.toHex(): String {
val hex = CharArray(2 * this.size)
this.forEachIndexed { i, byte ->
val unsigned = 0xff and byte.toInt()
hex[2 * i] = hexChars[unsigned / 16]
hex[2 * i + 1] = hexChars[unsigned % 16]
}
return hex.joinToString("")
}
private fun String.decodeHex(): ByteArray {
check(length % 2 == 0) { "Must have an even length" }
val bytes = ByteArray(length / 2)
var i = 0
while (i < length) {
// using left shift operator on every character
val a = Character.digit(this[i], 16) shl 4
val b = Character.digit(this[i+1], 16)
bytes[i / 2] = (a + b).toByte()
i += 2
}
return bytes
}
}
@Test
fun testAddressLength() {
assertEquals(4, IPv4.length)
assertEquals(16, IPv6.length)
}
@Test
fun testFamilyOf() {
assertTrue(IPv4.isFamily(InetAddress.getByName("192.168.0.1")))
assertTrue(IPv6.isFamily(InetAddress.getByName("1:2:3:4:5:6:7:8")))
}
@Test
fun testLocalhost() {
assertNotNull(IP.LOCALHOST)
}
@Test
fun testLoopback() {
assertNotNull(IP.LOOPBACK_IF)
}
@Test
fun testIsValidIpV4Address() {
for (host in validIpV4Hosts.keys) {
assertTrue(host, IPv4.isValid(host))
}
for (host in invalidIpV4Hosts.keys) {
assertFalse(host, IPv4.isValid(host))
}
}
@Test
fun testIsValidIpV6Address() {
for (host in validIpV6Hosts.keys) {
assertTrue(host, IPv6.isValid(host))
if (host[0] != '[' && !host.contains("%")) {
assertNotNull(host, IPv6.toAddress(host, true))
var hostMod = "[$host]"
assertTrue(hostMod, IPv6.isValid(hostMod))
hostMod = "$host%"
assertTrue(hostMod, IPv6.isValid(hostMod))
hostMod = "$host%eth1"
assertTrue(hostMod, IPv6.isValid(hostMod))
hostMod = "[$host%]"
assertTrue(hostMod, IPv6.isValid(hostMod))
hostMod = "[$host%1]"
assertTrue(hostMod, IPv6.isValid(hostMod))
hostMod = "[$host]%"
assertFalse(hostMod, IPv6.isValid(hostMod))
hostMod = "[$host]%1"
assertFalse(hostMod, IPv6.isValid(hostMod))
}
}
for (host in invalidIpV6Hosts.keys) {
assertFalse(host, IPv6.isValid(host))
assertNull(host, IPv6.toAddress(host))
var hostMod = "[$host]"
assertFalse(hostMod, IPv6.isValid(hostMod))
hostMod = "$host%"
assertFalse(hostMod, IPv6.isValid(hostMod))
hostMod = "$host%eth1"
assertFalse(hostMod, IPv6.isValid(hostMod))
hostMod = "[$host%]"
assertFalse(hostMod, IPv6.isValid(hostMod))
hostMod = "[$host%1]"
assertFalse(hostMod, IPv6.isValid(hostMod))
hostMod = "[$host]%"
assertFalse(hostMod, IPv6.isValid(hostMod))
hostMod = "[$host]%1"
assertFalse(hostMod, IPv6.isValid(hostMod))
hostMod = "$host]"
assertFalse(hostMod, IPv6.isValid(hostMod))
hostMod = "[$host"
assertFalse(hostMod, IPv6.isValid(hostMod))
}
}
@Test
fun testCreateByteArrayFromIpAddressString() {
for ((ip, value) in validIpV4Hosts) {
assertHexDumpEquals(value, IPv4.toBytes(ip), ip)
}
for ((ip, value) in invalidIpV4Hosts) {
assertHexDumpEquals(value, IPv4.toBytesOrNull(ip), ip)
}
for ((ip, value) in validIpV6Hosts) {
assertHexDumpEquals(value, IPv6.toBytes(ip), ip)
}
for ((ip, value) in invalidIpV6Hosts) {
assertHexDumpEquals(value, IPv6.toBytesOrNull(ip), ip)
}
}
@Test
@Throws(UnknownHostException::class)
fun testBytesToIpAddress() {
for ((key) in validIpV4Hosts) {
assertEquals(key, IPv4.toString(IPv4.toBytes(key)))
assertEquals(key, IPv4.toString(IPv4.toBytes(key)))
}
for ((key, value) in ipv6ToAddressStrings) {
assertEquals(value, IPv6.toString(key))
}
}
@Test
@Throws(UnknownHostException::class)
fun testIp6AddressToString() {
for ((key, value) in ipv6ToAddressStrings) {
assertEquals(value, IP.toString(InetAddress.getByAddress(key)))
}
}
@Test
@Throws(UnknownHostException::class)
fun testIp4AddressToString() {
for ((key, value) in validIpV4Hosts) {
assertEquals(key, IP.toString(InetAddress.getByAddress(value.decodeHex())))
}
}
@Test
fun testIpv4MappedIp6GetByName() {
for ((srcIp, dstIp) in ipv4MappedToIPv6AddressStrings) {
val inet6Address: Inet6Address? = IPv6.toAddress(srcIp, true)
assertNotNull("$srcIp, $dstIp", inet6Address)
assertEquals(srcIp, dstIp, IPv6.toString(inet6Address!!, true))
}
}
@Test
fun testInvalidIpv4MappedIp6GetByName() {
for (host in invalidIpV4Hosts.keys) {
assertNull(host, IPv4.toAddress(host))
}
for (host in invalidIpV6Hosts.keys) {
assertNull(host, IPv6.toAddress(host, true))
}
}
@Test
@Throws(UnknownHostException::class)
fun testIp6InetSocketAddressToString() {
for ((key, value) in ipv6ToAddressStrings) {
assertEquals("[$value]:9999", IP.toString(InetSocketAddress(InetAddress.getByAddress(key), 9999)))
}
}
@Test
@Throws(UnknownHostException::class)
fun testIp4SocketAddressToString() {
for ((key, value) in validIpV4Hosts) {
assertEquals("$key:9999", IP.toString(InetSocketAddress(InetAddress.getByAddress(value.decodeHex()), 9999)))
}
}
@Test
fun testPing() {
println(Ping.host("1.1.1.1").run())
}
@Test
fun testIntStringCycle() {
for (host in validIpV4Hosts.keys) {
println(host)
val ip = IPv4.toIntUnsafe(host)
val ipString = IPv4.toString(ip)
assertEquals(host, ipString)
}
}
@Test
fun testMac() {
assertEquals("12:12:12:12:12:12", Mac.toStringLowerCase(Mac.toLong("12:12:12:12:12:12")))
}
@Test
fun testIsPrivate() {
assertTrue(IPv4.isSiteLocal("192.168.23.102"))
assertTrue(IPv4.isSiteLocal("10.10.234.102"))
assertTrue(IPv4.isSiteLocal("172.16.45.13"))
assertFalse(IPv4.isSiteLocal("72.66.83.240"))
}
@Test
fun testIp4Range() {
assertTrue(IPv4.isInRange("10.10.10.5", "10.10.10.10", 24))
assertTrue(IPv4.isInRange("10.0.0.5", "10.10.10.10", 8))
assertFalse(IPv4.isInRange("11.0.0.5", "10.10.10.10", 8))
assertTrue(IPv4.isInRange("11.0.0.5", "10.10.10.10", 1))
assertTrue(IPv4.isInRange("11.0.0.5", "10.10.10.10", 0))
assertFalse(IPv4.isInRange("11.0.0.5", "10.10.10.10", 32))
assertTrue(IPv4.isInRange("10.10.10.10", "10.10.10.10", 32))
assertTrue(IPv4.isInRange("10.10.10.10", "10.10.10.10", 31))
assertTrue(IPv4.isInRange("10.10.10.10", "10.10.10.10", 30))
assertTrue(IPv4.isInRange("192.168.42.14", "192.168.0.0", 16))
assertTrue(IPv4.isInRange("192.168.0.0", "192.168.0.0", 16))
}
@Test
fun testCidr() {
assertTrue(IPv4.isValidCidr("10.10.10.5/0"))
assertTrue(IPv4.isValidCidr("10.10.10.5/24"))
assertTrue(IPv4.isValidCidr("10.10.10.5/32"))
assertFalse(IPv4.isValidCidr("10.10.10.5/33"))
assertFalse(IPv4.isValidCidr("10.10.10.5/-1"))
}
@Test
fun testToString() {
assertEquals("10.10.10.5", IPv4.toString(IPv4.toInt("10.10.10.5")))
}
}