From ccbe5b92a12c782d8f7da865e83003f9670dbc22 Mon Sep 17 00:00:00 2001 From: Yaro Kasear Date: Wed, 16 Apr 2025 11:00:46 -0500 Subject: [PATCH] Add Cisco client count parsing and update return values in analyze_pcap --- enrich.py | 35 +++++++++++++++++++++++++++++++---- 1 file changed, 31 insertions(+), 4 deletions(-) diff --git a/enrich.py b/enrich.py index 30d188c..4c28a37 100755 --- a/enrich.py +++ b/enrich.py @@ -301,6 +301,7 @@ def analyze_pcap(pcapng_path, start_ts, end_ts, ap_bssid, ap_channel): ssid_signals = defaultdict(list) ssid_to_bssids = defaultdict(set) bssid_to_ssid = {} + cisco_reported_clients = [] try: # Filter packets manually by timestamp @@ -350,6 +351,27 @@ def analyze_pcap(pcapng_path, start_ts, end_ts, ap_bssid, ap_channel): print(f"[DEBUG] Error parsing SSID: {e}") continue + try: + mgt = packet.get_multiple_layers('wlan.mgt')[0] + if hasattr(mgt, 'get_field'): + tags = mgt.get_field('tag') + if not tags: + print("[DEBUG] wlan.mgt present, but no tags parsed.") + + if tags and isinstance(tags, list): + for tag in tags: + if tag.get('wlan.tag.number') == '133': + try: + num_clients = int(tag.get('wlan.cisco.ccx1.clients')) + except (TypeError, ValueError): + num_clients = 0 + + cisco_reported_clients.append(num_clients) + break + except Exception as e: + print(f"[DEBUG] Could not parse Cisco client count: {e}") + cisco_reported_clients = None + bssid = getattr(wlan, 'bssid', '').lower() # For debugging purposes, print the SSID and BSSID @@ -375,11 +397,13 @@ def analyze_pcap(pcapng_path, start_ts, end_ts, ap_bssid, ap_channel): aps_on_channel = get_aps_on_channel(filtered_packets, ap_channel) avg_ap_signal, max_ap_signal = calculate_signal_strength_stats(filtered_packets, ap_channel) unlinked_devices = get_unlinked_devices(filtered_packets, ap_channel) + cisco_avg_reported_clients = mean(cisco_reported_clients) if cisco_reported_clients else 0 + cisco_max_reported_clients = max(cisco_reported_clients) if cisco_reported_clients else 0 finally: cap.close() - return clients_on_ap, clients_on_channel, aps_on_channel, avg_ap_signal, max_ap_signal, unlinked_devices + return clients_on_ap, clients_on_channel, aps_on_channel, avg_ap_signal, max_ap_signal, unlinked_devices, cisco_avg_reported_clients, cisco_max_reported_clients def main(): args = parse_args() @@ -407,7 +431,8 @@ def main(): reader = csv.DictReader(infile) fieldnames = reader.fieldnames + [ 'ClientsOnAP', 'ClientsOnChannel', 'APsOnChannel', - 'AvgAPSignal', 'StrongestAPSignal', 'UnlinkedDevices' + 'AvgAPSignal', 'StrongestAPSignal', 'UnlinkedDevices', + 'CiscoAvgReportedClients', 'CiscoMaxReportedClients' ] writer = csv.DictWriter(outfile, fieldnames=fieldnames) writer.writeheader() @@ -422,7 +447,7 @@ def main(): writer.writerow(row) continue - clients_ap, clients_chan, aps_chan, avg_signal, strongest_signal, unlinked = analyze_pcap(args.pcapng, tstart, tend, ap_bssid, ap_channel) + clients_ap, clients_chan, aps_chan, avg_signal, strongest_signal, unlinked, cisco_avg_reported_clients, cisco_max_reported_clients = analyze_pcap(args.pcapng, tstart, tend, ap_bssid, ap_channel) row.update({ 'ClientsOnAP': clients_ap, @@ -430,7 +455,9 @@ def main(): 'APsOnChannel': aps_chan, 'AvgAPSignal': avg_signal, 'StrongestAPSignal': strongest_signal, - 'UnlinkedDevices': unlinked + 'UnlinkedDevices': unlinked, + 'CiscoReportedClients': cisco_avg_reported_clients, + 'CiscoMaxReportedClients': cisco_max_reported_clients }) writer.writerow(row)