@@ -300,6 +300,66 @@ def get_terminal_width():
300300 import shutil
301301 return shutil .get_terminal_size (fallback = (24 , 80 )).columns
302302
303+ def _diagnose_no_targets (self ):
304+ """Print actionable diagnostics when a scan finds zero targets.
305+
306+ The bare "issues with your wifi card" message can't tell the three
307+ common root causes apart, so we probe them explicitly:
308+ * the card/driver captured nothing in monitor mode (RX counter ~0) —
309+ a driver/monitor-mode problem, not a network one;
310+ * APs exist but were removed by an encryption/type filter;
311+ * the scan only covered 2.4 GHz (5 GHz APs need -5 / --band).
312+
313+ Best-effort: never raises.
314+ """
315+ import os
316+ iface = Configuration .interface
317+ Color .pl ('\n {!} {O}Scan diagnostics:{W}' )
318+
319+ # 1. Did the monitor interface actually receive any frames? In monitor
320+ # mode the kernel bumps rx_packets for every captured frame, so a
321+ # near-zero count is a strong sign the card isn't really capturing.
322+ rx = None
323+ driver = None
324+ if iface :
325+ try :
326+ with open ('/sys/class/net/%s/statistics/rx_packets' % iface ) as fh :
327+ rx = int (fh .read ().strip ())
328+ except (OSError , ValueError ):
329+ rx = None
330+ try :
331+ driver = os .path .basename (
332+ os .path .realpath ('/sys/class/net/%s/device/driver' % iface ))
333+ except OSError :
334+ driver = None
335+
336+ if rx is not None :
337+ Color .pl (' {C}Interface:{W} %s%s {C}frames received:{W} %d' % (
338+ iface , (' {D}(%s){W}' % driver ) if driver else '' , rx ))
339+ if rx < 10 :
340+ Color .pl (' {R}→ The card received ~no frames in monitor mode.{W}' )
341+ Color .pl (' {O}This is almost always a driver/monitor-mode problem, '
342+ 'not a network issue:{W}' )
343+ Color .pl (' {O} - Verify monitor mode + injection: {C}aireplay-ng --test %s{W}' % iface )
344+ Color .pl (' {O} - Some USB chipsets (rtw88/rtl8xxxu) have flaky monitor '
345+ 'mode; try a different adapter.{W}' )
346+ Color .pl (' {O} - Check {C}dmesg{O} for mac80211 / USB errors.{W}' )
347+ else :
348+ Color .pl (' {G}→ The card IS receiving frames{W} — so the cause is '
349+ 'filtering or band, not the driver:' )
350+
351+ # 2. Band coverage (default scan is 2.4 GHz only).
352+ if not (Configuration .all_bands or Configuration .five_ghz ):
353+ Color .pl (' {O} - Scanning {C}2.4 GHz only{O} (default); for 5 GHz APs add '
354+ '{C}-5{O} or {C}--band abg{W}.' )
355+
356+ # 3. Active encryption/type filter (< 5 means a specific filter is on).
357+ enc = getattr (Configuration , 'encryption_filter' , None )
358+ if enc and len (enc ) < 5 :
359+ Color .pl (' {O} - Type filter active: {C}%s{O}; other AP types are hidden — '
360+ 'drop the filter to see all.{W}' % '/' .join (enc ))
361+ Color .pl ('' )
362+
303363 def select_targets (self ):
304364 """
305365 Returns list(target)
@@ -316,10 +376,8 @@ def select_targets(self):
316376 if self .err_msg is not None :
317377 Color .pl (self .err_msg )
318378
319- # TODO Print a more-helpful reason for failure.
320- # 1. Link to wireless drivers wiki,
321- # 2. How to check if your device supports monitor mode,
322- # 3. Provide airodump-ng command being executed.
379+ self ._diagnose_no_targets ()
380+
323381 raise Exception ('No targets found.'
324382 + ' You may need to wait longer,'
325383 + ' or you may have issues with your wifi card' )
0 commit comments