IP-Scan: echte CIDR-Auswertung statt hardcodiertem /24 [apk]
All checks were successful
Build APK / build-apk (push) Successful in 4m11s
All checks were successful
Build APK / build-apk (push) Successful in 4m11s
Der Scan lief stur ueber (1..254) einer aus dem Subnetz-String abgeschnittenen base — die Netzmaske wurde komplett ignoriert. Ein /23, /22 oder /16 wurde also nur zu einem Viertel/Achtel etc. gescannt. Jetzt: hostsInSubnet() parst die CIDR (ip/praefix), berechnet Netz- und Broadcast-Adresse und liefert ALLE Host-IPs des Bereichs. Unterstuetzt /0..32 (praktisch bis /16 = 65534 Hosts), /31+/32 ohne Netz/Broadcast-Sonderfall. Sammel-Build: enthaelt ausserdem Titelleisten-Fix, App-Icon, Debug-Log, IP-Scan-Logging. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
parent
c81871f010
commit
46226f0d78
1 changed files with 53 additions and 4 deletions
|
|
@ -82,14 +82,18 @@ class NetDiagScannerPlugin : Plugin() {
|
||||||
@PluginMethod
|
@PluginMethod
|
||||||
fun ipScan(call: PluginCall) {
|
fun ipScan(call: PluginCall) {
|
||||||
val subnet = call.getString("subnet") ?: return call.reject("subnet fehlt")
|
val subnet = call.getString("subnet") ?: return call.reject("subnet fehlt")
|
||||||
val base = subnet.substringBeforeLast('.', "192.168.1")
|
val hosts = hostsInSubnet(subnet)
|
||||||
|
if (hosts.isEmpty()) {
|
||||||
|
return call.reject("Subnetz ungültig oder zu groß (max /16): $subnet")
|
||||||
|
}
|
||||||
io.launch {
|
io.launch {
|
||||||
try {
|
try {
|
||||||
// Parallel-Ping über das gesamte /24
|
// Parallel-Ping über ALLE Host-Adressen des Subnetzes — CIDR-genau,
|
||||||
|
// also exakt der Bereich, den die Netzmaske aufspannt (/24, /23, /22 …).
|
||||||
val alive = withContext(Dispatchers.IO) {
|
val alive = withContext(Dispatchers.IO) {
|
||||||
(1..254).map { host ->
|
hosts.map { ipInt ->
|
||||||
async {
|
async {
|
||||||
val ip = "$base.$host"
|
val ip = intToIpv4(ipInt)
|
||||||
if (InetAddress.getByName(ip).isReachable(350)) ip else null
|
if (InetAddress.getByName(ip).isReachable(350)) ip else null
|
||||||
}
|
}
|
||||||
}.awaitAll().filterNotNull()
|
}.awaitAll().filterNotNull()
|
||||||
|
|
@ -112,6 +116,51 @@ class NetDiagScannerPlugin : Plugin() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Alle Host-IPs (als Int) eines CIDR-Subnetzes.
|
||||||
|
* "192.168.1.0/24" -> .1 bis .254, "10.0.0.0/22" -> 1022 Hosts usw.
|
||||||
|
* Ohne Praefix wird /24 angenommen. Netz- und Broadcast-Adresse sind
|
||||||
|
* ausgenommen (ausser /31, /32). Leer bei ungueltig oder > /16.
|
||||||
|
*/
|
||||||
|
private fun hostsInSubnet(cidr: String): List<Int> {
|
||||||
|
val parts = cidr.trim().split('/')
|
||||||
|
val ipInt = ipv4ToInt(parts[0].trim()) ?: return emptyList()
|
||||||
|
val prefix = if (parts.size > 1) (parts[1].trim().toIntOrNull() ?: 24) else 24
|
||||||
|
if (prefix < 0 || prefix > 32) return emptyList()
|
||||||
|
val mask = if (prefix == 0) 0 else (-1 shl (32 - prefix))
|
||||||
|
val network = ipInt and mask
|
||||||
|
val broadcast = network or mask.inv()
|
||||||
|
val out = ArrayList<Int>()
|
||||||
|
if (prefix >= 31) {
|
||||||
|
var i = network
|
||||||
|
while (true) { out.add(i); if (i == broadcast) break; i++ }
|
||||||
|
return out
|
||||||
|
}
|
||||||
|
val count = (broadcast.toLong() and 0xFFFFFFFFL) - (network.toLong() and 0xFFFFFFFFL) - 1L
|
||||||
|
if (count < 1L || count > 65534L) return emptyList()
|
||||||
|
var i = network + 1
|
||||||
|
val last = broadcast - 1
|
||||||
|
while (true) { out.add(i); if (i == last) break; i++ }
|
||||||
|
return out
|
||||||
|
}
|
||||||
|
|
||||||
|
/** "192.168.1.50" -> 32-Bit-Int (big-endian), null bei ungueltig */
|
||||||
|
private fun ipv4ToInt(s: String): Int? {
|
||||||
|
val o = s.split('.')
|
||||||
|
if (o.size != 4) return null
|
||||||
|
var v = 0
|
||||||
|
for (part in o) {
|
||||||
|
val n = part.toIntOrNull() ?: return null
|
||||||
|
if (n < 0 || n > 255) return null
|
||||||
|
v = (v shl 8) or n
|
||||||
|
}
|
||||||
|
return v
|
||||||
|
}
|
||||||
|
|
||||||
|
/** 32-Bit-Int (big-endian) -> "192.168.1.50" */
|
||||||
|
private fun intToIpv4(i: Int): String =
|
||||||
|
"${(i shr 24) and 0xFF}.${(i shr 16) and 0xFF}.${(i shr 8) and 0xFF}.${i and 0xFF}"
|
||||||
|
|
||||||
/* --------------------------------------------------------------------- */
|
/* --------------------------------------------------------------------- */
|
||||||
/* Port-Scan */
|
/* Port-Scan */
|
||||||
/* --------------------------------------------------------------------- */
|
/* --------------------------------------------------------------------- */
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue