def extcap_capture(interface, fifo, control_in, control_out, channel, tap): """Start the sniffer to capture packets""" # baudrate = detect_baudrate(interface) interface_port = str(interface).split(':')[0] interface_baudrate = str(interface).split(':')[1] with _StreamCloser(StreamOpen('u', interface_port, False, baudrate=int(interface_baudrate))) as stream, \ WpanApi(stream, nodeid=DEFAULT_NODEID) as wpan_api: wpan_api.prop_set_value(SPINEL.PROP_PHY_ENABLED, 1) if sys.platform == 'win32': python_path = subprocess.Popen( 'py -3 -c "import sys; print(sys.executable)"', stdout=subprocess.PIPE, shell=True, ).stdout.readline().decode().strip() sniffer_py = os.path.join(os.path.dirname(python_path), 'Scripts', 'sniffer.py') cmd = ['python', sniffer_py] else: cmd = ['sniffer.py'] cmd += [ '-c', channel, '-u', interface_port, '--crc', '--rssi', '-b', interface_baudrate, '-o', str(fifo), '--is-fifo', '--use-host-timestamp' ] if tap: cmd.append('--tap') subprocess.Popen(cmd).wait()
def open(self): '''Opens transport for communication.''' self._stream = StreamOpen(self._stream_descriptor[0], self._stream_descriptor[1], False) # FIXME: remove node id from constructor after WpanAPI is refactored self._wpan = WpanApi(self._stream, 666) self._wpan.queue_register(SPINEL.HEADER_DEFAULT) self._wpan.queue_register(SPINEL.HEADER_ASYNC) self._wpan.callback_register(SPINEL.PROP_STREAM_NET, self._wpan_receive) if (self._config[NCPTransport.CFG_KEY_RESET] ) and not self._wpan.cmd_reset(): raise Exception( 'Failed to reset NCP. Please flash connectivity firmware.') logger.info('Attaching to the network') if (not self._attach_to_network()): logger.error("Failed to attach to the network") raise Exception('Unable to attach') self._ml_eid = ipaddress.ip_address( self._wpan.prop_get_value(SPINEL.PROP_IPV6_ML_ADDR)) self._ml_prefix = self._wpan.prop_get_value(SPINEL.PROP_IPV6_ML_PREFIX) logger.info("Done") self.print_addresses()
def main(): """ Top-level main for sniffer host-side tool. """ (options, remaining_args) = parse_args() if options.debug: CONFIG.debug_set_level(options.debug) # Set default stream to pipe stream_type = 'p' stream_descriptor = "../../examples/apps/ncp/ot-ncp-ftd "+options.nodeid if options.uart: stream_type = 'u' stream_descriptor = options.uart elif options.socket: stream_type = 's' stream_descriptor = options.socket elif options.pipe: stream_type = 'p' stream_descriptor = options.pipe if options.nodeid: stream_descriptor += " "+str(options.nodeid) else: if len(remaining_args) > 0: stream_descriptor = " ".join(remaining_args) stream = StreamOpen(stream_type, stream_descriptor, False) if stream is None: exit() wpan_api = WpanApi(stream, options.nodeid) sniffer_init(wpan_api, options) pcap = PcapCodec() hdr = pcap.encode_header() if options.hex: hdr = util.hexify_str(hdr)+"\n" sys.stdout.write(hdr) sys.stdout.flush() try: tid = SPINEL.HEADER_ASYNC prop_id = SPINEL.PROP_STREAM_RAW while True: result = wpan_api.queue_wait_for_prop(prop_id, tid) if result and result.prop == prop_id: length = wpan_api.parse_S(result.value) pkt = result.value[2:2+length] if options.ti_crc: pkt = ti_crc(pkt) pkt = pcap.encode_frame(pkt) if options.hex: pkt = util.hexify_str(pkt)+"\n" sys.stdout.write(pkt) sys.stdout.flush() except KeyboardInterrupt: pass if wpan_api: wpan_api.stream.close()
def serialopen(interface, log_file): """ Open serial to indentify OpenThread sniffer :param interface: string, eg: '/dev/ttyUSB0 - Zolertia Firefly platform', '/dev/ttyACM1 - nRF52840 OpenThread Device' """ sys.stdout = log_file sys.stderr = log_file interface = str(interface).split()[0] baudrate = None for speed in COMMON_BAUDRATE: with _StreamCloser(StreamOpen('u', interface, False, baudrate=speed)) as stream, \ WpanApi(stream, nodeid=DEFAULT_NODEID, timeout=0.1) as wpan_api: # result should not be None for both NCP and RCP result = wpan_api.prop_get_value( SPINEL.PROP_CAPS) # confirm OpenThread Sniffer # check whether or not is OpenThread Sniffer if result is not None: baudrate = speed break if baudrate is not None: if sys.platform == 'win32': # Wireshark only shows the value of key `display`('OpenThread Sniffer'). # Here intentionally appends interface in the end (e.g. 'OpenThread Sniffer: COM0'). print('interface {value=%s:%s}{display=OpenThread Sniffer %s}' % (interface, baudrate, interface), file=sys.__stdout__, flush=True) else: # On Linux or MacOS, wireshark will show the concatenation of the content of `display` # and `interface` by default (e.g. 'OpenThread Sniffer: /dev/ttyACM0'). print('interface {value=%s:%s}{display=OpenThread Sniffer}' % (interface, baudrate), file=sys.__stdout__, flush=True)
def main(): """ Top-level main for sniffer host-side tool. """ (options, remaining_args) = parse_args() if options.debug: CONFIG.debug_set_level(options.debug) # Set default stream to pipe stream_type = 'p' stream_descriptor = "../../examples/apps/ncp/ot-ncp-ftd " + options.nodeid if options.uart: stream_type = 'u' stream_descriptor = options.uart elif options.socket: stream_type = 's' stream_descriptor = options.socket elif options.pipe: stream_type = 'p' stream_descriptor = options.pipe if options.nodeid: stream_descriptor += " " + str(options.nodeid) else: if len(remaining_args) > 0: stream_descriptor = " ".join(remaining_args) stream = StreamOpen(stream_type, stream_descriptor, False, options.baudrate) if stream is None: exit() wpan_api = WpanApi(stream, options.nodeid) result = sniffer_init(wpan_api, options) if not result: sys.stderr.write("ERROR: failed to initialize sniffer\n") exit() else: sys.stderr.write("SUCCESS: sniffer initialized\nSniffing...\n") pcap = PcapCodec() hdr = pcap.encode_header() if options.hex: hdr = util.hexify_str(hdr) + "\n" sys.stdout.write(hdr) sys.stdout.flush() epoch = datetime(1970, 1, 1) timebase = datetime.utcnow() - epoch timebase_sec = timebase.days * 24 * 60 * 60 + timebase.seconds timebase_usec = timebase.microseconds try: tid = SPINEL.HEADER_ASYNC prop_id = SPINEL.PROP_STREAM_RAW while True: result = wpan_api.queue_wait_for_prop(prop_id, tid) if result and result.prop == prop_id: length = wpan_api.parse_S(result.value) pkt = result.value[2:2 + length] if options.crc: pkt = crc(pkt) # metadata format (totally 17 bytes): # 0. RSSI(int8) # 1. Noise Floor(int8) # 2. Flags(uint16) # 3. PHY-specific data struct contains: # 3.0 Channel(uint8) # 3.1 LQI(uint8) # 3.2 Timestamp Msec(uint32) # 3.3 Timestamp Usec(uint16) # 4. Vendor data struct contains: # 4.0 Receive error(uint8) if len(result.value) == 2 + length + 17: metadata = wpan_api.parse_fields( result.value[2 + length:2 + length + 17], "ccSt(CCLS)t(i)") timestamp_usec = timebase_usec + metadata[3][ 2] * 1000 + metadata[3][3] timestamp_sec = timebase_sec + timestamp_usec / 1000000 timestamp_usec = timestamp_usec % 1000000 if options.rssi: pkt = pkt[:-2] + chr(metadata[0] & 0xff) + chr(0x80) # Some old version NCP doesn't contain timestamp information in metadata else: timestamp = datetime.utcnow() - epoch timestamp_sec = timestamp.days * 24 * 60 * 60 + timestamp.seconds timestamp_usec = timestamp.microseconds if options.rssi: pkt = pkt[:-2] + chr(127) + chr(0x80) sys.stderr.write( "WARNING: failed to display RSSI, please update the NCP version\n" ) pkt = pcap.encode_frame(pkt, timestamp_sec, timestamp_usec) if options.hex: pkt = util.hexify_str(pkt) + "\n" sys.stdout.write(pkt) sys.stdout.flush() except KeyboardInterrupt: pass if wpan_api: wpan_api.stream.close()
def main(): """ Top-level main for sniffer host-side tool. """ (options, remaining_args) = parse_args() if options.debug: CONFIG.debug_set_level(options.debug) if options.use_host_timestamp: print('WARNING: Using host timestamp, may be inaccurate', file=sys.stderr) # Set default stream to pipe stream_type = 'p' stream_descriptor = "../../examples/apps/ncp/ot-ncp-ftd " + options.nodeid if options.uart: stream_type = 'u' stream_descriptor = options.uart elif options.socket: stream_type = 's' stream_descriptor = options.socket elif options.pipe: stream_type = 'p' stream_descriptor = options.pipe if options.nodeid: stream_descriptor += " " + str(options.nodeid) else: if len(remaining_args) > 0: stream_descriptor = " ".join(remaining_args) stream = StreamOpen(stream_type, stream_descriptor, False, options.baudrate, options.rtscts) if stream is None: exit() wpan_api = WpanApi(stream, options.nodeid) result = sniffer_init(wpan_api, options) if not result: sys.stderr.write("ERROR: failed to initialize sniffer\n") exit() else: sys.stderr.write("SUCCESS: sniffer initialized\nSniffing...\n") pcap = PcapCodec() hdr = pcap.encode_header( DLT_IEEE802_15_4_TAP if options.tap else DLT_IEEE802_15_4_WITHFCS) if options.hex: hdr = util.hexify_str(hdr) + "\n" if options.output: output = open(options.output, 'wb') elif hasattr(sys.stdout, 'buffer'): output = sys.stdout.buffer else: output = sys.stdout output.write(hdr) output.flush() if options.is_fifo: threading.Thread(target=check_fifo, args=(output, )).start() epoch = datetime(1970, 1, 1) timebase = datetime.utcnow() - epoch timebase_sec = timebase.days * 24 * 60 * 60 + timebase.seconds timebase_usec = timebase.microseconds try: tid = SPINEL.HEADER_ASYNC prop_id = SPINEL.PROP_STREAM_RAW while True: result = wpan_api.queue_wait_for_prop(prop_id, tid) if result and result.prop == prop_id: length = wpan_api.parse_S(result.value) pkt = result.value[2:2 + length] # metadata format (totally 19 bytes): # 0. RSSI(int8) # 1. Noise Floor(int8) # 2. Flags(uint16) # 3. PHY-specific data struct contains: # 3.0 Channel(uint8) # 3.1 LQI(uint8) # 3.2 Timestamp in microseconds(uint64) # 4. Vendor data struct contains: # 4.0 Receive error(uint8) if len(result.value) == 2 + length + 19: metadata = wpan_api.parse_fields( result.value[2 + length:2 + length + 19], "ccSt(CCX)t(i)") timestamp = metadata[3][2] timestamp_sec = timestamp / 1000000 timestamp_usec = timestamp % 1000000 # (deprecated) metadata format (totally 17 bytes): # 0. RSSI(int8) # 1. Noise Floor(int8) # 2. Flags(uint16) # 3. PHY-specific data struct contains: # 3.0 Channel(uint8) # 3.1 LQI(uint8) # 3.2 Timestamp Msec(uint32) # 3.3 Timestamp Usec(uint16) # 4. Vendor data struct contains: # 4.0 Receive error(uint8) elif len(result.value) == 2 + length + 17: metadata = wpan_api.parse_fields( result.value[2 + length:2 + length + 17], "ccSt(CCLS)t(i)") timestamp_usec = timebase_usec + metadata[3][ 2] * 1000 + metadata[3][3] timestamp_sec = timebase_sec + timestamp_usec / 1000000 timestamp_usec = timestamp_usec % 1000000 # Some old version NCP doesn't contain timestamp information in metadata else: timestamp = datetime.utcnow() - epoch timestamp_sec = timestamp.days * 24 * 60 * 60 + timestamp.seconds timestamp_usec = timestamp.microseconds if options.rssi: sys.stderr.write( "WARNING: failed to display RSSI, please update the NCP version\n" ) if options.use_host_timestamp: timestamp = round(time.time() * 1000000) timestamp_sec = timestamp // 1000000 timestamp_usec = timestamp % 1000000 pkt = pcap.encode_frame(pkt, int(timestamp_sec), timestamp_usec, options.rssi, options.crc, metadata) if options.hex: pkt = util.hexify_str(pkt) + "\n" output.write(pkt) output.flush() except KeyboardInterrupt: pass if wpan_api: wpan_api.stream.close() output.close()
def main(): parser = argparse.ArgumentParser() parser.add_argument('rcp', type=str, help='path to rcp executable') args = parser.parse_args() stream = StreamOpen('p', f'{args.rcp} 1', False, 115200, False) wpan_api = WpanApi(stream, 1) assert wpan_api.prop_set_value(SPINEL.PROP_PHY_ENABLED, 1) == 1 ext_addr = b'\x00\x11\x22\x33\x44\x55\x66\x77' assert wpan_api.prop_set_value(SPINEL.PROP_PHY_CHAN, 17) == 17 assert wpan_api.prop_set_value(SPINEL.PROP_MAC_15_4_SADDR, 0x1234, 'H') == 0x1234 assert wpan_api.prop_set_value(SPINEL.PROP_MAC_15_4_LADDR, ext_addr, '8s') == ext_addr assert wpan_api.prop_set_value(SPINEL.PROP_MAC_SRC_MATCH_ENABLED, 1) == 1 while wpan_api.prop_insert_value( SPINEL.PROP_MAC_SRC_MATCH_EXTENDED_ADDRESSES, ext_addr, '8s') == ext_addr: ext_addr = (int.from_bytes(ext_addr, 'little') + 1).to_bytes( 8, 'little') short_addr = 0x2345 while wpan_api.prop_insert_value(SPINEL.PROP_MAC_SRC_MATCH_SHORT_ADDRESSES, short_addr, 'H') == short_addr: short_addr += 1 assert wpan_api.prop_set_value(SPINEL.PROP_MAC_FILTER_MODE, SPINEL.MAC_FILTER_MODE_PROMISCUOUS) in { SPINEL.MAC_FILTER_MODE_PROMISCUOUS, SPINEL.MAC_FILTER_MODE_MONITOR, } assert wpan_api.prop_set_value(SPINEL.PROP_MAC_RAW_STREAM_ENABLED, 1) == 1 assert wpan_api.prop_set_value(SPINEL.PROP_MAC_SCAN_MASK, 11) == [11] assert wpan_api.prop_set_value( SPINEL.PROP_MAC_SCAN_STATE, SPINEL.SCAN_STATE_ENERGY) == SPINEL.SCAN_STATE_ENERGY wpan_api.cmd_send(SPINEL.CMD_RESET) assert wpan_api.prop_get_value(SPINEL.PROP_PHY_ENABLED) == 0 assert wpan_api.prop_set_value(SPINEL.PROP_PHY_ENABLED, 1) == 1 assert wpan_api.prop_get_value(SPINEL.PROP_PHY_CHAN) == 11 assert wpan_api.prop_get_value(SPINEL.PROP_MAC_15_4_SADDR) == 0xfffe assert wpan_api.prop_get_value(SPINEL.PROP_MAC_15_4_LADDR) == b'\x00' * 8 assert wpan_api.prop_get_value(SPINEL.PROP_MAC_SRC_MATCH_ENABLED) == 0 assert wpan_api.prop_set_value(SPINEL.PROP_MAC_SRC_MATCH_ENABLED, 1) == 1 assert wpan_api.prop_insert_value( SPINEL.PROP_MAC_SRC_MATCH_EXTENDED_ADDRESSES, ext_addr, '8s') == ext_addr assert wpan_api.prop_insert_value( SPINEL.PROP_MAC_SRC_MATCH_SHORT_ADDRESSES, short_addr, 'H') == short_addr assert wpan_api.prop_get_value( SPINEL.PROP_MAC_FILTER_MODE) == SPINEL.MAC_FILTER_MDOE_NORMAL assert wpan_api.prop_get_value(SPINEL.PROP_MAC_RAW_STREAM_ENABLED) == 0 assert wpan_api.prop_get_value( SPINEL.PROP_MAC_SCAN_STATE) == SPINEL.SCAN_STATE_IDLE