# Removed leading IEEE80211_CHAN_
channel_flags = (
+( "INDOOR" , 0x0004 ) , # This channel can be used indoor
+( "OUTDOOR" , 0x0008 ) , # This channel can be used outdoor
( "TURBO" , 0x0010 ) , # Turbo channel
( "CCK" , 0x0020 ) , # CCK channel
( "OFDM" , 0x0040 ) , # OFDM channel
( "5GHZ" , 0x0100 ) , # 5 GHz spectrum channel
( "PASSIVE" , 0x0200 ) , # Only passive scan allowed
( "DYN" , 0x0400 ) , # Dynamic CCK-OFDM channel
-( "GFSK" , 0x0800 ) # GFSK channel (FHSS PHY)
+( "GFSK" , 0x0800 ) , # GFSK channel (FHSS PHY)
+( "RADAR" , 0x1000 ) , # Radar found on channel
+( "STURBO" , 0x2000 ) , # 11a static turbo channel only
+( "HALF" , 0x4000 ) , # Half rate channel
+( "QUARTER" , 0x8000 ) , # Quarter rate channel
)
# IEEE80211_CHAN_A = IEEE80211_CHAN_5GHZ | IEEE80211_CHAN_OFDM
# IEEE80211_CHAN_B = IEEE80211_CHAN_2GHZ | IEEE80211_CHAN_CCK
)
-# Unknown origin
-# Removed leading IEEE80211_STYPE_
-management_flags = (
-( "ASSOC_REQ" , 0x0000 ) ,
-( "ASSOC_RESP" , 0x0010 ) ,
-( "REASSOC_REQ" , 0x0020 ) ,
-( "REASSOC_RESP" , 0x0030 ) ,
-( "PROBE_REQ" , 0x0040 ) ,
-( "PROBE_RESP" , 0x0050 ) ,
-( "BEACON" , 0x0080 ) ,
-( "ATIM" , 0x0090 ) ,
-( "DISASSOC" , 0x00A0 ) ,
-( "AUTH" , 0x00B0 ) ,
-( "DEAUTH" , 0x00C0 ) ,
-( "ACTION" , 0x00D0 )
+# without IEEE80211_FC0_TYPE_
+frame_type = (
+( "MGT" , 0x00 ) ,
+( "CTL" , 0x04 ) ,
+( "DATA" , 0x08 )
+)
+# without IEEE80211_FC0_SUBTYPE_
+management_subtypes = (
+( "ASSOC_REQ" , 0x00 ) ,
+( "ASSOC_RESP" , 0x10 ) ,
+( "REASSOC_REQ" , 0x20 ) ,
+( "REASSOC_RESP" , 0x30 ) ,
+( "PROBE_REQ" , 0x40 ) ,
+( "PROBE_RESP" , 0x50 ) ,
+( "BEACON" , 0x80 ) ,
+( "ATIM" , 0x90 ) ,
+( "DISASSOC" , 0xA0 ) ,
+( "AUTH" , 0xB0 ) ,
+( "DEAUTH" , 0xC0 ) ,
+( "ACTION" , 0xD0 )
+)
+# without IEEE80211_FC0_SUBTYPE_
+control_subtypes = (
+( "PS_POLL" , 0xa0 ) ,
+( "RTS" , 0xb0 ) ,
+( "CTS" , 0xc0 ) ,
+( "ACK" , 0xd0 ) ,
+( "CF_END" , 0xe0 ) ,
+( "CF_END_ACK" , 0xf0 )
+)
+# without IEEE80211_FC0_SUBTYPE_
+data_subtypes = (
+( "DATA" , 0x00 ) ,
+( "CF_ACK" , 0x10 ) ,
+( "CF_POLL" , 0x20 ) ,
+( "CF_ACPL" , 0x30 ) ,
+( "NULL" , 0x40 ) ,
+( "CFACK" , 0x50 ) ,
+( "CFPOLL" , 0x60 ) ,
+( "CF_ACK_CF_ACK" , 0x70 ) ,
+( "QOS" , 0x80 ) ,
+( "QOS_NULL" , 0xc0 )
)
+# without IEEE80211_FC1_DIR_
+directions = (
+( "NODS" , 0x00 ) , # STA->STA
+( "TODS" , 0x01 ) , # STA->AP
+( "FROMDS" , 0x02 ) , # AP ->STA
+( "DSTODS" , 0x03 ) # AP ->AP
+)
import time
pointer = 0
pcktlen = len(payload)
- frame_ctl , duration_id = struct.unpack("<hh",payload[:4])
+ frame_ctl , frame_subtype , duration_id = struct.unpack("BBh",payload[:4])
pointer += 4
pcktlen -= 4
- for name,value in management_flags :
- if frame_ctl == value :
+
+ for name,value in frame_type :
+ if frame_ctl & 0x0c == value :
type = name
break
else :
- type = "unknown_%s" % frame_ctl
+ print "Unknown frame type %s" % ( frame_ctl & 0x0c , )
+ return
+
+ if type == "MGT" :
+ for name,value in management_subtypes :
+ if frame_ctl & 0xf0 == value :
+ subtype = name
+ break
+ else :
+ print "Unknown MGT subtype %s" % ( frame_ctl & 0xf0 , )
+ return
+
+ elif type == "CTL" :
+ for name,value in control_subtypes :
+ if frame_ctl & 0xf0 == value :
+ subtype = name
+ break
+ else :
+ print "Unknown CTL subtype %s" % ( frame_ctl & 0xf0 , )
+ return
+
+ elif type == "DATA" :
+ _subtype = []
+ for name,value in data_subtypes :
+ if frame_ctl & 0xf0 == value :
+ _subtype.append( name )
+ subtype = "-".join( _subtype )
+
+ for name,value in directions :
+ if frame_subtype & 0x03 == value :
+ direction = name
+ break
+ else :
+ print "Unknown direction %s" % ( frame_subtype & 0x03 , )
+ return
+
- mac_str = "<BBBBBB"
+ mac_str = "BBBBBB" # is leading '<' required
mac_fmt = "%02X:%02X:%02X:%02X:%02X:%02X"
maclist = []
- for i in range(4) :
+ for i in range(3) :
maclist.append( mac_fmt % struct.unpack( mac_str , payload[pointer:pointer+6] ) )
pointer += 6
pcktlen -= 6
+ # FIXME : only CTL/ACK have single address ???
+ # FIXME : Is this the same than pcktlen == 2
if pcktlen < 6 :
- unknowns = { 'unknown_212':12 , 'unknown_180':20 , 'unknown_196':12 , 'unknown_148':32 , 'unknown_4308':12 , 'unknown_4260':20 }
- if type in unknowns.keys() :
- if len(payload) == unknowns[type] :
- break
- raise Exception( "Unhandled type %s with length %d" % ( type , len(payload) ) )
+ break
+
+ sequence = struct.unpack("BB",payload[pointer:pointer+2])
+ pointer += 2
+ pcktlen -= 2
# print fields
# print values
# print "Radiotap flags : %s" % " ".join(flags)
# print "Channel %d (%s)" % ( values[3] , " ".join(channel) )
-## print "Control info",frame_ctl,duration_id
+## print "Control info",frame_ctl,frame_subtype,duration_id,"seq",sequence
# print type,":",maclist,"->",pcktlen
# print
- print "%20s %4d %5d" % (type,values[3],len(payload)),":"+" %s"*len(maclist) % tuple(maclist)
global tstamp,max_time,discovered
for mac in maclist :
- if not type.startswith( "unknown_" ) and not mac in discovered :
- if mac.startswith( "00:" ) :
- tstamp = time.time()
- discovered.append( mac )
+ if not mac in discovered :
+ tstamp = time.time()
+ discovered.append( mac )
if time.time()-tstamp > max_time :
fd = open( "discovered.list" , "a" )
for mac in discovered :
fd.close()
raise Exception( "Neighborhoud scan completed" )
+ print "%4s %13s %6s %4d %4d from %4d" % (type,subtype,direction,values[3],pcktlen,len(payload))," ; %4d %4d "%sequence,":"+" %s"*len(maclist) % tuple(maclist)
packet_limit = -1 # infinite
pc.loop( packet_limit , dealWithPacket )