Relocate monitor mode utilities in their specific directory
authorJavier Palacios <javiplx@gmail.com>
Mon, 23 Jul 2012 07:53:53 +0000 (09:53 +0200)
committerJavier Palacios <javiplx@gmail.com>
Mon, 23 Jul 2012 07:53:53 +0000 (09:53 +0200)
wifiscanner/ieee80211.py [deleted file]
wifiscanner/pcapy/build.sh [deleted file]
wifiscanner/wiviz.py [deleted file]
wifisniffer/ieee80211.py [new file with mode: 0755]
wifisniffer/pcapy/build.sh [new file with mode: 0755]
wifisniffer/wifilogger.py [new file with mode: 0755]

diff --git a/wifiscanner/ieee80211.py b/wifiscanner/ieee80211.py
deleted file mode 100755 (executable)
index 0b38558..0000000
+++ /dev/null
@@ -1,122 +0,0 @@
-
-# Removed leading IEEE80211_RADIOTAP_
-ratiotap_header_bits = (
-( "TSFT" , 0 , "q" , False ) ,
-( "FLAGS" , 1 , "B" , True ) ,
-( "RATE" , 2 , "B" , True ) ,
-( "CHANNEL" , 3 , "hh" , False ) ,
-( "FHSS" , 4 , "h" , False ) ,
-( "DBM_ANTSIGNAL" , 5 , "b" , True ) ,
-( "DBM_ANTNOISE" , 6 , "b" , True ) ,
-( "LOCK_QUALITY" , 7 , "h" , False ) ,
-( "TX_ATTENUATION" , 8 , "h" , False ) ,
-( "DB_TX_ATTENUATION" , 9 , "h" , False ) ,
-( "DBM_TX_POWER" , 10 , "b" , True ) ,
-( "ANTENNA" , 11 , "B" , True ) ,
-( "DB_ANTSIGNAL" , 12 , "B" , True ) ,
-( "DB_ANTNOISE" , 13 , "B" , True ) ,
-( "RX_FLAGS" , 14 , "h" , False ) ,
-( "TX_FLAGS" , 15 , "h" , False ) ,
-( "RTS_RETRIES" , 16 , "B" , True ) ,
-( "DATA_RETRIES" , 17 , "B" , True ) ,
-( "EXT" , 31 , "" , False )
-) 
-
-# 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
-( "2GHZ"    , 0x0080 ) , # 2 GHz spectrum 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)
-( "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
-# IEEE80211_CHAN_G  = IEEE80211_CHAN_2GHZ | IEEE80211_CHAN_DYN
-# IEEE80211_CHAN_TA = IEEE80211_CHAN_5GHZ | IEEE80211_CHAN_OFDM | IEEE80211_CHAN_TURBO
-# IEEE80211_CHAN_TG = IEEE80211_CHAN_2GHZ | IEEE80211_CHAN_DYN  | IEEE80211_CHAN_TURBO
-
-# Removed leading IEEE80211_RADIOTAP_F_
-radiotap_flags = (
-( "CFP"      , 0x01 ) , # sent/received during CFP
-( "SHORTPRE" , 0x02 ) , # sent/received with short preamble
-( "WEP"      , 0x04 ) , # sent/received with WEP encryption
-( "FRAG"     , 0x08 ) , # sent/received with fragmentation
-( "FCS"      , 0x10 ) , # frame includes FCS
-( "DATAPAD"  , 0x20 )   # frame has padding between 802.11 header and payload (to 32-bit boundary)
-)
-
-# Removed leading IEEE80211_RADIOTAP_F_RX_
-radiotap_rx_flags = (
-( "BADFCS" , 0x0001 )   # frame failed crc check
-)
-
-# Removed leading IEEE80211_RADIOTAP_F_TX_
-radiotap_tx_flags = (
-( "FAIL" , 0x0001 ) , # failed due to excessive retries
-( "CTS"  , 0x0002 ) , # used cts 'protection'
-( "RTS"  , 0x0004 )   # used rts/cts handshake
-)
-
-
-# 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
-)
-
diff --git a/wifiscanner/pcapy/build.sh b/wifiscanner/pcapy/build.sh
deleted file mode 100755 (executable)
index 8a0d443..0000000
+++ /dev/null
@@ -1,26 +0,0 @@
-#!/bin/sh
-
-set -e
-
-VERSION="0.10.6"
-
-if [ ! -d pcapy-0.10.6 ] ; then
-
-  if [ ! -f pcapy_${VERSION}.orig.tar.gz ] ; then
-    wget --quiet "http://corelabs.coresecurity.com/index.php?module=Wiki&action=attachment&type=tool&page=Pcapy&file=pcapy-${VERSION}.tar.gz" -O pcapy_${VERSION}.orig.tar.gz
-    fi
-
-  tar -xzf pcapy_${VERSION}.orig.tar.gz
-  fi
-
-cd pcapy-0.10.6
-svn --quiet co svn://svn.debian.org/python-modules/packages/pcapy/trunk/debian
-
-sed -i \
-       -e '/cdbs/ d' \
-       -e 's/python-all-dev/python-dev/' \
-       -e '/Maintainer: / a Packager: Javier Palacios <javiplx@gmail.com>' \
-       debian/control
-
-dpkg-buildpackage -rfakeroot -us -uc
-
diff --git a/wifiscanner/wiviz.py b/wifiscanner/wiviz.py
deleted file mode 100755 (executable)
index 7d0bbc6..0000000
+++ /dev/null
@@ -1,180 +0,0 @@
-#!/usr/bin/python
-
-import pcapy
-import struct
-
-iface = 'wlan0'
-
-max_bytes = 1024
-promiscuous = False
-read_timeout = 100 # in milliseconds
-pc = pcapy.open_live(iface, max_bytes, promiscuous, read_timeout)
-
-from ieee80211 import *
-
-import time
-
-max_time = 1
-tstamp = time.time()
-discovered = []
-
-def parse_radiotap( radiotap , it_present ) :
-
-    fields = []
-    format , padstr = "<" , ""
-    for name,bit,fmt,pad in ratiotap_header_bits :
-# What about  'it_present & ( 0x1 << bit )' ??
-        if it_present & pow(2,bit) == pow(2,bit) :
-            if not fmt :
-                print "Unknown bit %s (%d) set" % ( name , bit )
-                return
-            fields.append( name )
-            if fmt == "hh" :
-                fields.append( "CHANNEL_BITMAP" )
-            format += fmt
-            if pad :
-                padstr += "x"
-    values = struct.unpack(format+padstr,radiotap])
-
-    radio_hdr = {}
-    for i in range(len(fields)) :
-        radio_hdr[fields[i]] = values[i]
-
-    flags = []
-    for name,value in radiotap_flags :
-        if radio_hdr['FLAGS'] & value == value :
-            flags.append( name )
-    radio_hdr['_flags'] = flags
-    if radio_hdr['FLAGS'] != 16 and radio_hdr['FLAGS'] != 18 :
-        # 16 - FCS
-        # 18 - SHORTPRE , FCS
-        print 'WARNING : Unexpected flags : (%s) %s' % ( radio_hdr['FLAGS'] , " , ".join( flags ) )
-
-    channel = []
-    for name,value in channel_flags :
-        if radio_hdr['CHANNEL_BITMAP'] & value == value :
-            channel.append( name )
-    if radio_hdr['CHANNEL_BITMAP'] != 160 and radio_hdr['CHANNEL_BITMAP'] != 192 :
-        # 160 - CCK , 2GHZ
-        # 192 - OFDM , 2GHZ
-        print 'WARNING : Unexpected channel flags : (%s) %s' % ( radio_hdr['CHANNEL_BITMAP'] , " , ".join( channel ) )
-    radio_hdr['_channel_bitmap'] = channel
-
-    return radio_hdr
-
-
-def dealWithPacket ( hdr , data ) :
-
-    if hdr.getlen() != hdr.getcaplen() :
-        print "Error in header : %d vs. %d" % ( hdr.getlen() , hdr.getcaplen() )
-        return
-    if len(data) != hdr.getlen() :
-        print "Data lenght does not match"
-        return
-
-    it_version , it_len , it_present = struct.unpack("<Bxhl",data[:8])
-    if it_version != 0 :
-        print "Bad version (%s), it is probably not radiotap header" % it_version
-        return
-    if it_len <= 0 :
-        print "Bad length on radiotap header"
-        return
-
-    radio_hdr = parse_radiotap( data[8:it_len] , it_present )
-    if not radio_hdr :
-        return
-
-    payload = data[it_len:]
-
-
-    pointer = 0
-    pcktlen = len(payload)
-
-    frame_ctl , frame_subtype , duration_id = struct.unpack("BBh",payload[:4])
-    pointer += 4
-    pcktlen -= 4
-
-    for name,value in frame_type :
-        if frame_ctl & 0x0c == value :
-            type = name
-            break
-    else :
-        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" # is leading '<' required
-    mac_fmt = "%02X:%02X:%02X:%02X:%02X:%02X"
-
-    maclist = []
-    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 :
-            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,frame_subtype,duration_id,"seq",sequence
-#    print type,":",maclist,"->",pcktlen
-#    print
-
-    global tstamp,max_time,discovered
-    for mac in maclist :
-        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.write( "%s\n" % mac )
-        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 )
-
diff --git a/wifisniffer/ieee80211.py b/wifisniffer/ieee80211.py
new file mode 100755 (executable)
index 0000000..0b38558
--- /dev/null
@@ -0,0 +1,122 @@
+
+# Removed leading IEEE80211_RADIOTAP_
+ratiotap_header_bits = (
+( "TSFT" , 0 , "q" , False ) ,
+( "FLAGS" , 1 , "B" , True ) ,
+( "RATE" , 2 , "B" , True ) ,
+( "CHANNEL" , 3 , "hh" , False ) ,
+( "FHSS" , 4 , "h" , False ) ,
+( "DBM_ANTSIGNAL" , 5 , "b" , True ) ,
+( "DBM_ANTNOISE" , 6 , "b" , True ) ,
+( "LOCK_QUALITY" , 7 , "h" , False ) ,
+( "TX_ATTENUATION" , 8 , "h" , False ) ,
+( "DB_TX_ATTENUATION" , 9 , "h" , False ) ,
+( "DBM_TX_POWER" , 10 , "b" , True ) ,
+( "ANTENNA" , 11 , "B" , True ) ,
+( "DB_ANTSIGNAL" , 12 , "B" , True ) ,
+( "DB_ANTNOISE" , 13 , "B" , True ) ,
+( "RX_FLAGS" , 14 , "h" , False ) ,
+( "TX_FLAGS" , 15 , "h" , False ) ,
+( "RTS_RETRIES" , 16 , "B" , True ) ,
+( "DATA_RETRIES" , 17 , "B" , True ) ,
+( "EXT" , 31 , "" , False )
+) 
+
+# 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
+( "2GHZ"    , 0x0080 ) , # 2 GHz spectrum 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)
+( "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
+# IEEE80211_CHAN_G  = IEEE80211_CHAN_2GHZ | IEEE80211_CHAN_DYN
+# IEEE80211_CHAN_TA = IEEE80211_CHAN_5GHZ | IEEE80211_CHAN_OFDM | IEEE80211_CHAN_TURBO
+# IEEE80211_CHAN_TG = IEEE80211_CHAN_2GHZ | IEEE80211_CHAN_DYN  | IEEE80211_CHAN_TURBO
+
+# Removed leading IEEE80211_RADIOTAP_F_
+radiotap_flags = (
+( "CFP"      , 0x01 ) , # sent/received during CFP
+( "SHORTPRE" , 0x02 ) , # sent/received with short preamble
+( "WEP"      , 0x04 ) , # sent/received with WEP encryption
+( "FRAG"     , 0x08 ) , # sent/received with fragmentation
+( "FCS"      , 0x10 ) , # frame includes FCS
+( "DATAPAD"  , 0x20 )   # frame has padding between 802.11 header and payload (to 32-bit boundary)
+)
+
+# Removed leading IEEE80211_RADIOTAP_F_RX_
+radiotap_rx_flags = (
+( "BADFCS" , 0x0001 )   # frame failed crc check
+)
+
+# Removed leading IEEE80211_RADIOTAP_F_TX_
+radiotap_tx_flags = (
+( "FAIL" , 0x0001 ) , # failed due to excessive retries
+( "CTS"  , 0x0002 ) , # used cts 'protection'
+( "RTS"  , 0x0004 )   # used rts/cts handshake
+)
+
+
+# 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
+)
+
diff --git a/wifisniffer/pcapy/build.sh b/wifisniffer/pcapy/build.sh
new file mode 100755 (executable)
index 0000000..8a0d443
--- /dev/null
@@ -0,0 +1,26 @@
+#!/bin/sh
+
+set -e
+
+VERSION="0.10.6"
+
+if [ ! -d pcapy-0.10.6 ] ; then
+
+  if [ ! -f pcapy_${VERSION}.orig.tar.gz ] ; then
+    wget --quiet "http://corelabs.coresecurity.com/index.php?module=Wiki&action=attachment&type=tool&page=Pcapy&file=pcapy-${VERSION}.tar.gz" -O pcapy_${VERSION}.orig.tar.gz
+    fi
+
+  tar -xzf pcapy_${VERSION}.orig.tar.gz
+  fi
+
+cd pcapy-0.10.6
+svn --quiet co svn://svn.debian.org/python-modules/packages/pcapy/trunk/debian
+
+sed -i \
+       -e '/cdbs/ d' \
+       -e 's/python-all-dev/python-dev/' \
+       -e '/Maintainer: / a Packager: Javier Palacios <javiplx@gmail.com>' \
+       debian/control
+
+dpkg-buildpackage -rfakeroot -us -uc
+
diff --git a/wifisniffer/wifilogger.py b/wifisniffer/wifilogger.py
new file mode 100755 (executable)
index 0000000..7d0bbc6
--- /dev/null
@@ -0,0 +1,180 @@
+#!/usr/bin/python
+
+import pcapy
+import struct
+
+iface = 'wlan0'
+
+max_bytes = 1024
+promiscuous = False
+read_timeout = 100 # in milliseconds
+pc = pcapy.open_live(iface, max_bytes, promiscuous, read_timeout)
+
+from ieee80211 import *
+
+import time
+
+max_time = 1
+tstamp = time.time()
+discovered = []
+
+def parse_radiotap( radiotap , it_present ) :
+
+    fields = []
+    format , padstr = "<" , ""
+    for name,bit,fmt,pad in ratiotap_header_bits :
+# What about  'it_present & ( 0x1 << bit )' ??
+        if it_present & pow(2,bit) == pow(2,bit) :
+            if not fmt :
+                print "Unknown bit %s (%d) set" % ( name , bit )
+                return
+            fields.append( name )
+            if fmt == "hh" :
+                fields.append( "CHANNEL_BITMAP" )
+            format += fmt
+            if pad :
+                padstr += "x"
+    values = struct.unpack(format+padstr,radiotap])
+
+    radio_hdr = {}
+    for i in range(len(fields)) :
+        radio_hdr[fields[i]] = values[i]
+
+    flags = []
+    for name,value in radiotap_flags :
+        if radio_hdr['FLAGS'] & value == value :
+            flags.append( name )
+    radio_hdr['_flags'] = flags
+    if radio_hdr['FLAGS'] != 16 and radio_hdr['FLAGS'] != 18 :
+        # 16 - FCS
+        # 18 - SHORTPRE , FCS
+        print 'WARNING : Unexpected flags : (%s) %s' % ( radio_hdr['FLAGS'] , " , ".join( flags ) )
+
+    channel = []
+    for name,value in channel_flags :
+        if radio_hdr['CHANNEL_BITMAP'] & value == value :
+            channel.append( name )
+    if radio_hdr['CHANNEL_BITMAP'] != 160 and radio_hdr['CHANNEL_BITMAP'] != 192 :
+        # 160 - CCK , 2GHZ
+        # 192 - OFDM , 2GHZ
+        print 'WARNING : Unexpected channel flags : (%s) %s' % ( radio_hdr['CHANNEL_BITMAP'] , " , ".join( channel ) )
+    radio_hdr['_channel_bitmap'] = channel
+
+    return radio_hdr
+
+
+def dealWithPacket ( hdr , data ) :
+
+    if hdr.getlen() != hdr.getcaplen() :
+        print "Error in header : %d vs. %d" % ( hdr.getlen() , hdr.getcaplen() )
+        return
+    if len(data) != hdr.getlen() :
+        print "Data lenght does not match"
+        return
+
+    it_version , it_len , it_present = struct.unpack("<Bxhl",data[:8])
+    if it_version != 0 :
+        print "Bad version (%s), it is probably not radiotap header" % it_version
+        return
+    if it_len <= 0 :
+        print "Bad length on radiotap header"
+        return
+
+    radio_hdr = parse_radiotap( data[8:it_len] , it_present )
+    if not radio_hdr :
+        return
+
+    payload = data[it_len:]
+
+
+    pointer = 0
+    pcktlen = len(payload)
+
+    frame_ctl , frame_subtype , duration_id = struct.unpack("BBh",payload[:4])
+    pointer += 4
+    pcktlen -= 4
+
+    for name,value in frame_type :
+        if frame_ctl & 0x0c == value :
+            type = name
+            break
+    else :
+        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" # is leading '<' required
+    mac_fmt = "%02X:%02X:%02X:%02X:%02X:%02X"
+
+    maclist = []
+    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 :
+            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,frame_subtype,duration_id,"seq",sequence
+#    print type,":",maclist,"->",pcktlen
+#    print
+
+    global tstamp,max_time,discovered
+    for mac in maclist :
+        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.write( "%s\n" % mac )
+        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 )
+