Generalize ip neigh parser

Now we can rely on fewer assumptions.
This commit is contained in:
Mygod
2018-12-14 02:20:55 +08:00
parent 51a19a3c55
commit 373d45f668
2 changed files with 22 additions and 24 deletions

View File

@@ -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) {

View File

@@ -69,8 +69,7 @@ class Subrouting(private val parent: Routing, priority: Int, val upstream: Strin
*/
override fun close() = IpNeighbourMonitor.unregisterCallback(this)
override fun onIpNeighbourAvailable(neighbours: List<IpNeighbour>) {
synchronized(parent) {
override fun onIpNeighbourAvailable(neighbours: List<IpNeighbour>) = synchronized(parent) {
val toRemove = HashSet(subroutes.keys)
for (neighbour in neighbours) {
if (neighbour.dev != parent.downstream || neighbour.ip !is Inet4Address ||
@@ -88,7 +87,6 @@ class Subrouting(private val parent: Routing, priority: Int, val upstream: Strin
for (address in toRemove) subroutes.remove(address)!!.close()
}
}
}
fun revert() {
subroutes.forEach { (_, subroute) -> subroute.close() }