Fix IP and CIDR validation (#6124)
This commit is contained in:
1 parent
63f557242b
commit
dac65a972c
1 file changed
+15
-39
@@ -16,7 +16,6 @@ import com.v2ray.ang.AppConfig
|
|||||||
import com.v2ray.ang.AppConfig.LOOPBACK
|
import com.v2ray.ang.AppConfig.LOOPBACK
|
||||||
import com.v2ray.ang.BuildConfig
|
import com.v2ray.ang.BuildConfig
|
||||||
import java.io.IOException
|
import java.io.IOException
|
||||||
import java.net.InetAddress
|
|
||||||
import java.net.ServerSocket
|
import java.net.ServerSocket
|
||||||
import java.net.URI
|
import java.net.URI
|
||||||
import java.net.URLDecoder
|
import java.net.URLDecoder
|
||||||
@@ -213,8 +212,10 @@ object Utils {
|
|||||||
*/
|
*/
|
||||||
private fun isIpv6Address(value: String): Boolean {
|
private fun isIpv6Address(value: String): Boolean {
|
||||||
var addr = value
|
var addr = value
|
||||||
if (addr.startsWith("[") && addr.endsWith("]")) {
|
if (addr.startsWith("[")) {
|
||||||
addr = addr.drop(1).dropLast(1)
|
val closingBracket = addr.lastIndexOf(']')
|
||||||
|
if (closingBracket <= 1) return false
|
||||||
|
addr = addr.substring(1, closingBracket)
|
||||||
}
|
}
|
||||||
return IPV6_REGEX.matches(addr)
|
return IPV6_REGEX.matches(addr)
|
||||||
}
|
}
|
||||||
@@ -460,48 +461,23 @@ object Utils {
|
|||||||
fun isXray(): Boolean = BuildConfig.APPLICATION_ID.startsWith("com.v2ray.ang")
|
fun isXray(): Boolean = BuildConfig.APPLICATION_ID.startsWith("com.v2ray.ang")
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Converts an InetAddress to its long representation
|
* Check if an IPv4 address is within an IPv4 CIDR range
|
||||||
*
|
*
|
||||||
* @param ip The InetAddress to convert
|
* @param ip The IPv4 address to check
|
||||||
* @return The long representation of the IP address
|
* @param cidr The IPv4 CIDR range (e.g., "192.168.1.0/24")
|
||||||
*/
|
|
||||||
private fun inetAddressToLong(ip: InetAddress): Long {
|
|
||||||
val bytes = ip.address
|
|
||||||
var result: Long = 0
|
|
||||||
for (i in bytes.indices) {
|
|
||||||
result = result shl 8 or (bytes[i].toInt() and 0xff).toLong()
|
|
||||||
}
|
|
||||||
return result
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Check if an IP address is within a CIDR range
|
|
||||||
*
|
|
||||||
* @param ip The IP address to check
|
|
||||||
* @param cidr The CIDR notation range (e.g., "192.168.1.0/24")
|
|
||||||
* @return True if the IP is within the CIDR range, false otherwise
|
* @return True if the IP is within the CIDR range, false otherwise
|
||||||
*/
|
*/
|
||||||
fun isIpInCidr(ip: String, cidr: String): Boolean {
|
fun isIpInCidr(ip: String, cidr: String): Boolean {
|
||||||
try {
|
val parts = cidr.split('/')
|
||||||
if (!isIpAddress(ip)) return false
|
if (parts.size != 2 || !isIpv4Address(ip) || !isIpv4Address(parts[0])) return false
|
||||||
|
|
||||||
// Parse CIDR (e.g., "192.168.1.0/24")
|
val prefixLength = parts[1].toIntOrNull()?.takeIf { it in 0..32 } ?: return false
|
||||||
val (cidrIp, prefixLen) = cidr.split("/")
|
val mask = if (prefixLength == 0) 0L else (-1L shl (32 - prefixLength))
|
||||||
val prefixLength = prefixLen.toInt()
|
return (ipv4ToLong(ip) and mask) == (ipv4ToLong(parts[0]) and mask)
|
||||||
|
}
|
||||||
|
|
||||||
// Convert IP and CIDR's IP portion to Long
|
private fun ipv4ToLong(ip: String): Long {
|
||||||
val ipLong = inetAddressToLong(InetAddress.getByName(ip))
|
return ip.split('.').fold(0L) { result, octet -> (result shl 8) or octet.toLong() }
|
||||||
val cidrIpLong = inetAddressToLong(InetAddress.getByName(cidrIp))
|
|
||||||
|
|
||||||
// Calculate subnet mask (e.g., /24 → 0xFFFFFF00)
|
|
||||||
val mask = if (prefixLength == 0) 0L else (-1L shl (32 - prefixLength))
|
|
||||||
|
|
||||||
// Check if they're in the same subnet
|
|
||||||
return (ipLong and mask) == (cidrIpLong and mask)
|
|
||||||
} catch (e: Exception) {
|
|
||||||
LogUtil.e(AppConfig.TAG, "Failed to check if IP is in CIDR", e)
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
Reference in new issue
Block a user