diff --git a/wifi_monitor.py b/wifi_monitor.py index caabf4a..1a91ef4 100755 --- a/wifi_monitor.py +++ b/wifi_monitor.py @@ -427,14 +427,18 @@ class CaptureAnalyzer: total_count = len(packets) print(f"Total packets captured (scapy): {total_count}") + scapy_data_count = sum(1 for pkt in packets if pkt.haslayer(Dot11) and pkt[Dot11].type == 2) + if tcpdump_data_count is not None: + print(f"Data frames captured (scapy): {scapy_data_count}") print(f"Data frames captured (tcpdump): {tcpdump_data_count}") - if total_count > 0: - scapy_data_count = sum(1 for pkt in packets if pkt.haslayer(Dot11) and pkt[Dot11].type == 2) - print(f"Data frames captured (scapy): {scapy_data_count}") - if tcpdump_data_count > 0: - ratio = scapy_data_count / tcpdump_data_count - print(f"Scapy capture ratio: {ratio:.1%} ({scapy_data_count}/{tcpdump_data_count})") + if tcpdump_data_count > 0: + ratio = scapy_data_count / tcpdump_data_count + print(f"Scapy capture ratio: {ratio:.1%} ({scapy_data_count}/{tcpdump_data_count})") + elif scapy_data_count > 0: + print(f"Note: tcpdump found 0 data frames while scapy found {scapy_data_count}") + else: + print("Note: tcpdump counter unavailable (tcpdump not found or failed)") if total_count == 0: self._print_no_packets_message() @@ -786,11 +790,14 @@ class PacketCapture: ) await check_proc.wait() if check_proc.returncode != 0: + print("Warning: tcpdump not found, skipping concurrent count") return None # Use tcpdump with BPF filter for data frames - # wlan[0] & 0x0C extracts the type field (bits 2-3) - # Type 2 (data) = 0x08, so we check wlan[0] & 0x0C == 0x08 + # For 802.11 frames: wlan[0] contains Frame Control field + # Bits 2-3 are the type field: 00=Management, 01=Control, 10=Data + # Type 2 (Data) = 0x08 when masked with 0x0C + # BPF syntax: use == for equality comparison proc = await asyncio.create_subprocess_exec( "tcpdump", "-i", interface, @@ -817,6 +824,18 @@ class PacketCapture: _, stderr = await proc.communicate() stderr_text = stderr.decode() if stderr else "" + # Check return code + if proc.returncode != 0 and proc.returncode != -15: # -15 is SIGTERM, which is expected + print(f"Warning: tcpdump exited with code {proc.returncode}") + if stderr_text: + print(f"tcpdump stderr: {stderr_text[:300]}") + return None + + # Debug: print stderr if no count found + if not stderr_text.strip(): + print("Warning: tcpdump produced no output") + return None + # Parse tcpdump output for packet count # Format: "X packets captured" or "X packets received by filter" data_frame_count = 0 @@ -834,11 +853,19 @@ class PacketCapture: if potential_count > data_frame_count: data_frame_count = potential_count - return data_frame_count if data_frame_count > 0 else None + if data_frame_count == 0: + # Debug output - but still return 0 so we can show it + print(f"Warning: tcpdump found 0 data frames. tcpdump stderr: {stderr_text[:200]}") + + # Return the count even if 0, so we can display it + return data_frame_count except FileNotFoundError: + print("Warning: tcpdump not found, skipping concurrent count") return None except Exception as e: print(f"Warning: tcpdump counter failed: {e}") + import traceback + traceback.print_exc() return None async def _main_capture_async(self, interface, duration):