Adding log file and generic wifilogger refactoring
[wifihood] / wifisniffer / wifilogger.py
1 #!/usr/bin/python
2
3 import pcapy
4 import struct
5
6 iface = 'wlan0'
7
8 import time
9
10 from ieee80211 import *
11
12 max_time = 15 * 60
13 tstamp = time.time()
14
15 logfile = open( "wifilogger.log" , "a" )
16
17 max_bytes = 1024
18 promiscuous = False
19 read_timeout = 100 # in milliseconds
20 pc = pcapy.open_live(iface, max_bytes, promiscuous, read_timeout)
21
22
23 def parse_radiotap( radiotap , it_present ) :
24
25     fields = []
26     rfmt , padstr = "<" , ""
27     for name,bit,fmt,pad in ratiotap_header_bits :
28         if it_present & ( 0x1 << bit ) :
29             if not fmt :
30                 print "ERROR : unknown bit %s (%d) set" % ( name , bit )
31                 return
32             fields.append( name )
33             if fmt == "hh" :
34                 fields.append( "CHANNEL_BITMAP" )
35             rfmt += fmt
36             if pad :
37                 padstr += "x"
38     values = struct.unpack(rfmt+padstr,radiotap)
39
40     radio_hdr = {}
41     for i in range(len(fields)) :
42         radio_hdr[fields[i]] = values[i]
43
44     flags = []
45     for name,value in radiotap_flags :
46         if radio_hdr['FLAGS'] & value == value :
47             flags.append( name )
48     if radio_hdr['FLAGS'] != 16 and radio_hdr['FLAGS'] != 18 :
49         # 16 - FCS
50         # 18 - SHORTPRE , FCS
51         print 'WARNING : Unexpected flags : (%s) %s' % ( radio_hdr['FLAGS'] , " , ".join( flags ) )
52     radio_hdr['_flags'] = flags
53
54     channel = []
55     for name,value in channel_flags :
56         if radio_hdr['CHANNEL_BITMAP'] & value == value :
57             channel.append( name )
58     if radio_hdr['CHANNEL_BITMAP'] != 160 and radio_hdr['CHANNEL_BITMAP'] != 192 :
59         # 160 - CCK , 2GHZ
60         # 192 - OFDM , 2GHZ
61         print 'WARNING : Unexpected channel flags : (%s) %s' % ( radio_hdr['CHANNEL_BITMAP'] , " , ".join( channel ) )
62     radio_hdr['_channel_bitmap'] = channel
63
64     return radio_hdr
65
66
67 class CaptureEnd ( Exception ) : pass
68
69
70 def dealWithPacket ( hdr , data ) :
71
72     if hdr.getlen() != hdr.getcaplen() :
73         print "ERROR : bad sizes in header : %d vs. %d" % ( hdr.getlen() , hdr.getcaplen() )
74         return
75     if len(data) != hdr.getlen() :
76         print "ERROR : Data lenght does not match"
77         return
78
79     it_version , it_len , it_present = struct.unpack("<Bxhl",data[:8])
80     if it_version != 0 :
81         print "ERROR : Bad version (%s), it is probably not radiotap header" % it_version
82         return
83     if it_len <= 0 :
84         print "ERROR : Bad length on radiotap header"
85         return
86     if it_len != 32 :
87         print "ERROR : Strange length on radiotap header"
88         return
89
90     radio_hdr = parse_radiotap( data[8:it_len] , it_present )
91     if not radio_hdr :
92         return
93
94
95     payload = data[it_len:]
96
97     pcktlen = len(payload)
98
99     frame_ctl , frame_ctl2 , duration_id = struct.unpack("BBh",payload[:4])
100     pointer  = 4
101     pcktlen -= 4
102
103
104     for name,value in frame_types :
105         if frame_ctl & 0x0c == value :
106             frame_type = name
107             break
108     else :
109         print "ERROR : unknown frame type %s" % ( frame_ctl & 0x0c , )
110         return
111
112     if frame_type == "MGT" :
113         for name,value in management_subtypes :
114             if frame_ctl & 0xf0 == value :
115                 frame_subtype = name
116                 break
117         else :
118             print "ERROR : unknown MGT subtype %s" % ( frame_ctl & 0xf0 , )
119             return
120
121     elif frame_type == "CTL" :
122         for name,value in control_subtypes :
123             if frame_ctl & 0xf0 == value :
124                 frame_subtype = name
125                 break
126         else :
127             print "ERROR : unknown CTL subtype %s" % ( frame_ctl & 0xf0 , )
128             return
129
130     elif frame_type == "DATA" :
131         _subtype = []
132         for name,value in data_subtypes :
133             if frame_ctl & 0xf0 == value :
134                 _subtype.append( name )
135         frame_subtype = "-".join( _subtype )
136
137     else :
138         print "Handling of frame type %s not implemented" % frame_type
139         return
140
141
142     for name,value in directions : # Only for DATA frames ???
143         if frame_ctl2 & 0x03 == value :
144             direction = name
145             break
146     else :
147         print "ERROR : unknown direction %s" % ( frame_ctl2 & 0x03 , )
148         return
149
150
151     mac_str = "BBBBBB" # is leading '<' required
152     mac_fmt = "%02X:%02X:%02X:%02X:%02X:%02X"
153
154     maclist = []
155     for i in range(3) :
156         maclist.append( mac_fmt % struct.unpack( mac_str , payload[pointer:pointer+6] ) )
157         pointer += 6
158         pcktlen -= 6
159         if pcktlen < 6 :
160             break
161
162
163     if frame_type != "CTL" :
164         sequence = struct.unpack("BB",payload[pointer:pointer+2])
165         pointer += 2
166         pcktlen -= 2
167     else :
168         sequence = ( -1 , -1 )
169
170
171     if frame_type == "DATA" :
172         maclist.append( mac_fmt % struct.unpack( mac_str , payload[pointer:pointer+6] ) )
173         pointer += 6
174         pcktlen -= 6
175
176
177     logfile.write( "%4s %13s %6s %4d [ %2d %2d ] read %4d missing %4d" % (frame_type,frame_subtype,direction,radio_hdr['CHANNEL'],radio_hdr['FLAGS'],radio_hdr['CHANNEL_BITMAP'],pointer,pcktlen) )
178     logfile.write( " = %s %s " % ( radio_hdr['DBM_ANTSIGNAL'] , radio_hdr['DBM_ANTNOISE'] ) )
179     logfile.write( " ; %4d %4d " % sequence )
180     logfile.write( " - %4d :" % duration_id )
181     logfile.write( " %s"*len(maclist) % tuple(maclist) )
182     logfile.write( "\n" )
183
184     curtime = time.time()
185     if curtime - tstamp > max_time :
186         raise CaptureEnd( "Neighborhoud scan completed" )
187
188
189 packet_limit = -1 # infinite
190 try :
191     pc.loop( packet_limit , dealWithPacket )
192 except CaptureEnd , ex :
193     print "FINISED : %s" % ex
194 except Exception , ex :
195     print "ERROR : %s" % ex
196
197 logfile.close()
198