1 import struct
2 import glob
3 from warnings import warn
4
5 from pcapdump import *
6 from daintree import *
7 from pcapdlt import *
8
9 from kbutils import *
10 from zigbeedecode import *
11 from dot154decode import *
12 from config import *
16 '''
17 Returns an instance of a KillerBee device, setup on the given channel.
18 Error handling for KillerBee creation and setting of the channel is wrapped
19 and will raise an Exception().
20 @return: A KillerBee instance initialized to the given channel.
21 '''
22 kb = KillerBee()
23 if kb is None:
24 raise Exception("Failed to create a KillerBee instance.")
25 try:
26 kb.set_channel(channel)
27 except Exception, e:
28 raise Exception('Error: Failed to set channel to %d' % channel, e)
29 return kb
30
32 '''Deprecated. Use show_dev or call kbutils.devlist.'''
33 return kbutils.devlist(vendor=None, product=None)
34
35 -def show_dev(vendor=None, product=None, gps=None, include=None):
36 '''
37 A basic function to output the device listing.
38 Placed here for reuse, as many tool scripts were implementing it.
39 @param gps: Provide device names in this argument (previously known as
40 'gps') which you wish to not be enumerated. Aka, exclude these items.
41 @param include: Provide device names in this argument if you would like only
42 these to be enumerated. Aka, include only these items.
43 '''
44 print("{: >14} {: <20} {: >10}".format("Dev", "Product String", "Serial Number"))
45 for dev in kbutils.devlist(vendor=vendor, product=product, gps=gps, include=include):
46 print("{0: >14} {1: <20} {2: >10}".format(dev[0], dev[1], dev[2]))
47
50 - def __init__(self, device=None, datasource=None, gps=None):
51 '''
52 Instantiates the KillerBee class.
53
54 @type device: String
55 @param device: Device identifier, either USB vendor:product, serial device node, or IP address
56 @type datasource: String
57 @param datasource: A known datasource type that is used
58 by dblog to record how the data was captured.
59 @type gps: String
60 @param gps: Optional serial device identifier for an attached GPS
61 unit. If provided, or if global variable has previously been set,
62 KillerBee skips that device in initalization process.
63 @return: None
64 @rtype: None
65 '''
66
67 global gps_devstring
68 if gps_devstring is None and gps is not None:
69 gps_devstring = gps
70
71 self.dev = None
72 self.__bus = None
73 self.driver = None
74
75
76
77
78 if (device is not None) and kbutils.isIpAddr(device):
79 from dev_wislab import isWislab
80 if isWislab(device):
81 from dev_wislab import WISLAB
82 self.driver = WISLAB(dev=device)
83 else: del isWislab
84
85
86 if self.driver is None:
87 if device is None:
88 result = kbutils.search_usb(None)
89 if result != None:
90 if USBVER == 0:
91 (self.__bus, self.dev) = result
92 elif USBVER == 1:
93
94 self.dev = result
95
96 elif ":" in device:
97 result = kbutils.search_usb(device)
98 if result == None:
99 raise KBInterfaceError("Did not find a USB device matching %s." % device)
100 else:
101 if USBVER == 0:
102 (self.__bus, self.dev) = result
103 elif USBVER == 1:
104
105 self.dev = result
106
107 if self.dev is not None:
108 if self.__device_is(RZ_USB_VEND_ID, RZ_USB_PROD_ID):
109 from dev_rzusbstick import RZUSBSTICK
110 self.driver = RZUSBSTICK(self.dev, self.__bus)
111 elif self.__device_is(ZN_USB_VEND_ID, ZN_USB_PROD_ID):
112 raise KBInterfaceError("Zena firmware not yet implemented.")
113 else:
114 raise KBInterfaceError("KillerBee doesn't know how to interact with USB device vendor=%04x, product=%04x.".format(self.dev.idVendor, self.dev.idProduct))
115
116
117
118
119
120
121
122
123
124 if self.driver is None:
125
126 if device is None:
127 glob_list = get_serial_ports()
128 if len(glob_list) > 0:
129
130 device = glob_list[0]
131
132 if (device is not None) and kbutils.isSerialDeviceString(device):
133 self.dev = device
134 if (self.dev == gps_devstring):
135 pass
136 elif (DEV_ENABLE_ZIGDUINO and kbutils.iszigduino(self.dev)):
137 from dev_zigduino import ZIGDUINO
138 self.driver = ZIGDUINO(self.dev)
139 elif (DEV_ENABLE_FREAKDUINO and kbutils.isfreakduino(self.dev)):
140 from dev_freakduino import FREAKDUINO
141 self.driver = FREAKDUINO(self.dev)
142 else:
143 gfccspi,subtype = isgoodfetccspi(self.dev)
144 if gfccspi and subtype == 0:
145 from dev_telosb import TELOSB
146 self.driver = TELOSB(self.dev)
147 elif gfccspi and subtype == 1:
148 from dev_apimote import APIMOTE
149 self.driver = APIMOTE(self.dev, revision=1)
150 elif gfccspi and subtype == 2:
151 from dev_apimote import APIMOTE
152 self.driver = APIMOTE(self.dev, revision=2)
153 else:
154 raise KBInterfaceError("KillerBee doesn't know how to interact with serial device at '%s'." % self.dev)
155
156 else:
157 raise KBInterfaceError("KillerBee doesn't understand device given by '%s'." % device)
158
159
160 if datasource is not None:
161 try:
162 import dblog
163 self.dblog = dblog.DBLogger(datasource)
164 except Exception as e:
165 warn("Error initializing DBLogger (%s)." % e)
166 datasource = None
167
169 '''
170 Compares KillerBee class' device data to a known USB vendorId and productId
171 @type vendorId:
172 @type productId:
173 @rtype: Boolean
174 @return: True if KillerBee class has device matching the vendor and product IDs provided.
175 '''
176 if self.dev.idVendor == vendorId and self.dev.idProduct == productId: return True
177 else: return False
178
179
181 '''
182 Deprecated in class, use kbutils.search_usb(device, vendor, product) instead of class version.
183 '''
184 raise DeprecationWarning("Use kbutils.search_usb(device, vendor, product) instead of class version.")
185
186
187
189 '''
190 Deprecated in class, use kbutils.search_usb_bus(bus, device, vendor, product) instead of class version.
191 '''
192 raise DeprecationWarning("Use kbutils.search_usb_bus(bus, device, vendor, product) instead of class version.")
193
194
195
196 - def dev_list(self, vendor=None, product=None):
197 '''
198 Deprecated in class, use kbutils.devlist() instead.
199 '''
200 raise DeprecationWarning("Use kbutils.devlist(vendor, product) instead of class version.")
201
202
204 '''
205 Returns device information in a list identifying the device. Implemented by the loaded driver.
206 @rtype: List
207 @return: List of 3 strings identifying device.
208 '''
209 return self.driver.get_dev_info()
210
212 '''
213 Closes the device out.
214 @return: None
215 @rtype: None
216 '''
217 if self.driver != None: self.driver.close()
218 if hasattr(self, "dblog") and (self.dblog is not None):
219 self.dblog.close()
220
222 '''
223 Uses the specified capability to determine if the opened device
224 is supported. Returns True when supported, else False.
225 @rtype: Boolean
226 '''
227 return self.driver.capabilities.check(capab)
228
230 '''
231 Returns a list of capability information for the device.
232 @rtype: List
233 @return: Capability information for the opened device.
234 '''
235 return self.driver.capabilities.getlist()
236
238 '''
239 Turns the sniffer on such that pnext() will start returning observed
240 data. Will set the command mode to Air Capture if it is not already
241 set.
242 @type channel: Integer
243 @param channel: Sets the channel, optional
244 @rtype: None
245 '''
246 return self.driver.sniffer_on(channel)
247
249 '''
250 Turns the sniffer off, freeing the hardware for other functions. It is
251 not necessary to call this function before closing the interface with
252 close().
253 @rtype: None
254 '''
255 return self.driver.sniffer_off()
256
257 @property
259 """Getter function for the channel that was last set on the device."""
260
261 return self.driver._channel
262
264 '''
265 Sets the radio interface to the specifid channel. Currently, support is
266 limited to 2.4 GHz channels 11 - 26.
267 @type channel: Integer
268 @param channel: Sets the channel, optional
269 @rtype: None
270 '''
271 if hasattr(self, "dblog"):
272 self.dblog.set_channel(channel)
273 self.driver.set_channel(channel)
274
276 '''
277 Based on sniffer capabilities, return if this is an OK channel number.
278 @rtype: Boolean
279 '''
280 return self.driver.capabilities.is_valid_channel(channel)
281
282 - def inject(self, packet, channel=None, count=1, delay=0):
283 '''
284 Injects the specified packet contents.
285 @type packet: String
286 @param packet: Packet contents to transmit, without FCS.
287 @type channel: Integer
288 @param channel: Sets the channel, optional
289 @type count: Integer
290 @param count: Transmits a specified number of frames, def=1
291 @type delay: Float
292 @param delay: Delay between each frame, def=1
293 @rtype: None
294 '''
295 return self.driver.inject(packet, channel, count, delay)
296
297 - def pnext(self, timeout=100):
298 '''
299 Returns packet data as a string, else None.
300 @type timeout: Integer
301 @param timeout: Timeout to wait for packet reception in usec
302 @rtype: List
303 @return: Returns None is timeout expires and no packet received. When a packet is received, a list is returned, in the form [ String: packet contents | Bool: Valid CRC | Int: Unscaled RSSI ]
304 '''
305 return self.driver.pnext(timeout)
306
308 '''
309 Attempts reflexive jamming on all 802.15.4 frames.
310 Targeted frames must be >12 bytes for reliable jamming in current firmware.
311 @type channel: Integer
312 @param channel: Sets the channel, optional.
313 @rtype: None
314 '''
315 return self.driver.jammer_on(channel=channel)
316