diff --git a/mobile/src/main/java/be/mygod/vpnhotspot/net/IpNeighbour.kt b/mobile/src/main/java/be/mygod/vpnhotspot/net/IpNeighbour.kt index a6b8894b..deec46d6 100644 --- a/mobile/src/main/java/be/mygod/vpnhotspot/net/IpNeighbour.kt +++ b/mobile/src/main/java/be/mygod/vpnhotspot/net/IpNeighbour.kt @@ -16,18 +16,18 @@ data class IpNeighbour(val ip: InetAddress, val dev: String, val lladdr: String, * Parser based on: * https://android.googlesource.com/platform/external/iproute2/+/ad0a6a2/ip/ipneigh.c#194 * https://people.cs.clemson.edu/~westall/853/notes/arpstate.pdf - * Assumptions: IP addr (key) always present, RTM_GETNEIGH is never used and show_stats = 0 + * Assumptions: IP addr (key) always present and RTM_GETNEIGH is never used */ - private val parser = ("^(Deleted )?([^ ]+?) (dev ([^ ]+?) )?(lladdr (.[^ ]+?))?( router)?( proxy)?" + - "( ([INCOMPLET,RAHBSDYF]+))?\$").toRegex() + private val parser = "^(Deleted )?([^ ]+) dev ([^ ]+) (lladdr (.[^ ]+))?.*?( ([INCOMPLET,RAHBSDYF]+))?\$" + .toRegex() private fun checkLladdrNotLoopback(lladdr: String) = if (lladdr == "00:00:00:00:00:00") "" else lladdr fun parse(line: String): IpNeighbour? { return try { val match = parser.matchEntire(line)!! val ip = parseNumericAddress(match.groupValues[2]) - val dev = match.groupValues[4] - var lladdr = checkLladdrNotLoopback(match.groupValues[6]) + val dev = match.groupValues[3] + var lladdr = checkLladdrNotLoopback(match.groupValues[5]) // use ARP as fallback if (dev.isNotEmpty() && lladdr.isEmpty()) lladdr = checkLladdrNotLoopback(arp() .asSequence() @@ -35,12 +35,12 @@ data class IpNeighbour(val ip: InetAddress, val dev: String, val lladdr: String, .map { it[ARP_HW_ADDRESS] } .singleOrNull() ?: "") val state = if (match.groupValues[1].isNotEmpty() || lladdr.isEmpty()) State.DELETING else - when (match.groupValues[10]) { + when (match.groupValues[7]) { "", "INCOMPLETE" -> State.INCOMPLETE "REACHABLE", "DELAY", "STALE", "PROBE", "PERMANENT" -> State.VALID "FAILED" -> State.FAILED "NOARP" -> return null // skip - else -> throw IllegalArgumentException("Unknown state encountered: ${match.groupValues[10]}") + else -> throw IllegalArgumentException("Unknown state encountered: ${match.groupValues[7]}") } IpNeighbour(ip, dev, lladdr, state) } catch (e: Exception) { diff --git a/mobile/src/main/java/be/mygod/vpnhotspot/net/Subrouting.kt b/mobile/src/main/java/be/mygod/vpnhotspot/net/Subrouting.kt index 9d8174eb..cbe1d374 100644 --- a/mobile/src/main/java/be/mygod/vpnhotspot/net/Subrouting.kt +++ b/mobile/src/main/java/be/mygod/vpnhotspot/net/Subrouting.kt @@ -69,25 +69,23 @@ class Subrouting(private val parent: Routing, priority: Int, val upstream: Strin */ override fun close() = IpNeighbourMonitor.unregisterCallback(this) - override fun onIpNeighbourAvailable(neighbours: List) { - synchronized(parent) { - val toRemove = HashSet(subroutes.keys) - for (neighbour in neighbours) { - if (neighbour.dev != parent.downstream || neighbour.ip !is Inet4Address || - AppDatabase.instance.clientRecordDao.lookup(neighbour.lladdr.macToLong()).blocked) continue - toRemove.remove(neighbour.ip) - try { - subroutes.computeIfAbsentCompat(neighbour.ip) { Subroute(neighbour.ip, neighbour.lladdr) } - } catch (e: Exception) { - Timber.w(e) - SmartSnackbar.make(e).show() - } - } - if (toRemove.isNotEmpty()) { - TrafficRecorder.update() // record stats before removing rules to prevent stats losing - for (address in toRemove) subroutes.remove(address)!!.close() + override fun onIpNeighbourAvailable(neighbours: List) = synchronized(parent) { + val toRemove = HashSet(subroutes.keys) + for (neighbour in neighbours) { + if (neighbour.dev != parent.downstream || neighbour.ip !is Inet4Address || + AppDatabase.instance.clientRecordDao.lookup(neighbour.lladdr.macToLong()).blocked) continue + toRemove.remove(neighbour.ip) + try { + subroutes.computeIfAbsentCompat(neighbour.ip) { Subroute(neighbour.ip, neighbour.lladdr) } + } catch (e: Exception) { + Timber.w(e) + SmartSnackbar.make(e).show() } } + if (toRemove.isNotEmpty()) { + TrafficRecorder.update() // record stats before removing rules to prevent stats losing + for (address in toRemove) subroutes.remove(address)!!.close() + } } fun revert() {