From 0fd16d47f3bd5793cbb93de3c9dcec6324b92a6e Mon Sep 17 00:00:00 2001 From: Yaro Kasear Date: Fri, 2 May 2025 13:24:47 -0500 Subject: [PATCH] Refactor SSID metrics handling by removing Cisco client tracking and updating related functions for improved clarity and performance --- enrich.py | 10 ++------ enrichment/csv_handler.py | 2 +- enrichment/indexed_capture.py | 38 +++++------------------------- enrichment/merge_ssid_summaries.py | 6 ----- enrichment/metrics_ssid.py | 14 +---------- 5 files changed, 10 insertions(+), 60 deletions(-) diff --git a/enrich.py b/enrich.py index 5e5a2c9..eff2ab6 100755 --- a/enrich.py +++ b/enrich.py @@ -57,7 +57,6 @@ 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 = [] ssid_packet_counts = defaultdict(int) try: @@ -73,7 +72,6 @@ def analyze_pcap(pcapng_path, start_ts, end_ts, ap_bssid, ap_channel): ssid_hidden_status, ssid_encryption_status, ssid_signals, - cisco_reported_clients, ssid_packet_counts, ssid_clients ) = extract_ssid_metrics(filtered_packets) @@ -84,8 +82,6 @@ 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 num_bssids = len(ssid_to_bssids[our_ssid]) if our_ssid in ssid_to_bssids else 0 average_signal = mean(ssid_signals[our_ssid]) if our_ssid in ssid_signals else 0 max_ssid_signal = max(ssid_signals[our_ssid]) if our_ssid in ssid_signals else 0 @@ -115,9 +111,8 @@ def analyze_pcap(pcapng_path, start_ts, end_ts, ap_bssid, ap_channel): 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, num_bssids, - average_signal, max_ssid_signal, num_channels_ssid, - ssid_summary, packet_count + num_bssids, average_signal, max_ssid_signal, + num_channels_ssid, ssid_summary, packet_count ) def main(): @@ -158,7 +153,6 @@ def main(): ( clients_ap, clients_chan, aps_chan, avg_signal, strongest_signal, unlinked, - cisco_avg_reported_clients, cisco_max_reported_clients, num_bssids, average_signal, max_ssid_signal, num_channels_ssid, packet_count ) = result diff --git a/enrichment/csv_handler.py b/enrichment/csv_handler.py index 39a2342..8ad8da5 100644 --- a/enrichment/csv_handler.py +++ b/enrichment/csv_handler.py @@ -32,7 +32,7 @@ def write_ssid_sidecar(enriched_path, ssid_summary): with ssid_outfile.open('w', newline='', encoding='utf-8') as f: fieldnames = [ 'SSID', 'Hidden', 'Open', 'BSSID_Count', 'BSSIDs', 'Avg_Signal', 'Max_Signal', - 'Min_Signal', 'Clients_Seen', 'CiscoAvgClients', 'CiscoMaxClients', 'PacketCount' + 'Min_Signal', 'Clients_Seen', 'PacketCount' ] writer = csv.DictWriter(f, fieldnames=fieldnames) writer.writeheader() diff --git a/enrichment/indexed_capture.py b/enrichment/indexed_capture.py index b143100..f02d78e 100644 --- a/enrichment/indexed_capture.py +++ b/enrichment/indexed_capture.py @@ -12,8 +12,6 @@ class IndexedCapture: self.ssid_hidden_status = {} # SSID → hidden True/False self.ssid_encryption_status = {} # SSID → open/encrypted self.ssid_signals = defaultdict(list) # SSID → list of dBm values - self.cisco_ssid_clients = defaultdict(list) # SSID → list of (timestamp, client_count) - self.cisco_reported_clients = [] # list of all reported counts self.ssid_packet_counts = defaultdict(int) # SSID → number of packets self.ssid_clients = defaultdict(set) # SSID → MAC addresses self.channel_to_aps = defaultdict(set) # Channel → BSSID @@ -84,7 +82,7 @@ class IndexedCapture: privacy_bit = mgt._all_fields.get('wlan_mgt.fixed.capabilities.privacy') is_open = (str(privacy_bit) != '1') - # First: extract SSID and Cisco client info independently + # First: extract SSID client info independently for tag in tags: tag_number = tag.get('wlan.tag.number') @@ -100,12 +98,6 @@ class IndexedCapture: except Exception: ssid = None - if tag_number == '133': - try: - num_clients = int(tag.get('wlan.cisco.ccx1.clients')) - except (TypeError, ValueError): - num_clients = None - # Now that we have them parsed, update structures if ssid: self.ssid_hidden_status[ssid] = hidden_ssid @@ -114,8 +106,6 @@ class IndexedCapture: if num_clients is not None: timestamp = float(packet.frame_info.time_epoch) - self.cisco_ssid_clients[ssid].append((timestamp, num_clients)) - self.cisco_reported_clients.append(num_clients) bssid = getattr(wlan, 'bssid', '').lower() if not bssid or bssid == 'ff:ff:ff:ff:ff:ff': @@ -208,14 +198,14 @@ class IndexedCapture: clients_on_channel = len(window_clients.get(ap_channel, [])) aps_on_channel = len(window_aps.get(ap_channel, [])) - avg_ap_signal = mean(window_signals[ap_channel]) if window_signals.get(ap_channel) else 0 + avg_ap_signal = safe_mean(window_signals[ap_channel]) max_ap_signal = max(window_signals[ap_channel]) if window_signals.get(ap_channel) else 0 unlinked_devices = self._count_unlinked_devices(packets, ap_channel) our_ssid = self.bssid_to_ssid.get(ap_bssid) num_bssids = len(window_ssid_to_bssids.get(our_ssid, [])) if our_ssid else 0 - avg_ssid_signal = mean(window_ssid_signals.get(our_ssid, [])) if our_ssid else 0 + avg_ssid_signal = safe_mean(window_ssid_signals.get(our_ssid, [])) max_ssid_signal = max(window_ssid_signals.get(our_ssid, [])) if our_ssid else 0 num_channels_ssid = len({self._channel_of_bssid(b) for b in window_ssid_to_bssids.get(our_ssid, [])}) if our_ssid else 0 packet_count = len(packets) @@ -223,8 +213,6 @@ class IndexedCapture: return ( clients_on_ap, clients_on_channel, aps_on_channel, avg_ap_signal, max_ap_signal, unlinked_devices, - self._cisco_avg_clients(our_ssid, start_ts, end_ts), - self._cisco_max_clients(our_ssid, start_ts, end_ts), num_bssids, avg_ssid_signal, max_ssid_signal, num_channels_ssid, packet_count ) @@ -293,26 +281,12 @@ class IndexedCapture: continue return len(ghost_candidates) - - def _cisco_avg_clients(self, ssid, start_ts, end_ts): - if ssid not in self.cisco_ssid_clients: - return 0 - - hits = [] - for ts, count in self.cisco_ssid_clients[ssid]: - if start_ts <= ts <= end_ts: - hits.append(count) - - return round(mean(hits), 2) if hits else 0 - - def _cisco_max_clients(self, ssid, start_ts, end_ts): - if ssid not in self.cisco_ssid_clients: - return 0 - windowed = [count for ts, count in self.cisco_ssid_clients[ssid] if start_ts <= ts <= end_ts] - return max(windowed) if windowed else 0 def _channel_of_bssid(self, bssid): for channel, bssids in self.channel_to_aps.items(): if bssid in bssids: return channel return None + +def safe_mean(data): + return mean(data) if data else 0 diff --git a/enrichment/merge_ssid_summaries.py b/enrichment/merge_ssid_summaries.py index 12f0fe2..834b880 100644 --- a/enrichment/merge_ssid_summaries.py +++ b/enrichment/merge_ssid_summaries.py @@ -19,8 +19,6 @@ def merge_ssid_summaries(summary_lists): 'Max_Signal': entry['Max_Signal'], 'Min_Signal': entry['Min_Signal'], 'Clients_Seen': entry['Clients_Seen'], - 'CiscoAvgClients': [entry['CiscoAvgClients']], - 'CiscoMaxClients': entry['CiscoMaxClients'], 'PacketCount': entry['PacketCount'] } else: @@ -31,8 +29,6 @@ def merge_ssid_summaries(summary_lists): merged[key]['Max_Signal'] = max(merged[key]['Max_Signal'], entry['Max_Signal']) merged[key]['Min_Signal'] = min(merged[key]['Min_Signal'], entry['Min_Signal']) merged[key]['Clients_Seen'] += entry['Clients_Seen'] - merged[key]['CiscoAvgClients'].append(entry['CiscoAvgClients']) - merged[key]['CiscoMaxClients'] = max(merged[key]['CiscoMaxClients'], entry['CiscoMaxClients']) merged[key]['PacketCount'] += entry['PacketCount'] final_list = [] @@ -47,8 +43,6 @@ def merge_ssid_summaries(summary_lists): 'Max_Signal': data['Max_Signal'], 'Min_Signal': data['Min_Signal'], 'Clients_Seen': data['Clients_Seen'], - 'CiscoAvgClients': round(mean(data['CiscoAvgClients']), 2), - 'CiscoMaxClients': data['CiscoMaxClients'], 'PacketCount': data['PacketCount'] }) diff --git a/enrichment/metrics_ssid.py b/enrichment/metrics_ssid.py index 9c50124..fa68a44 100644 --- a/enrichment/metrics_ssid.py +++ b/enrichment/metrics_ssid.py @@ -7,9 +7,7 @@ def extract_ssid_metrics(packets): bssid_to_ssid = {} ssid_to_bssids = defaultdict(set) ssid_hidden_status = {} - ssid_encryption_status = {} - cisco_ssid_clients = defaultdict(list) - cisco_reported_clients = [] + ssid_encryption_status = {} ssid_signals = defaultdict(list) ssid_packet_counts = defaultdict(int) @@ -56,14 +54,6 @@ def extract_ssid_metrics(packets): ssid = ssid_bytes.decode('utf-8', errors='replace') except Exception: ssid = None - if tag_number == '133': - try: - num_clients = int(tag.get('wlan.cisco.ccx1.clients')) - if ssid: - cisco_ssid_clients[ssid].append(num_clients) - cisco_reported_clients.append(num_clients) - except (TypeError, ValueError): - pass if not ssid: continue @@ -104,8 +94,6 @@ def extract_ssid_metrics(packets): ssid_hidden_status, ssid_encryption_status, ssid_signals, - cisco_ssid_clients, - cisco_reported_clients, ssid_packet_counts, ssid_clients )