Prevent labeled devices from being silently seeded; detect opcode=2 ARP for labeled MACs
seed_from_arp_cache was adding labeled personal devices to known_devices at startup, causing all subsequent arrivals to be ignored (already_known=True). Now skips them so on_arrival fires normally when they rejoin. ARP opcode=2 (replies) are now treated as genuine signals for explicitly labeled devices. iPhones with privacy MACs frequently emit only opcode=2 after initial association — the AP proxy forgery concern doesn't apply to devices the operator has explicitly named.
This commit is contained in:
@@ -827,6 +827,17 @@ def seed_from_arp_cache():
|
|||||||
if mac == "00:00:00:00:00:00" or flags == "0x0":
|
if mac == "00:00:00:00:00:00" or flags == "0x0":
|
||||||
continue
|
continue
|
||||||
|
|
||||||
|
# Labeled personal devices must NOT be silently seeded — they need
|
||||||
|
# a real on_arrival call so ARRIVED fires when they rejoin.
|
||||||
|
# Just update last_seen as a baseline so the watchdog has a reference.
|
||||||
|
with personal_lock:
|
||||||
|
is_personal = mac in device_labels or mac in personal_devices
|
||||||
|
if is_personal:
|
||||||
|
with last_seen_lock:
|
||||||
|
if mac not in last_seen:
|
||||||
|
last_seen[mac] = time.time()
|
||||||
|
continue
|
||||||
|
|
||||||
vendor = lookup_oui(mac)
|
vendor = lookup_oui(mac)
|
||||||
with known_lock:
|
with known_lock:
|
||||||
if mac not in known_devices:
|
if mac not in known_devices:
|
||||||
@@ -1579,10 +1590,14 @@ def parse_frame(data: bytes) -> None:
|
|||||||
|
|
||||||
# Branch A: ARP frame (ethertype 0x0806)
|
# Branch A: ARP frame (ethertype 0x0806)
|
||||||
if eth_type == 0x0806:
|
if eth_type == 0x0806:
|
||||||
# Only ARP requests (opcode 1) are genuine device-originated signals.
|
opcode = struct.unpack('!H', data[20:22])[0] if len(data) >= 22 else 0
|
||||||
# ARP replies (opcode 2) may be AP ARP proxy forgeries: the AP answers
|
# Opcode 1 (request) is a genuine device signal.
|
||||||
# on behalf of disconnected clients with the client MAC as Ethernet source.
|
# Opcode 2 (reply) may be an AP ARP proxy forgery — EXCEPT for explicitly
|
||||||
if len(data) >= 22 and struct.unpack('!H', data[20:22])[0] == 1:
|
# labeled personal devices where we trust the frame regardless, because
|
||||||
|
# iPhones with privacy MACs often only emit opcode=2 after initial association.
|
||||||
|
with personal_lock:
|
||||||
|
is_labeled = src_mac in device_labels
|
||||||
|
if opcode == 1 or (opcode == 2 and is_labeled):
|
||||||
_update_last_seen(src_mac)
|
_update_last_seen(src_mac)
|
||||||
# Personal devices first seen via ARP get no DHCP/Netlink event.
|
# Personal devices first seen via ARP get no DHCP/Netlink event.
|
||||||
# Fire on_arrival so they get ARRIVED alert and occupancy counts.
|
# Fire on_arrival so they get ARRIVED alert and occupancy counts.
|
||||||
|
|||||||
Reference in New Issue
Block a user