Improved detection of frame type and examine according ieee80211_frame structure
authorjaviplx <javiplx@gmail.com>
Sun, 10 Oct 2010 23:34:56 +0000 (23:34 +0000)
committerjaviplx <javiplx@gmail.com>
Sun, 10 Oct 2010 23:34:56 +0000 (23:34 +0000)
git-svn-id: file:///svnroot/wifihood/trunk/wifiscanner@46 c51dfc6a-5949-4919-9c8e-f207a149c383

wiviz.py

index 5710393..98001d4 100755 (executable)
--- a/wiviz.py
+++ b/wiviz.py
@@ -35,6 +35,8 @@ ratiotap_header_bits = (
 
 # 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
@@ -42,7 +44,11 @@ channel_flags = (
 ( "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
@@ -73,23 +79,49 @@ radiotap_tx_flags = (
 )
 
 
-# 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 )  
 )
-
 
 import time
 
@@ -146,46 +178,70 @@ def dealWithPacket ( hdr , data ) :
     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
 
-    mac_str = "<BBBBBB"
+    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 = "UNDEFINED"
+
+
+    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 :
@@ -193,6 +249,7 @@ def dealWithPacket ( hdr , data ) :
         fd.close()
         raise Exception( "Neighborhoud scan completed" )
 
+    print "%4s %13s %4d %4d from %4d" % (type,subtype,values[3],pcktlen,len(payload))," ; %4d %4d "%sequence,":"+" %s"*len(maclist) % tuple(maclist)
 
 packet_limit = -1 # infinite
 pc.loop( packet_limit , dealWithPacket )