Package killerbee :: Package zbwardrive :: Module capture
[hide private]
[frames] | no frames]

Source Code for Module killerbee.zbwardrive.capture

 1  import sys 
 2  from datetime import datetime 
 3  import threading, signal 
 4  from killerbee import * 
 5   
 6  # Globals 
 7  triggers = [] 
 8   
 9  # startCapture 
10  # Given a database and a key into the database's networks table, 
11  #  initiate a pcap and online database capture. 
12 -def startCapture(zbdb, channel, dblog=False, gps=False):
13 ''' 14 Before calling, you should have already ensured the channel or the 15 channel which the key is associated with does not already have an active 16 capture occuring. 17 ''' 18 nextDev = zbdb.get_devices_nextFree() 19 #TODO if device not availabe, wait till one opens up, and then occupy it. if nothing opens within 10 seconds, say you don't have a device available 20 capChan = channel 21 key = "CH%d" % channel 22 if nextDev == None: 23 print 'Cap%s: No free device to use for capture.' % key 24 return None 25 print 'Cap%s: Launching a capture on channel %s.' % (key, capChan) 26 signal.signal(signal.SIGINT, interrupt) 27 trigger = threading.Event() 28 triggers.append(trigger) 29 CaptureThread(capChan, nextDev, trigger, dblog=dblog, gps=gps).start() 30 zbdb.update_devices_start_capture(nextDev, capChan)
31 32 # Called on keyboard interput to exit threads and exit the scanner script.
33 -def interrupt(signum, frame):
34 global triggers 35 for trigger in triggers: 36 trigger.set() 37 sys.exit(1)
38 39 # Thread to capture a given channel, using a given device, to a given filename 40 # exits when trigger (threading.Event object) is set. 41 #TODO change to multiprocessing, with the db having shared state
42 -class CaptureThread(threading.Thread):
43 - def __init__(self, channel, devstring, trigger, dblog=False, gps=None):
44 self.channel = channel 45 self.rf_freq_mhz = (channel - 10) * 5 + 2400 46 self.devstring = devstring 47 self.trigger = trigger 48 self.packetcount = 0 49 self.useDBlog = dblog 50 self.currentGPS = gps 51 52 timeLabel = datetime.now().strftime('%Y%m%d-%H%M') 53 fname = 'zb_c%s_%s.pcap' % (channel, timeLabel) #fname is -w equiv 54 self.pd = PcapDumper(DLT_IEEE802_15_4, fname, ppi=True) 55 56 threading.Thread.__init__(self)
57
58 - def run(self):
59 if self.useDBlog == True: 60 self.kb = KillerBee(device=self.devstring, datasource="Wardrive Live") 61 else: 62 self.kb = KillerBee(device=self.devstring) 63 self.kb.set_channel(self.channel) 64 self.kb.sniffer_on() 65 print "Capturing on \'%s\' at channel %d." % (self.kb.get_dev_info()[0], self.channel) 66 # loop capturing packets to dblog and file 67 while not self.trigger.is_set(): 68 packet = self.kb.pnext() 69 if packet != None: 70 self.packetcount+=1 71 if self.useDBlog: #by checking, we avoid wasted time and warnings 72 self.kb.dblog.add_packet(full=packet) 73 try: 74 if self.currentGPS != None and 'lat' in self.currentGPS: 75 # We use the existince of the 'lat' key to promise ourselves 76 # that the lat, lng, and alt keys are there. 77 self.pd.pcap_dump(packet[0], 78 freq_mhz=self.rf_freq_mhz, ant_dbm=packet['dbm'], 79 location=(self.currentGPS['lng'], self.currentGPS['lat'], self.currentGPS['alt']) ) 80 else: 81 self.pd.pcap_dump(packet[0], freq_mhz=self.rf_freq_mhz, 82 ant_dbm=packet['dbm']) 83 except IOError as e: 84 #TODO replace this with code that ensures the captures exit before the manager 85 # maybe have a shared memory int that is the number of currently running capture threads, 86 # or use a shared state db, and only once all devices are marked free does the manager die 87 if e.errno == 32: #broken pipe, likely from manager being shut down 88 continue 89 else: 90 raise e 91 #TODO if no packet detected in a certain period of time, and we know other channels want capture, then quit 92 93 # trigger threading.Event set to false, so shutdown thread 94 self.kb.sniffer_off() 95 self.kb.close() 96 self.pd.close() 97 print "%d packets captured on channel %d." % (self.packetcount, self.channel)
98