Support permanent entries without ip associated

This commit is contained in:
Mygod
2022-02-21 20:59:16 -05:00
parent 61efc79e9a
commit 977614f566

View File

@@ -27,8 +27,8 @@ data class IpNeighbour(val ip: InetAddress, val dev: String, val lladdr: MacAddr
* https://people.cs.clemson.edu/~westall/853/notes/arpstate.pdf * https://people.cs.clemson.edu/~westall/853/notes/arpstate.pdf
* Assumptions: IP addr (key) always present and RTM_GETNEIGH is never used * Assumptions: IP addr (key) always present and RTM_GETNEIGH is never used
*/ */
private val parser = "^(Deleted )?([^ ]+) dev ([^ ]+) (lladdr ([^ ]*))?.*?( ([INCOMPLET,RAHBSDYF]+))?\$" private val parser = ("^(Deleted )?(?:([^ ]+) )?dev ([^ ]+) (?:lladdr ([^ ]*))?.*?" +
.toRegex() "(?: ([INCOMPLET,RAHBSDYF]+))?\$").toRegex()
/** /**
* Fallback format will be used if if_indextoname returns null, which some stupid devices do. * Fallback format will be used if if_indextoname returns null, which some stupid devices do.
* *
@@ -49,14 +49,15 @@ data class IpNeighbour(val ip: InetAddress, val dev: String, val lladdr: MacAddr
suspend fun parse(line: String, fullMode: Boolean): List<IpNeighbour> { suspend fun parse(line: String, fullMode: Boolean): List<IpNeighbour> {
return if (line.isBlank()) emptyList() else try { return if (line.isBlank()) emptyList() else try {
val match = parser.matchEntire(line)!! val match = parser.matchEntire(line)!!
val ip = parseNumericAddress(match.groupValues[2]) // by regex, ip is non-empty if (match.groups[2] == null) return emptyList()
val devs = substituteDev(match.groupValues[3]) // by regex, dev is non-empty as well val ip = parseNumericAddress(match.groupValues[2])
val state = if (match.groupValues[1].isNotEmpty()) State.DELETING else when (match.groupValues[7]) { val devs = substituteDev(match.groupValues[3]) // by regex, dev is non-empty
val state = if (match.groupValues[1].isNotEmpty()) State.DELETING else when (match.groupValues[5]) {
"", "INCOMPLETE" -> State.INCOMPLETE "", "INCOMPLETE" -> State.INCOMPLETE
"REACHABLE", "DELAY", "STALE", "PROBE", "PERMANENT" -> State.VALID "REACHABLE", "DELAY", "STALE", "PROBE", "PERMANENT" -> State.VALID
"FAILED" -> State.FAILED "FAILED" -> State.FAILED
"NOARP" -> return emptyList() // skip "NOARP" -> return emptyList() // skip
else -> throw IllegalArgumentException("Unknown state encountered: ${match.groupValues[7]}") else -> throw IllegalArgumentException("Unknown state encountered: ${match.groupValues[5]}")
} }
var lladdr = MacAddressCompat.ALL_ZEROS_ADDRESS var lladdr = MacAddressCompat.ALL_ZEROS_ADDRESS
if (!fullMode && state != State.VALID) { if (!fullMode && state != State.VALID) {
@@ -64,7 +65,7 @@ data class IpNeighbour(val ip: InetAddress, val dev: String, val lladdr: MacAddr
return devs.map { IpNeighbour(ip, it, lladdr, State.DELETING) } return devs.map { IpNeighbour(ip, it, lladdr, State.DELETING) }
} }
if (match.groups[4] != null) try { if (match.groups[4] != null) try {
lladdr = MacAddressCompat.fromString(match.groupValues[5]) lladdr = MacAddressCompat.fromString(match.groupValues[4])
} catch (e: IllegalArgumentException) { } catch (e: IllegalArgumentException) {
if (state != State.INCOMPLETE && state != State.DELETING) { if (state != State.INCOMPLETE && state != State.DELETING) {
Timber.w(IOException("Failed to find MAC address for $line", e)) Timber.w(IOException("Failed to find MAC address for $line", e))