From c66444f45bc0bc0784d93cb68ba10c9b10fa9d7f Mon Sep 17 00:00:00 2001 From: Robinson Date: Mon, 26 Apr 2021 23:22:24 +0200 Subject: [PATCH] added IPv4/6 cidrPrefixToSubnetMask, added IPv6 toInt (really a bigInt) convenience methods --- src/dorkbox/netUtil/IPv4.kt | 101 +++++++++++++++--------------------- src/dorkbox/netUtil/IPv6.kt | 36 +++++++++++++ 2 files changed, 77 insertions(+), 60 deletions(-) diff --git a/src/dorkbox/netUtil/IPv4.kt b/src/dorkbox/netUtil/IPv4.kt index 0803010..76db0a5 100644 --- a/src/dorkbox/netUtil/IPv4.kt +++ b/src/dorkbox/netUtil/IPv4.kt @@ -544,50 +544,25 @@ object IPv4 { } /** - * @param cidr the CIDR notation, ie: 24, 16, etc. That we want to convert into a netmask, as a SIGNED INTEGER (the bits are still - * correct, but to see this "as unix would", you must convert to an unsigned integer. + * @param cidrPrefix the CIDR notation, ie: /24, /16, etc that we want to convert into a netmask * * @return the netmask (as a signed int), or if there were errors, the default /0 netmask */ - fun getCidrAsIntNetmask(cidr: Int): Int { - return when (cidr) { - 32 -> -1 - 31 -> -2 - 30 -> -4 - 29 -> -8 - 28 -> -16 - 27 -> -32 - 26 -> -64 - 25 -> -128 - 24 -> -256 - 23 -> -512 - 22 -> -1024 - 21 -> -2048 - 20 -> -4096 - 19 -> -8192 - 18 -> -16384 - 17 -> -32768 - 16 -> -65536 - 15 -> -131072 - 14 -> -262144 - 13 -> -524288 - 12 -> -1048576 - 11 -> -2097152 - 10 -> -4194304 - 9 -> -8388608 - 8 -> -16777216 - 7 -> -33554432 - 6 -> -67108864 - 5 -> -134217728 - 4 -> -268435456 - 3 -> -536870912 - 2 -> -1073741824 - 1 -> -2147483648 - else -> 0 - } + fun cidrPrefixToSubnetMask(cidrPrefix: Int): Int { + /** + * Perform the shift on a long and downcast it to int afterwards. + * This is necessary to handle a cidrPrefix of zero correctly. + * The left shift operator on an int only uses the five least + * significant bits of the right-hand operand. Thus -1 << 32 evaluates + * to -1 instead of 0. The left shift operator applied on a long + * uses the six least significant bits. + * + * Also see https://github.com/netty/netty/issues/2767 + */ + return (-1L shl 32 - cidrPrefix and -0x1).toInt() } - fun getCidrFromMask(mask: String): Int { + fun cidrPrefixFromSubnetMask(mask: String): Int { return when (mask) { "255.255.255.255" -> 32 "255.255.255.254" -> 31 @@ -739,7 +714,7 @@ object IPv4 { /** - * Converts a byte array into an 32-bit integer + * Converts a byte array into a 32-bit integer */ fun toInt(ipBytes: ByteArray): Int { return ipBytes[0].toInt() shl 24 or @@ -748,6 +723,32 @@ object IPv4 { (ipBytes[3].toInt()) } + /** + * Converts an IP address into a 32-bit integer + */ + fun toInt(ipAsString: String): Int { + return if (isValid(ipAsString)) { + toIntUnsafe(ipAsString) + } else { + 0 + } + } + + /** + * Converts an IP address into a 32-bit integer, no validity checks are performed + */ + fun toIntUnsafe(ipAsString: String): Int { + val bytes = toBytes(ipAsString) + + var address = 0 + for (element in bytes) { + address = address shl 8 + address = address or (element.toInt() and 0xff) + } + + return address + } + /** * Converts a 32-bit integer into a dotted-quad IPv4 address. */ @@ -856,26 +857,6 @@ object IPv4 { (bytes and 0xFF).toByte()) } - fun toInt(ipAsString: String): Int { - return if (isValid(ipAsString)) { - toIntUnsafe(ipAsString) - } else { - 0 - } - } - - fun toIntUnsafe(ipAsString: String): Int { - val bytes = toBytes(ipAsString) - - var address = 0 - for (element in bytes) { - address = address shl 8 - address = address or (element.toInt() and 0xff) - } - - return address - } - /** * Returns the [Inet4Address] representation of a [String] IP address. * diff --git a/src/dorkbox/netUtil/IPv6.kt b/src/dorkbox/netUtil/IPv6.kt index c302633..72cb5da 100644 --- a/src/dorkbox/netUtil/IPv6.kt +++ b/src/dorkbox/netUtil/IPv6.kt @@ -17,6 +17,7 @@ package dorkbox.netUtil +import java.math.BigInteger import java.net.* /** @@ -558,6 +559,32 @@ object IPv6 { return fromString(fixedIp)?.address ?: ByteArray(32) } + /** + * Converts a byte array into a 128-bit BigInteger + */ + fun toInt(ipBytes: ByteArray): BigInteger { + return BigInteger(ipBytes) + } + + /** + * Converts an IP address into a 128-bit BigInteger + */ + fun toInt(ipAsString: String): BigInteger { + return if (isValid(ipAsString)) { + toIntUnsafe(ipAsString) + } else { + BigInteger(ByteArray(0)) + } + } + + /** + * Converts an IP address into a 128-bit BigInteger, no validity checks are performed + */ + fun toIntUnsafe(ipAsString: String): BigInteger { + val bytes = toBytes(ipAsString) + return BigInteger(bytes) + } + /** * Creates an Inet6Address based on an ipAddressString. */ @@ -1083,4 +1110,13 @@ object IPv6 { throw IllegalArgumentException("invalid address") } } + + /** + * @param cidrPrefix the CIDR notation, ie: /24, /16, etc that we want to convert into a netmask + * + * @return the netmask, or if there were errors, the default /0 netmask + */ + fun cidrPrefixToSubnetMask(cidrPrefix: Int): BigInteger { + return MINUS_ONE.shiftLeft(128 - cidrPrefix) + } }