diff --git a/listener.py b/listener.py index 196fd8f..34a7512 100755 --- a/listener.py +++ b/listener.py @@ -17,6 +17,7 @@ aps = set() ap_signals = defaultdict(list) # BSSID -> list of dBm ssid_map = {} # BSSID -> SSID ssid_signals = defaultdict(list) # SSID -> list of dBm +ap_clients = defaultdict(set) # === Signal handling === def stop_sniff(signum, frame): @@ -65,17 +66,27 @@ def handle_packet(pkt): dot11 = pkt[Dot11] - if dot11.type == 0 and dot11.subtype in (5, 8): # Probe Resp or Beacon - aps.add(dot11.addr2) - ssid = parse_ssid(pkt) - if ssid: - ssid_map[dot11.addr2] = ssid - else: - if dot11.addr1: - clients.add(dot11.addr1) + # === Detect APs via beacons/probe responses === + if dot11.type == 0 and dot11.subtype in (5, 8): # Probe Response or Beacon if dot11.addr2: - clients.add(dot11.addr2) + aps.add(dot11.addr2) + ssid = parse_ssid(pkt) + if ssid: + ssid_map[dot11.addr2] = ssid + # === Track all seen clients === + if dot11.addr1: + clients.add(dot11.addr1) + if dot11.addr2: + clients.add(dot11.addr2) + + # === Guess client <-> AP relationships === + if dot11.addr1 in aps and dot11.addr2: + ap_clients[dot11.addr1].add(dot11.addr2) + elif dot11.addr2 in aps and dot11.addr1: + ap_clients[dot11.addr2].add(dot11.addr1) + + # === Signal strength tracking === try: signal_dbm = pkt[RadioTap].dBm_AntSignal if dot11.addr2 in aps: @@ -98,7 +109,7 @@ def write_csv(outfile): "StrongestAPSignal": max([max(v) for v in ap_signals.values() if v], default=0), "AvgSSIDSignal": round(sum([sum(v)/len(v) for v in ssid_signals.values() if v]) / len(ssid_signals) if ssid_signals else 0, 2), "MaxSSIDSignal": max([max(v) for v in ssid_signals.values() if v], default=0), - "ClientsOnAP": "N/A", + "ClientsOnAP": sum(len(s) for s in ap_clients.values()), "CiscoAvgReportedClients": "N/A", "CiscoMaxReportedClients": "N/A", "NumberofBSSIDsOnSSID": "N/A",