2016-07-21 07:55:03 +00:00
|
|
|
/* packet-nordic_ble.c
|
2021-06-28 10:11:51 +00:00
|
|
|
* Routines for nRF Sniffer for Bluetooth LE dissection
|
2016-07-21 07:55:03 +00:00
|
|
|
*
|
2018-03-13 08:28:15 +00:00
|
|
|
* Copyright (c) 2016-2018 Nordic Semiconductor.
|
2016-07-21 07:55:03 +00:00
|
|
|
*
|
|
|
|
* Wireshark - Network traffic analyzer
|
|
|
|
* By Gerald Combs <gerald@wireshark.org>
|
|
|
|
* Copyright 1998 Gerald Combs
|
|
|
|
*
|
2018-03-07 13:08:18 +00:00
|
|
|
* SPDX-License-Identifier: GPL-2.0-or-later
|
2016-07-21 07:55:03 +00:00
|
|
|
*/
|
|
|
|
|
2021-06-28 10:11:51 +00:00
|
|
|
/* nRF Sniffer for Bluetooth LE packet format: BoardID + Header + Payload
|
2017-08-19 20:02:43 +00:00
|
|
|
*
|
|
|
|
* +--------+--------+--------+--------+--------+--------+--------+--------+
|
|
|
|
* | BoardID (1 byte) |
|
|
|
|
* +--------+--------+--------+--------+--------+--------+--------+--------+
|
|
|
|
*
|
2018-03-13 08:28:15 +00:00
|
|
|
* Header version 0 (legacy):
|
|
|
|
* +--------+--------+--------+--------+--------+--------+--------+--------+
|
|
|
|
* | Packet ID (1 byte) |
|
|
|
|
* +--------+--------+--------+--------+--------+--------+--------+--------+
|
|
|
|
* | Packet counter (LSB) |
|
|
|
|
* | (2 bytes) |
|
|
|
|
* +--------+--------+--------+--------+--------+--------+--------+--------+
|
|
|
|
* | Unused |
|
|
|
|
* | (2 bytes) |
|
|
|
|
* +--------+--------+--------+--------+--------+--------+--------+--------+
|
|
|
|
* | Length of payload (1 byte) |
|
|
|
|
* +--------+--------+--------+--------+--------+--------+--------+--------+
|
|
|
|
*
|
|
|
|
* Header version 1:
|
2017-08-19 20:02:43 +00:00
|
|
|
* +--------+--------+--------+--------+--------+--------+--------+--------+
|
|
|
|
* | Length of header (1 byte) |
|
|
|
|
* +--------+--------+--------+--------+--------+--------+--------+--------+
|
|
|
|
* | Length of payload (1 byte) |
|
|
|
|
* +--------+--------+--------+--------+--------+--------+--------+--------+
|
|
|
|
* | Protocol version (1 byte) |
|
|
|
|
* +--------+--------+--------+--------+--------+--------+--------+--------+
|
|
|
|
* | Packet counter (LSB) |
|
|
|
|
* | (2 bytes) |
|
|
|
|
* +--------+--------+--------+--------+--------+--------+--------+--------+
|
|
|
|
* | Packet ID (1 byte) |
|
|
|
|
* +--------+--------+--------+--------+--------+--------+--------+--------+
|
|
|
|
*
|
2020-04-10 14:44:13 +00:00
|
|
|
* Header version > 1:
|
2018-03-13 08:28:15 +00:00
|
|
|
* +--------+--------+--------+--------+--------+--------+--------+--------+
|
|
|
|
* | Length of payload (little endian) |
|
|
|
|
* | (2 bytes) |
|
|
|
|
* +--------+--------+--------+--------+--------+--------+--------+--------+
|
|
|
|
* | Protocol version (1 byte) |
|
|
|
|
* +--------+--------+--------+--------+--------+--------+--------+--------+
|
|
|
|
* | Packet counter (little endian) |
|
|
|
|
* | (2 bytes) |
|
|
|
|
* +--------+--------+--------+--------+--------+--------+--------+--------+
|
|
|
|
* | Packet ID (1 byte) |
|
|
|
|
* +--------+--------+--------+--------+--------+--------+--------+--------+
|
|
|
|
*
|
2017-08-19 20:02:43 +00:00
|
|
|
* Packet ID:
|
|
|
|
* 0x00 = REQ_FOLLOW
|
2020-04-10 14:44:13 +00:00
|
|
|
* Host tells the Sniffer to scan for Advertising from a specific
|
|
|
|
* address and follow all communication it has with other devices.
|
|
|
|
*
|
2017-08-19 20:02:43 +00:00
|
|
|
* 0x01 = EVENT_FOLLOW
|
|
|
|
* Sniffer tells the Host that it has entered the FOLLOW state.
|
2020-04-10 14:44:13 +00:00
|
|
|
*
|
|
|
|
* 0x02 = EVENT_PACKET_ADVERTISING
|
|
|
|
* Sniffer tells the Host that it has received an advertising physical
|
|
|
|
* channel PDU.
|
|
|
|
*
|
2017-08-19 20:02:43 +00:00
|
|
|
* 0x05 = EVENT_CONNECT
|
|
|
|
* Sniffer tells the Host that someone has connected to the unit we
|
|
|
|
* are following.
|
2020-04-10 14:44:13 +00:00
|
|
|
*
|
|
|
|
* 0x06 = EVENT_PACKET_DATA
|
|
|
|
* Protocol version < 3:
|
|
|
|
* Sniffer tells the host that it has received a packet on any physical
|
|
|
|
* channel.
|
|
|
|
* Access address == 0x8e89bed6 Advertising physical channel PDU
|
|
|
|
* Access address != 0x8e89bed6 Data physical channel PDU
|
|
|
|
* Protocol version 3:
|
|
|
|
* Sniffer tells the Host that it has received a data physical
|
|
|
|
* channel PDU.
|
|
|
|
*
|
2017-08-19 20:02:43 +00:00
|
|
|
* 0x07 = REQ_SCAN_CONT
|
2020-04-10 14:44:13 +00:00
|
|
|
* Host tells the Sniffer to scan continuously for any advertising
|
|
|
|
* physical channel PDUs and send all packets received.
|
|
|
|
*
|
2017-08-19 20:02:43 +00:00
|
|
|
* 0x09 = EVENT_DISCONNECT
|
|
|
|
* Sniffer tells the Host that the connected address we were following
|
|
|
|
* has received a disconnect packet.
|
2020-04-10 14:44:13 +00:00
|
|
|
*
|
2017-08-19 20:02:43 +00:00
|
|
|
* 0x0C = SET_TEMPORARY_KEY
|
2020-04-10 14:44:13 +00:00
|
|
|
* Specify a temporary key (TK) to use on encryption.
|
|
|
|
* Only used for Legacy OOB and Legacy passkey pairing.
|
|
|
|
*
|
2017-08-19 20:02:43 +00:00
|
|
|
* 0x0D = PING_REQ
|
2020-04-10 14:44:13 +00:00
|
|
|
*
|
2017-08-19 20:02:43 +00:00
|
|
|
* 0x0E = PING_RESP
|
2020-04-10 14:44:13 +00:00
|
|
|
*
|
2017-08-19 20:02:43 +00:00
|
|
|
* 0x13 = SWITCH_BAUD_RATE_REQ
|
2020-04-10 14:44:13 +00:00
|
|
|
*
|
2017-08-19 20:02:43 +00:00
|
|
|
* 0x14 = SWITCH_BAUD_RATE_RESP
|
2020-04-10 14:44:13 +00:00
|
|
|
*
|
2017-08-19 20:02:43 +00:00
|
|
|
* 0x17 = SET_ADV_CHANNEL_HOP_SEQ
|
|
|
|
* Host tells the Sniffer which order to cycle through the channels
|
|
|
|
* when following an advertiser.
|
2020-04-10 14:44:13 +00:00
|
|
|
*
|
2017-08-19 20:02:43 +00:00
|
|
|
* 0xFE = GO_IDLE
|
|
|
|
* Host tell the Sniffer to stop sending UART traffic and listen for
|
|
|
|
* new commands.
|
|
|
|
*
|
|
|
|
* Payloads:
|
|
|
|
*
|
2020-04-10 14:44:13 +00:00
|
|
|
* Protocol version < 3:
|
|
|
|
* EVENT_PACKET (ID 0x06)
|
|
|
|
*
|
|
|
|
* Protocol version 3:
|
|
|
|
* EVENT_PACKET_ADVERTISING (ID 0x02)
|
|
|
|
* EVENT_PACKET_DATA (ID 0x06)
|
2017-08-19 20:02:43 +00:00
|
|
|
* +--------+--------+--------+--------+--------+--------+--------+--------+
|
|
|
|
* | Length of payload data (1 byte) |
|
|
|
|
* +--------+--------+--------+--------+--------+--------+--------+--------+
|
|
|
|
* | Flags (1 byte) |
|
|
|
|
* +--------+--------+--------+--------+--------+--------+--------+--------+
|
|
|
|
* | Channel (1 byte) |
|
|
|
|
* +--------+--------+--------+--------+--------+--------+--------+--------+
|
2020-04-04 10:53:49 +00:00
|
|
|
* | RSSISample (dBm) (1 byte) |
|
2017-08-19 20:02:43 +00:00
|
|
|
* +--------+--------+--------+--------+--------+--------+--------+--------+
|
|
|
|
* | Event counter |
|
|
|
|
* | (2 bytes) |
|
|
|
|
* +--------+--------+--------+--------+--------+--------+--------+--------+
|
2020-04-10 14:44:13 +00:00
|
|
|
* | Protocol version < 3: Delta time (us end to start) |
|
|
|
|
* | (4 bytes) |
|
|
|
|
* | Protocol version 3: Firmware Timestamp (us) |
|
|
|
|
* | (4 bytes) |
|
2017-08-19 20:02:43 +00:00
|
|
|
* +--------+--------+--------+--------+--------+--------+--------+--------+
|
|
|
|
*
|
|
|
|
* +--------+--------+--------+--------+--------+--------+--------+--------+
|
|
|
|
* | |
|
2020-04-04 10:55:49 +00:00
|
|
|
* | Bluetooth Low Energy Link Layer Packet (excluding preamble) |
|
2017-08-19 20:02:43 +00:00
|
|
|
* | ... |
|
|
|
|
* | |
|
|
|
|
* +--------+--------+--------+--------+--------+--------+--------+--------+
|
|
|
|
*
|
2020-04-10 14:44:13 +00:00
|
|
|
* Flags EVENT_PACKET_ADVERTISING (0x02)
|
|
|
|
* 0000000x = CRC (0 = Incorrect, 1 = OK)
|
|
|
|
* 000000x0 = RFU
|
|
|
|
* 00000x00 = RFU
|
|
|
|
* 00000xx0 = AUX_TYPE (channel < 37: 0 = AUX_ADV_IND, 1 = AUX_CHAIN_IND,
|
|
|
|
* 2 = AUX_SYNC_IND, 3 = AUX_SCAN_RSP)
|
|
|
|
* 0000x000 = RFU
|
|
|
|
* 0xxx0000 = PHY (0 = 1M, 1 = 2M, 2 = Coded, rest unused)
|
|
|
|
* x0000000 = RFU
|
|
|
|
*
|
|
|
|
* Flags EVENT_PACKET_DATA (0x06)
|
2018-03-13 08:28:15 +00:00
|
|
|
* 0000000x = CRC (0 = Incorrect, 1 = OK)
|
|
|
|
* 000000x0 = Direction (0 = Slave -> Master, 1 = Master -> Slave)
|
|
|
|
* 00000x00 = Encrypted (0 = No, 1 = Yes)
|
|
|
|
* 0000x000 = MIC (0 = Incorrect, 1 = OK)
|
|
|
|
* 0xxx0000 = PHY (0 = 1M, 1 = 2M, 2 = Coded, rest unused)
|
|
|
|
* x0000000 = RFU
|
2017-08-19 20:02:43 +00:00
|
|
|
*
|
|
|
|
* Channel:
|
|
|
|
* The channel index being used.
|
|
|
|
*
|
2020-04-04 10:53:49 +00:00
|
|
|
* RSSIsample:
|
|
|
|
* RSSI sample raw value. The value of this register is read as a
|
|
|
|
* positive value while the actual received signal strength is a
|
|
|
|
* negative value. Actual received signal strength is therefore
|
|
|
|
* as follows: rssi = -RSSISAMPLE dBm
|
|
|
|
*
|
2017-08-19 20:02:43 +00:00
|
|
|
* Delta time:
|
2020-04-10 14:44:13 +00:00
|
|
|
* This is the time in microseconds from the end of the previous received
|
2017-08-19 20:02:43 +00:00
|
|
|
* packet to the beginning of this packet.
|
2020-04-10 14:44:13 +00:00
|
|
|
*
|
|
|
|
* Firmware timestamp:
|
|
|
|
* Timestamp of the start of the received packet captured by the firmware
|
|
|
|
* timer with microsecond resolution.
|
2017-08-19 20:02:43 +00:00
|
|
|
*/
|
|
|
|
|
2016-07-21 07:55:03 +00:00
|
|
|
#include "config.h"
|
|
|
|
|
|
|
|
#include <epan/packet.h>
|
|
|
|
#include <epan/expert.h>
|
2017-08-24 07:51:04 +00:00
|
|
|
#include <epan/proto_data.h>
|
|
|
|
|
|
|
|
#include <wsutil/utf8_entities.h>
|
2017-08-26 09:21:52 +00:00
|
|
|
#include <wiretap/wtap.h>
|
2016-07-21 07:55:03 +00:00
|
|
|
|
2016-08-02 11:54:46 +00:00
|
|
|
#include "packet-btle.h"
|
|
|
|
|
2016-07-21 07:55:03 +00:00
|
|
|
/* Size of various UART Packet header fields */
|
2018-03-13 08:28:15 +00:00
|
|
|
#define UART_HEADER_LEN 6
|
|
|
|
#define EVENT_PACKET_LEN 10
|
2016-12-14 09:17:42 +00:00
|
|
|
|
2018-03-13 08:28:15 +00:00
|
|
|
#define US_PER_BYTE_1M_PHY 8
|
|
|
|
#define US_PER_BYTE_2M_PHY 4
|
2016-12-14 09:17:42 +00:00
|
|
|
|
2020-04-11 17:10:39 +00:00
|
|
|
#define US_PER_BYTE_CODED_PHY_S8 64
|
|
|
|
#define US_PER_BYTE_CODED_PHY_S2 16
|
|
|
|
|
2018-03-13 08:28:15 +00:00
|
|
|
#define PREAMBLE_LEN_1M_PHY 1
|
|
|
|
#define PREAMBLE_LEN_2M_PHY 2
|
2016-07-21 07:55:03 +00:00
|
|
|
|
2020-04-11 17:10:39 +00:00
|
|
|
/* Preamble + Access Address + CI + TERM1 */
|
|
|
|
#define FEC1_BLOCK_S8_US (80 + 256 + 16 + 24)
|
|
|
|
#define TERM2_S8_US 24
|
|
|
|
#define TERM2_S2_US 6
|
|
|
|
|
2016-07-21 07:55:03 +00:00
|
|
|
void proto_reg_handoff_nordic_ble(void);
|
|
|
|
void proto_register_nordic_ble(void);
|
|
|
|
|
|
|
|
/* Initialize the protocol and registered fields */
|
|
|
|
static int proto_nordic_ble = -1;
|
|
|
|
|
|
|
|
/* Initialize the subtree pointers */
|
|
|
|
static gint ett_nordic_ble = -1;
|
2016-12-14 09:17:42 +00:00
|
|
|
static gint ett_packet_header = -1;
|
2016-07-21 07:55:03 +00:00
|
|
|
static gint ett_flags = -1;
|
|
|
|
|
|
|
|
static int hf_nordic_ble_board_id = -1;
|
2016-12-14 19:27:54 +00:00
|
|
|
static int hf_nordic_ble_legacy_marker = -1;
|
2016-12-14 09:17:42 +00:00
|
|
|
static int hf_nordic_ble_header = -1;
|
2016-07-21 07:55:03 +00:00
|
|
|
static int hf_nordic_ble_header_length = -1;
|
|
|
|
static int hf_nordic_ble_payload_length = -1;
|
2016-12-14 09:17:42 +00:00
|
|
|
static int hf_nordic_ble_protover = -1;
|
2016-07-21 07:55:03 +00:00
|
|
|
static int hf_nordic_ble_packet_counter = -1;
|
2016-12-14 09:17:42 +00:00
|
|
|
static int hf_nordic_ble_packet_id = -1;
|
|
|
|
static int hf_nordic_ble_packet_length = -1;
|
2016-07-21 07:55:03 +00:00
|
|
|
static int hf_nordic_ble_flags = -1;
|
|
|
|
static int hf_nordic_ble_crcok = -1;
|
|
|
|
static int hf_nordic_ble_encrypted = -1;
|
|
|
|
static int hf_nordic_ble_micok = -1;
|
2020-07-05 21:16:21 +00:00
|
|
|
static int hf_nordic_ble_mic_not_relevant = -1;
|
2020-04-10 14:44:13 +00:00
|
|
|
static int hf_nordic_ble_aux_type = -1;
|
|
|
|
static int hf_nordic_ble_flag_reserved1 = -1;
|
|
|
|
static int hf_nordic_ble_flag_reserved2 = -1;
|
|
|
|
static int hf_nordic_ble_flag_reserved3 = -1;
|
|
|
|
static int hf_nordic_ble_flag_reserved7 = -1;
|
2018-03-13 08:28:15 +00:00
|
|
|
static int hf_nordic_ble_le_phy = -1;
|
2016-07-21 07:55:03 +00:00
|
|
|
static int hf_nordic_ble_direction = -1;
|
|
|
|
static int hf_nordic_ble_channel = -1;
|
|
|
|
static int hf_nordic_ble_rssi = -1;
|
|
|
|
static int hf_nordic_ble_event_counter = -1;
|
2020-04-10 14:44:13 +00:00
|
|
|
static int hf_nordic_ble_time = -1;
|
2016-07-21 07:55:03 +00:00
|
|
|
static int hf_nordic_ble_delta_time = -1;
|
|
|
|
static int hf_nordic_ble_delta_time_ss = -1;
|
2020-04-10 14:44:13 +00:00
|
|
|
static int hf_nordic_ble_packet_time = -1;
|
2016-07-21 07:55:03 +00:00
|
|
|
|
|
|
|
static expert_field ei_nordic_ble_bad_crc = EI_INIT;
|
|
|
|
static expert_field ei_nordic_ble_bad_mic = EI_INIT;
|
|
|
|
static expert_field ei_nordic_ble_bad_length = EI_INIT;
|
2018-03-13 08:28:15 +00:00
|
|
|
static expert_field ei_nordic_ble_unknown_version = EI_INIT;
|
2016-07-21 07:55:03 +00:00
|
|
|
|
|
|
|
static const true_false_string direction_tfs =
|
|
|
|
{
|
|
|
|
"Master -> Slave",
|
|
|
|
"Slave -> Master"
|
|
|
|
};
|
2016-12-14 09:17:42 +00:00
|
|
|
|
2016-07-21 07:55:03 +00:00
|
|
|
static const true_false_string ok_incorrect =
|
|
|
|
{
|
|
|
|
"OK",
|
|
|
|
"Incorrect"
|
|
|
|
};
|
|
|
|
|
2018-03-13 08:28:15 +00:00
|
|
|
static const value_string le_phys[] =
|
|
|
|
{
|
|
|
|
{ 0, "LE 1M" },
|
|
|
|
{ 1, "LE 2M" },
|
|
|
|
{ 2, "LE Coded" },
|
|
|
|
{ 3, "Reserved" },
|
|
|
|
{ 4, "Reserved" },
|
|
|
|
{ 5, "Reserved" },
|
|
|
|
{ 6, "Reserved" },
|
|
|
|
{ 7, "Reserved" },
|
|
|
|
{ 0, NULL }
|
|
|
|
};
|
|
|
|
|
2020-04-11 17:10:39 +00:00
|
|
|
#define CI_S8 0
|
|
|
|
#define CI_S2 1
|
|
|
|
|
2020-04-10 14:44:13 +00:00
|
|
|
static const value_string le_aux_ext_adv[] = {
|
|
|
|
{ 0, "AUX_ADV_IND" },
|
|
|
|
{ 1, "AUX_CHAIN_IND" },
|
|
|
|
{ 2, "AUX_SYNC_IND" },
|
|
|
|
{ 3, "AUX_SCAN_RSP" },
|
|
|
|
{ 0, NULL }
|
|
|
|
};
|
|
|
|
|
2018-03-13 08:28:15 +00:00
|
|
|
typedef struct {
|
|
|
|
guint8 protover;
|
|
|
|
guint8 phy;
|
|
|
|
gboolean bad_length;
|
|
|
|
guint16 payload_length;
|
|
|
|
guint16 event_packet_length;
|
|
|
|
} nordic_ble_context_t;
|
|
|
|
|
2016-07-21 07:55:03 +00:00
|
|
|
/* next dissector */
|
|
|
|
static dissector_handle_t btle_dissector_handle = NULL;
|
|
|
|
static dissector_handle_t debug_handle = NULL;
|
|
|
|
|
2016-12-14 09:17:42 +00:00
|
|
|
static gint
|
2018-03-13 08:28:15 +00:00
|
|
|
dissect_lengths(tvbuff_t *tvb, gint offset, packet_info *pinfo, proto_tree *tree, nordic_ble_context_t *nordic_ble_context)
|
2016-07-21 07:55:03 +00:00
|
|
|
{
|
2018-03-13 08:28:15 +00:00
|
|
|
guint32 hlen, plen;
|
2016-07-21 07:55:03 +00:00
|
|
|
proto_item* item;
|
|
|
|
|
2018-03-13 08:28:15 +00:00
|
|
|
switch (nordic_ble_context->protover) {
|
|
|
|
case 0: /* Legacy version */
|
|
|
|
hlen = 2 + UART_HEADER_LEN; /* 2 bytes legacy marker + UART header */
|
|
|
|
item = proto_tree_add_item_ret_uint(tree, hf_nordic_ble_payload_length, tvb, offset, 1, ENC_NA, &plen);
|
2016-12-14 19:27:54 +00:00
|
|
|
offset += 1;
|
2018-03-13 08:28:15 +00:00
|
|
|
break;
|
2016-07-21 07:55:03 +00:00
|
|
|
|
2018-03-13 08:28:15 +00:00
|
|
|
case 1:
|
|
|
|
proto_tree_add_item_ret_uint(tree, hf_nordic_ble_header_length, tvb, offset, 1, ENC_NA, &hlen);
|
|
|
|
hlen += 1; /* Add one byte for board id */
|
|
|
|
offset += 1;
|
2016-07-21 07:55:03 +00:00
|
|
|
|
2018-03-13 08:28:15 +00:00
|
|
|
item = proto_tree_add_item_ret_uint(tree, hf_nordic_ble_payload_length, tvb, offset, 1, ENC_NA, &plen);
|
|
|
|
offset += 1;
|
|
|
|
break;
|
|
|
|
|
2020-04-10 14:44:13 +00:00
|
|
|
default: /* Starting from version 2 */
|
2018-03-13 08:28:15 +00:00
|
|
|
hlen = 1 + UART_HEADER_LEN; /* Board ID + UART header */
|
|
|
|
item = proto_tree_add_item_ret_uint(tree, hf_nordic_ble_payload_length, tvb, offset, 2, ENC_LITTLE_ENDIAN, &plen);
|
|
|
|
offset += 2;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
if ((hlen + plen) != tvb_captured_length(tvb)) {
|
2016-07-21 07:55:03 +00:00
|
|
|
expert_add_info(pinfo, item, &ei_nordic_ble_bad_length);
|
2018-03-13 08:28:15 +00:00
|
|
|
nordic_ble_context->bad_length = TRUE;
|
2016-07-21 07:55:03 +00:00
|
|
|
}
|
|
|
|
|
2018-03-13 08:28:15 +00:00
|
|
|
nordic_ble_context->payload_length = plen;
|
2016-12-14 19:27:54 +00:00
|
|
|
|
2016-12-14 09:17:42 +00:00
|
|
|
return offset;
|
2016-07-21 07:55:03 +00:00
|
|
|
}
|
|
|
|
|
2016-12-14 09:17:42 +00:00
|
|
|
static gint
|
2018-03-13 08:28:15 +00:00
|
|
|
dissect_flags(tvbuff_t *tvb, gint offset, packet_info *pinfo, proto_tree *tree, nordic_ble_context_t *nordic_ble_context, btle_context_t *context)
|
2016-07-21 07:55:03 +00:00
|
|
|
{
|
2020-04-10 14:44:13 +00:00
|
|
|
guint8 flags, channel;
|
|
|
|
gboolean dir;
|
2016-08-09 19:59:30 +00:00
|
|
|
proto_item *flags_item, *item;
|
|
|
|
proto_tree *flags_tree;
|
2016-07-21 07:55:03 +00:00
|
|
|
|
2016-12-14 09:17:42 +00:00
|
|
|
flags = tvb_get_guint8(tvb, offset);
|
2020-04-10 14:44:13 +00:00
|
|
|
channel = tvb_get_guint8(tvb, offset + 1);
|
|
|
|
|
|
|
|
if (nordic_ble_context->protover < 3) {
|
|
|
|
guint32 access_address;
|
|
|
|
|
|
|
|
access_address = tvb_get_letohl(tvb, offset + nordic_ble_context->event_packet_length - 1);
|
|
|
|
context->pdu_type = access_address == ACCESS_ADDRESS_ADVERTISING ? BTLE_PDU_TYPE_ADVERTISING : BTLE_PDU_TYPE_DATA;
|
|
|
|
}
|
|
|
|
|
|
|
|
context->crc_checked_at_capture = 1;
|
2016-08-02 11:54:46 +00:00
|
|
|
context->crc_valid_at_capture = !!(flags & 1);
|
2020-04-10 14:44:13 +00:00
|
|
|
|
|
|
|
if (context->pdu_type == BTLE_PDU_TYPE_DATA) {
|
|
|
|
dir = !!(flags & 2);
|
|
|
|
context->mic_checked_at_capture = !!(flags & 4);
|
|
|
|
if (context->mic_checked_at_capture) {
|
|
|
|
context->mic_valid_at_capture = !!(flags & 8);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2018-03-13 08:28:15 +00:00
|
|
|
nordic_ble_context->phy = (flags >> 4) & 7;
|
2020-11-21 10:08:50 +00:00
|
|
|
context->phy = nordic_ble_context->phy;
|
2016-07-21 07:55:03 +00:00
|
|
|
|
2020-04-10 14:44:13 +00:00
|
|
|
if (context->pdu_type == BTLE_PDU_TYPE_DATA) {
|
|
|
|
if (dir) {
|
|
|
|
set_address(&pinfo->src, AT_STRINGZ, 7, "Master");
|
|
|
|
set_address(&pinfo->dst, AT_STRINGZ, 6, "Slave");
|
|
|
|
context->direction = BTLE_DIR_MASTER_SLAVE;
|
|
|
|
pinfo->p2p_dir = P2P_DIR_SENT;
|
|
|
|
} else {
|
|
|
|
set_address(&pinfo->src, AT_STRINGZ, 6, "Slave");
|
|
|
|
set_address(&pinfo->dst, AT_STRINGZ, 7, "Master");
|
|
|
|
context->direction = BTLE_DIR_SLAVE_MASTER;
|
|
|
|
pinfo->p2p_dir = P2P_DIR_RECV;
|
|
|
|
}
|
2016-07-21 07:55:03 +00:00
|
|
|
}
|
|
|
|
|
2016-12-14 09:17:42 +00:00
|
|
|
flags_item = proto_tree_add_item(tree, hf_nordic_ble_flags, tvb, offset, 1, ENC_NA);
|
2016-08-09 19:59:30 +00:00
|
|
|
flags_tree = proto_item_add_subtree(flags_item, ett_flags);
|
2018-03-13 08:28:15 +00:00
|
|
|
item = proto_tree_add_item(flags_tree, hf_nordic_ble_crcok, tvb, offset, 1, ENC_NA);
|
|
|
|
if (!context->crc_valid_at_capture) {
|
|
|
|
/* CRC is bad */
|
|
|
|
expert_add_info(pinfo, item, &ei_nordic_ble_bad_crc);
|
|
|
|
}
|
2020-04-10 14:44:13 +00:00
|
|
|
|
|
|
|
if (context->pdu_type == BTLE_PDU_TYPE_DATA) {
|
|
|
|
proto_tree_add_item(flags_tree, hf_nordic_ble_direction, tvb, offset, 1, ENC_NA);
|
|
|
|
proto_tree_add_item(flags_tree, hf_nordic_ble_encrypted, tvb, offset, 1, ENC_NA);
|
|
|
|
if (context->mic_checked_at_capture) {
|
|
|
|
item = proto_tree_add_item(flags_tree, hf_nordic_ble_micok, tvb, offset, 1, ENC_NA);
|
|
|
|
if (!context->mic_valid_at_capture) {
|
|
|
|
/* MIC is bad */
|
|
|
|
expert_add_info(pinfo, item, &ei_nordic_ble_bad_mic);
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
proto_tree_add_item(flags_tree, hf_nordic_ble_mic_not_relevant, tvb, offset, 1, ENC_NA);
|
2016-07-21 07:55:03 +00:00
|
|
|
}
|
2018-03-13 08:28:15 +00:00
|
|
|
} else {
|
2020-04-10 14:44:13 +00:00
|
|
|
if (channel < 37) {
|
|
|
|
guint32 aux_pdu_type;
|
|
|
|
|
|
|
|
proto_tree_add_item_ret_uint(flags_tree, hf_nordic_ble_aux_type, tvb, offset, 1, ENC_NA, &aux_pdu_type);
|
|
|
|
context->aux_pdu_type = aux_pdu_type;
|
|
|
|
context->aux_pdu_type_valid = TRUE;
|
|
|
|
} else {
|
|
|
|
proto_tree_add_item(flags_tree, hf_nordic_ble_flag_reserved1, tvb, offset, 1, ENC_NA);
|
|
|
|
proto_tree_add_item(flags_tree, hf_nordic_ble_flag_reserved2, tvb, offset, 1, ENC_NA);
|
|
|
|
}
|
|
|
|
proto_tree_add_item(flags_tree, hf_nordic_ble_flag_reserved3, tvb, offset, 1, ENC_NA);
|
2016-07-21 07:55:03 +00:00
|
|
|
}
|
2020-04-10 14:44:13 +00:00
|
|
|
|
2018-03-13 08:28:15 +00:00
|
|
|
proto_tree_add_item(flags_tree, hf_nordic_ble_le_phy, tvb, offset, 1, ENC_NA);
|
2020-04-10 14:44:13 +00:00
|
|
|
proto_tree_add_item(flags_tree, hf_nordic_ble_flag_reserved7, tvb, offset, 1, ENC_NA);
|
|
|
|
|
2016-12-14 09:17:42 +00:00
|
|
|
offset++;
|
2016-07-21 07:55:03 +00:00
|
|
|
|
2016-12-14 09:17:42 +00:00
|
|
|
return offset;
|
2016-07-21 07:55:03 +00:00
|
|
|
}
|
|
|
|
|
2020-04-11 17:10:39 +00:00
|
|
|
static guint16 packet_time_get(nordic_ble_context_t *nordic_ble_context, guint8 ci)
|
2020-04-10 14:44:13 +00:00
|
|
|
{
|
|
|
|
/* Calculate packet time according to this packets PHY */
|
|
|
|
guint16 ble_payload_length = nordic_ble_context->payload_length - nordic_ble_context->event_packet_length;
|
|
|
|
|
|
|
|
switch (nordic_ble_context->phy) {
|
|
|
|
case LE_1M_PHY:
|
|
|
|
return US_PER_BYTE_1M_PHY * (PREAMBLE_LEN_1M_PHY + ble_payload_length);
|
|
|
|
case LE_2M_PHY:
|
|
|
|
return US_PER_BYTE_2M_PHY * (PREAMBLE_LEN_2M_PHY + ble_payload_length);
|
2020-04-11 17:10:39 +00:00
|
|
|
case LE_CODED_PHY:
|
|
|
|
{
|
|
|
|
/* Subtract Access address and CI */
|
|
|
|
guint16 fec2_block_len = ble_payload_length - 4 - 1;
|
|
|
|
|
|
|
|
switch (ci) {
|
|
|
|
case CI_S8:
|
|
|
|
return FEC1_BLOCK_S8_US + fec2_block_len * US_PER_BYTE_CODED_PHY_S8 + TERM2_S8_US;
|
|
|
|
case CI_S2:
|
|
|
|
return FEC1_BLOCK_S8_US + fec2_block_len * US_PER_BYTE_CODED_PHY_S2 + TERM2_S2_US;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
/* Fallthrough */
|
2020-04-10 14:44:13 +00:00
|
|
|
default:
|
|
|
|
return 0; /* Unknown */
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2021-06-25 11:02:52 +00:00
|
|
|
typedef struct
|
|
|
|
{
|
|
|
|
guint32 packet_start_time;
|
|
|
|
guint32 packet_end_time;
|
|
|
|
} packet_times_t;
|
|
|
|
|
|
|
|
typedef struct {
|
|
|
|
gboolean first_frame_seen;
|
|
|
|
/* Time information about previous packet times to calculate delta times */
|
|
|
|
guint32 packet_time;
|
|
|
|
guint32 packet_start_time;
|
|
|
|
guint32 packet_end_time;
|
|
|
|
} packet_time_context_t;
|
|
|
|
|
|
|
|
static wmem_tree_t *packet_time_context_tree;
|
|
|
|
|
|
|
|
static packet_time_context_t *packet_times_get(packet_info *pinfo)
|
|
|
|
{
|
|
|
|
guint32 interface_id = (pinfo->rec->presence_flags & WTAP_HAS_INTERFACE_ID) ? pinfo->rec->rec_header.packet_header.interface_id: HCI_INTERFACE_DEFAULT;
|
|
|
|
wmem_tree_t *wmem_tree;
|
|
|
|
wmem_tree_key_t keys[2];
|
|
|
|
|
|
|
|
keys[0].length = 1;
|
|
|
|
keys[0].key = &interface_id;
|
|
|
|
keys[1].length = 0;
|
|
|
|
keys[1].key = NULL;
|
|
|
|
|
|
|
|
wmem_tree = (wmem_tree_t *) wmem_tree_lookup32_array(packet_time_context_tree, keys);
|
|
|
|
if (wmem_tree) {
|
|
|
|
return (packet_time_context_t *) wmem_tree_lookup32_le(wmem_tree, 0);
|
|
|
|
}
|
|
|
|
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
static packet_time_context_t *packet_times_insert(packet_info *pinfo)
|
|
|
|
{
|
|
|
|
guint32 interface_id = (pinfo->rec->presence_flags & WTAP_HAS_INTERFACE_ID) ? pinfo->rec->rec_header.packet_header.interface_id: HCI_INTERFACE_DEFAULT;
|
|
|
|
guint32 key = 0;
|
|
|
|
wmem_tree_key_t keys[3];
|
|
|
|
packet_time_context_t *packet_times;
|
|
|
|
|
|
|
|
keys[0].length = 1;
|
|
|
|
keys[0].key = &interface_id;
|
|
|
|
keys[1].length = 1;
|
|
|
|
keys[1].key = &key;
|
|
|
|
keys[2].length = 0;
|
|
|
|
keys[2].key = NULL;
|
|
|
|
packet_times = wmem_new0(wmem_file_scope(), packet_time_context_t);
|
|
|
|
wmem_tree_insert32_array(packet_time_context_tree, keys, packet_times);
|
|
|
|
|
|
|
|
return packet_times;
|
|
|
|
}
|
|
|
|
|
2016-12-14 09:17:42 +00:00
|
|
|
static gint
|
2018-03-13 08:28:15 +00:00
|
|
|
dissect_ble_delta_time(tvbuff_t *tvb, gint offset, packet_info *pinfo, proto_tree *tree, nordic_ble_context_t *nordic_ble_context)
|
2016-07-21 07:55:03 +00:00
|
|
|
{
|
2020-04-10 14:44:13 +00:00
|
|
|
guint32 delta_time, delta_time_ss, prev_packet_time, packet_time;
|
2017-08-24 07:51:04 +00:00
|
|
|
proto_item *pi;
|
2021-06-25 11:02:52 +00:00
|
|
|
packet_time_context_t *packet_times_context;
|
|
|
|
|
|
|
|
packet_times_context = packet_times_get(pinfo);
|
|
|
|
if (!packet_times_context) {
|
|
|
|
packet_times_context = packet_times_insert(pinfo);
|
|
|
|
}
|
2017-08-24 07:51:04 +00:00
|
|
|
|
2018-03-13 08:28:15 +00:00
|
|
|
/* end-to-start */
|
|
|
|
proto_tree_add_item_ret_uint(tree, hf_nordic_ble_delta_time, tvb, offset, 4, ENC_LITTLE_ENDIAN, &delta_time);
|
|
|
|
|
2018-12-27 02:26:24 +00:00
|
|
|
if (!pinfo->fd->visited) {
|
2018-03-13 08:28:15 +00:00
|
|
|
/* First time visiting this packet, store previous BLE packet time */
|
2021-06-25 11:02:52 +00:00
|
|
|
p_add_proto_data(wmem_file_scope(), pinfo, proto_nordic_ble, 0, GUINT_TO_POINTER(packet_times_context->packet_time));
|
|
|
|
prev_packet_time = packet_times_context->packet_time;
|
2017-08-24 07:51:04 +00:00
|
|
|
} else {
|
2018-03-13 08:28:15 +00:00
|
|
|
prev_packet_time = GPOINTER_TO_UINT(p_get_proto_data(wmem_file_scope(), pinfo, proto_nordic_ble, 0));
|
2017-08-24 07:51:04 +00:00
|
|
|
}
|
2016-07-21 07:55:03 +00:00
|
|
|
|
2021-06-25 11:02:52 +00:00
|
|
|
if (!packet_times_context->first_frame_seen) {
|
2018-03-13 08:28:15 +00:00
|
|
|
delta_time_ss = prev_packet_time + delta_time;
|
|
|
|
pi = proto_tree_add_uint(tree, hf_nordic_ble_delta_time_ss, tvb, offset, 4, delta_time_ss);
|
2019-04-03 21:32:30 +00:00
|
|
|
proto_item_set_generated(pi);
|
2018-03-13 08:28:15 +00:00
|
|
|
}
|
2016-07-21 07:55:03 +00:00
|
|
|
|
2020-04-11 17:10:39 +00:00
|
|
|
packet_time = packet_time_get(nordic_ble_context, 0 /* This version never supported Coded PHY */);
|
2020-04-10 14:44:13 +00:00
|
|
|
pi = proto_tree_add_uint(tree, hf_nordic_ble_packet_time, tvb, offset, 4, packet_time);
|
|
|
|
proto_item_set_generated(pi);
|
|
|
|
|
2021-06-25 11:02:52 +00:00
|
|
|
offset += 4;
|
|
|
|
|
2018-12-27 02:26:24 +00:00
|
|
|
if (!pinfo->fd->visited) {
|
2021-06-25 11:02:52 +00:00
|
|
|
packet_times_context->packet_time = packet_time;
|
|
|
|
packet_times_context->first_frame_seen = TRUE;
|
2020-04-10 14:44:13 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
return offset;
|
|
|
|
}
|
|
|
|
|
|
|
|
static gint
|
|
|
|
dissect_ble_timestamp(tvbuff_t *tvb, gint offset, packet_info *pinfo, proto_tree *tree, nordic_ble_context_t *nordic_ble_context)
|
|
|
|
{
|
|
|
|
guint32 delta_time, delta_time_ss, packet_time;
|
|
|
|
guint32 timestamp, last_packet_end_time, last_packet_start_time;
|
|
|
|
proto_item *item;
|
2021-06-25 11:02:52 +00:00
|
|
|
packet_time_context_t *packet_times_context;
|
|
|
|
|
|
|
|
packet_times_context = packet_times_get(pinfo);
|
|
|
|
if (!packet_times_context) {
|
|
|
|
packet_times_context = packet_times_insert(pinfo);
|
|
|
|
}
|
2020-04-10 14:44:13 +00:00
|
|
|
|
|
|
|
proto_tree_add_item_ret_uint(tree, hf_nordic_ble_time, tvb, offset, 4, ENC_LITTLE_ENDIAN, ×tamp);
|
|
|
|
|
|
|
|
if (!pinfo->fd->visited) {
|
|
|
|
packet_times_t *saved_packet_times = wmem_new0(wmem_file_scope(), packet_times_t);
|
2021-06-25 11:02:52 +00:00
|
|
|
|
|
|
|
saved_packet_times->packet_end_time = packet_times_context->packet_end_time;
|
|
|
|
saved_packet_times->packet_start_time = packet_times_context->packet_start_time;
|
2020-04-10 14:44:13 +00:00
|
|
|
p_add_proto_data(wmem_file_scope(), pinfo, proto_nordic_ble, 0, saved_packet_times);
|
|
|
|
|
|
|
|
/* First time visiting this packet, store previous BLE packet time */
|
2021-06-25 11:02:52 +00:00
|
|
|
last_packet_end_time = packet_times_context->packet_end_time;
|
|
|
|
last_packet_start_time = packet_times_context->packet_start_time;
|
2020-04-10 14:44:13 +00:00
|
|
|
} else {
|
|
|
|
packet_times_t* saved_packet_times = (packet_times_t *)p_get_proto_data(wmem_file_scope(), pinfo, proto_nordic_ble, 0);
|
|
|
|
|
|
|
|
last_packet_end_time = saved_packet_times->packet_end_time;
|
|
|
|
last_packet_start_time = saved_packet_times->packet_start_time;
|
|
|
|
}
|
|
|
|
|
2020-04-11 17:10:39 +00:00
|
|
|
guint8 ci = tvb_get_guint8(tvb, offset + 4 + 4);
|
|
|
|
packet_time = packet_time_get(nordic_ble_context, ci);
|
2020-04-10 14:44:13 +00:00
|
|
|
item = proto_tree_add_uint(tree, hf_nordic_ble_packet_time, tvb, offset, 4, packet_time);
|
|
|
|
proto_item_set_generated(item);
|
|
|
|
|
|
|
|
if (pinfo->num > 1) {
|
|
|
|
/* Calculated delta times are not valid for the first packet because we don't have the last packet times. */
|
|
|
|
delta_time = timestamp - last_packet_end_time;
|
|
|
|
item = proto_tree_add_uint(tree, hf_nordic_ble_delta_time, tvb, offset, 4, delta_time);
|
|
|
|
proto_item_set_generated(item);
|
|
|
|
|
|
|
|
delta_time_ss = timestamp - last_packet_start_time;
|
|
|
|
item = proto_tree_add_uint(tree, hf_nordic_ble_delta_time_ss, tvb, offset, 4, delta_time_ss);
|
|
|
|
proto_item_set_generated(item);
|
2017-08-24 07:51:04 +00:00
|
|
|
}
|
2016-07-21 07:55:03 +00:00
|
|
|
|
2020-04-10 14:44:13 +00:00
|
|
|
if (!pinfo->fd->visited) {
|
|
|
|
|
2021-06-25 11:02:52 +00:00
|
|
|
packet_times_context->packet_start_time = timestamp;
|
|
|
|
packet_times_context->packet_end_time = timestamp + packet_time;
|
|
|
|
packet_times_context->first_frame_seen = TRUE;
|
2020-04-10 14:44:13 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
offset += 4;
|
|
|
|
|
2016-12-14 09:17:42 +00:00
|
|
|
return offset;
|
|
|
|
}
|
2016-07-21 07:55:03 +00:00
|
|
|
|
2016-12-14 09:17:42 +00:00
|
|
|
static gint
|
2016-12-14 19:27:54 +00:00
|
|
|
dissect_packet_counter(tvbuff_t *tvb, gint offset, proto_item *item, proto_tree *tree)
|
|
|
|
{
|
|
|
|
proto_item_append_text(item, ", Packet counter: %u", tvb_get_guint16(tvb, offset, ENC_LITTLE_ENDIAN));
|
|
|
|
proto_tree_add_item(tree, hf_nordic_ble_packet_counter, tvb, offset, 2, ENC_LITTLE_ENDIAN);
|
|
|
|
offset += 2;
|
|
|
|
|
|
|
|
return offset;
|
|
|
|
}
|
|
|
|
|
|
|
|
static gint
|
2020-04-10 14:44:13 +00:00
|
|
|
dissect_packet_header(tvbuff_t *tvb, gint offset, packet_info *pinfo, proto_tree *tree, nordic_ble_context_t *nordic_ble_context, btle_context_t *context)
|
2016-07-21 07:55:03 +00:00
|
|
|
{
|
2016-12-14 09:17:42 +00:00
|
|
|
proto_item *ti;
|
|
|
|
proto_tree *header_tree;
|
2016-12-14 19:27:54 +00:00
|
|
|
gint start_offset = offset;
|
2016-07-21 07:55:03 +00:00
|
|
|
|
2016-12-14 19:27:54 +00:00
|
|
|
ti = proto_tree_add_item(tree, hf_nordic_ble_header, tvb, offset, -1, ENC_NA);
|
2016-12-14 09:17:42 +00:00
|
|
|
header_tree = proto_item_add_subtree(ti, ett_packet_header);
|
2018-03-13 08:28:15 +00:00
|
|
|
proto_item_append_text(ti, " Version: %u", nordic_ble_context->protover);
|
|
|
|
|
|
|
|
if (nordic_ble_context->protover == 0) {
|
|
|
|
proto_item *item = proto_tree_add_uint(header_tree, hf_nordic_ble_protover, tvb, 0, 0, 0);
|
2019-04-03 21:32:30 +00:00
|
|
|
proto_item_set_generated(item);
|
2016-07-21 07:55:03 +00:00
|
|
|
|
2016-12-14 19:27:54 +00:00
|
|
|
proto_tree_add_item(header_tree, hf_nordic_ble_packet_id, tvb, offset, 1, ENC_NA);
|
|
|
|
offset += 1;
|
2016-07-21 07:55:03 +00:00
|
|
|
|
2016-12-14 19:27:54 +00:00
|
|
|
offset = dissect_packet_counter(tvb, offset, ti, header_tree);
|
2016-07-21 07:55:03 +00:00
|
|
|
|
2016-12-14 19:27:54 +00:00
|
|
|
offset += 2; // Two unused bytes
|
|
|
|
}
|
2016-07-21 07:55:03 +00:00
|
|
|
|
2018-03-13 08:28:15 +00:00
|
|
|
offset = dissect_lengths(tvb, offset, pinfo, header_tree, nordic_ble_context);
|
2016-07-21 07:55:03 +00:00
|
|
|
|
2018-03-13 08:28:15 +00:00
|
|
|
if (nordic_ble_context->protover != 0) {
|
|
|
|
proto_item *item = proto_tree_add_item(header_tree, hf_nordic_ble_protover, tvb, offset, 1, ENC_NA);
|
2016-12-14 19:27:54 +00:00
|
|
|
offset += 1;
|
2020-04-10 14:44:13 +00:00
|
|
|
if (nordic_ble_context->protover > 3) {
|
2018-03-13 08:28:15 +00:00
|
|
|
expert_add_info(pinfo, item, &ei_nordic_ble_unknown_version);
|
|
|
|
}
|
2016-12-14 19:27:54 +00:00
|
|
|
|
|
|
|
offset = dissect_packet_counter(tvb, offset, ti, header_tree);
|
|
|
|
|
|
|
|
proto_tree_add_item(header_tree, hf_nordic_ble_packet_id, tvb, offset, 1, ENC_NA);
|
2020-04-10 14:44:13 +00:00
|
|
|
|
|
|
|
if (nordic_ble_context->protover > 2) {
|
|
|
|
guint8 id = tvb_get_guint8(tvb, offset);
|
|
|
|
|
|
|
|
context->pdu_type = id == 0x06 ? BTLE_PDU_TYPE_DATA :
|
|
|
|
id == 0x02 ? BTLE_PDU_TYPE_ADVERTISING :
|
|
|
|
BTLE_PDU_TYPE_UNKNOWN;
|
|
|
|
}
|
|
|
|
|
2016-12-14 19:27:54 +00:00
|
|
|
offset += 1;
|
|
|
|
}
|
|
|
|
|
|
|
|
proto_item_set_len(ti, offset - start_offset);
|
2016-07-21 07:55:03 +00:00
|
|
|
|
2016-12-14 09:17:42 +00:00
|
|
|
return offset;
|
|
|
|
}
|
|
|
|
|
|
|
|
static gint
|
2018-03-13 08:28:15 +00:00
|
|
|
dissect_packet(tvbuff_t *tvb, gint offset, packet_info *pinfo, proto_tree *tree, nordic_ble_context_t *nordic_ble_context, btle_context_t *context)
|
2016-07-21 07:55:03 +00:00
|
|
|
{
|
2016-12-14 09:17:42 +00:00
|
|
|
gint32 rssi;
|
2021-01-21 07:22:47 +00:00
|
|
|
guint32 channel, event_counter;
|
2016-07-21 07:55:03 +00:00
|
|
|
|
2018-03-13 08:28:15 +00:00
|
|
|
if (nordic_ble_context->protover == 0) {
|
|
|
|
// Event packet length is fixed for the legacy version
|
|
|
|
nordic_ble_context->event_packet_length = EVENT_PACKET_LEN;
|
|
|
|
} else {
|
|
|
|
guint32 plen;
|
|
|
|
proto_tree_add_item_ret_uint(tree, hf_nordic_ble_packet_length, tvb, offset, 1, ENC_NA, &plen);
|
|
|
|
nordic_ble_context->event_packet_length = plen;
|
2017-08-19 21:59:02 +00:00
|
|
|
offset += 1;
|
|
|
|
}
|
2017-08-19 20:02:43 +00:00
|
|
|
|
2018-03-13 08:28:15 +00:00
|
|
|
offset = dissect_flags(tvb, offset, pinfo, tree, nordic_ble_context, context);
|
2016-07-21 07:55:03 +00:00
|
|
|
|
2020-03-29 20:27:13 +00:00
|
|
|
proto_tree_add_item_ret_uint(tree, hf_nordic_ble_channel, tvb, offset, 1, ENC_NA, &channel);
|
2016-12-14 09:17:42 +00:00
|
|
|
offset += 1;
|
|
|
|
|
2020-03-29 20:27:13 +00:00
|
|
|
context->channel = channel;
|
|
|
|
|
2016-12-14 09:17:42 +00:00
|
|
|
rssi = (-1)*((gint32)tvb_get_guint8(tvb, offset));
|
|
|
|
proto_tree_add_int(tree, hf_nordic_ble_rssi, tvb, offset, 1, rssi);
|
|
|
|
offset += 1;
|
2016-07-21 07:55:03 +00:00
|
|
|
|
2021-01-21 07:22:47 +00:00
|
|
|
proto_tree_add_item_ret_uint(tree, hf_nordic_ble_event_counter, tvb, offset, 2, ENC_LITTLE_ENDIAN, &event_counter);
|
2016-12-14 09:17:42 +00:00
|
|
|
offset += 2;
|
2016-07-21 07:55:03 +00:00
|
|
|
|
2021-01-21 07:22:47 +00:00
|
|
|
context->event_counter = event_counter;
|
|
|
|
context->event_counter_valid = 1;
|
|
|
|
|
2020-04-10 14:44:13 +00:00
|
|
|
if (nordic_ble_context->protover < 3) {
|
|
|
|
offset = dissect_ble_delta_time(tvb, offset, pinfo, tree, nordic_ble_context);
|
|
|
|
} else {
|
|
|
|
offset = dissect_ble_timestamp(tvb, offset, pinfo, tree, nordic_ble_context);
|
|
|
|
}
|
2016-07-21 07:55:03 +00:00
|
|
|
|
2016-12-14 09:17:42 +00:00
|
|
|
return offset;
|
2016-07-21 07:55:03 +00:00
|
|
|
}
|
|
|
|
|
2016-12-14 09:17:42 +00:00
|
|
|
static gint
|
|
|
|
dissect_header(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, btle_context_t *context, gboolean *bad_length)
|
2016-07-21 07:55:03 +00:00
|
|
|
{
|
|
|
|
proto_item *ti;
|
|
|
|
proto_tree *nordic_ble_tree;
|
2016-12-14 09:17:42 +00:00
|
|
|
gint offset = 0;
|
2018-03-13 08:28:15 +00:00
|
|
|
nordic_ble_context_t nordic_ble_context;
|
|
|
|
|
|
|
|
memset(&nordic_ble_context, 0, sizeof(nordic_ble_context));
|
2016-07-21 07:55:03 +00:00
|
|
|
|
|
|
|
ti = proto_tree_add_item(tree, proto_nordic_ble, tvb, 0, -1, ENC_NA);
|
|
|
|
nordic_ble_tree = proto_item_add_subtree(ti, ett_nordic_ble);
|
|
|
|
|
2018-03-13 08:28:15 +00:00
|
|
|
if (tvb_get_guint16(tvb, 0, ENC_BIG_ENDIAN) == 0xBEEF) {
|
2016-12-14 19:27:54 +00:00
|
|
|
proto_tree_add_item(nordic_ble_tree, hf_nordic_ble_legacy_marker, tvb, 0, 2, ENC_BIG_ENDIAN);
|
|
|
|
offset += 2;
|
2018-03-13 08:28:15 +00:00
|
|
|
|
|
|
|
nordic_ble_context.protover = 0; /* Legacy Version */
|
2016-12-14 19:27:54 +00:00
|
|
|
} else {
|
|
|
|
proto_tree_add_item(nordic_ble_tree, hf_nordic_ble_board_id, tvb, 0, 1, ENC_NA);
|
|
|
|
offset += 1;
|
2018-03-13 08:28:15 +00:00
|
|
|
|
|
|
|
nordic_ble_context.protover = tvb_get_guint8(tvb, offset + 2);
|
2016-12-14 19:27:54 +00:00
|
|
|
}
|
2016-07-21 07:55:03 +00:00
|
|
|
|
2020-04-10 14:44:13 +00:00
|
|
|
offset = dissect_packet_header(tvb, offset, pinfo, nordic_ble_tree, &nordic_ble_context, context);
|
2018-03-13 08:28:15 +00:00
|
|
|
offset = dissect_packet(tvb, offset, pinfo, nordic_ble_tree, &nordic_ble_context, context);
|
2016-07-21 07:55:03 +00:00
|
|
|
|
2016-12-14 09:17:42 +00:00
|
|
|
proto_item_set_len(ti, offset);
|
2018-03-13 08:28:15 +00:00
|
|
|
*bad_length = nordic_ble_context.bad_length;
|
2016-07-21 07:55:03 +00:00
|
|
|
|
2016-12-14 09:17:42 +00:00
|
|
|
return offset;
|
2016-07-21 07:55:03 +00:00
|
|
|
}
|
|
|
|
|
2016-12-14 09:17:42 +00:00
|
|
|
/* Main entry point for sniffer */
|
2016-07-21 07:55:03 +00:00
|
|
|
static int
|
2016-08-02 11:54:46 +00:00
|
|
|
dissect_nordic_ble(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void *data _U_)
|
2016-07-21 07:55:03 +00:00
|
|
|
{
|
2016-08-02 11:54:46 +00:00
|
|
|
tvbuff_t *payload_tvb;
|
|
|
|
btle_context_t *context;
|
2016-12-14 09:17:42 +00:00
|
|
|
gint offset;
|
|
|
|
gboolean bad_length = FALSE;
|
2016-07-21 07:55:03 +00:00
|
|
|
|
2021-07-16 15:36:34 +00:00
|
|
|
context = wmem_new0(pinfo->pool, btle_context_t);
|
2016-07-21 07:55:03 +00:00
|
|
|
|
2016-12-14 09:17:42 +00:00
|
|
|
offset = dissect_header(tvb, pinfo, tree, context, &bad_length);
|
2017-01-10 06:18:49 +00:00
|
|
|
payload_tvb = tvb_new_subset_length_caplen(tvb, offset, -1, tvb_captured_length(tvb) - offset);
|
2016-07-21 07:55:03 +00:00
|
|
|
|
2016-12-14 09:17:42 +00:00
|
|
|
if (!bad_length) {
|
2016-08-02 11:54:46 +00:00
|
|
|
call_dissector_with_data(btle_dissector_handle, payload_tvb, pinfo, tree, context);
|
2016-07-21 07:55:03 +00:00
|
|
|
}
|
|
|
|
|
2016-08-02 11:54:46 +00:00
|
|
|
if ((context->mic_checked_at_capture) && (!context->mic_valid_at_capture)) {
|
2016-07-21 07:55:03 +00:00
|
|
|
col_add_str(pinfo->cinfo, COL_INFO, "Encrypted packet decrypted incorrectly (bad MIC)");
|
|
|
|
}
|
|
|
|
|
|
|
|
if (debug_handle) {
|
|
|
|
call_dissector(debug_handle, payload_tvb, pinfo, tree);
|
|
|
|
}
|
|
|
|
|
2016-12-14 09:17:42 +00:00
|
|
|
return offset;
|
2016-07-21 07:55:03 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
proto_register_nordic_ble(void)
|
|
|
|
{
|
|
|
|
static hf_register_info hf[] = {
|
2016-12-14 09:17:42 +00:00
|
|
|
{ &hf_nordic_ble_board_id,
|
|
|
|
{ "Board", "nordic_ble.board_id",
|
|
|
|
FT_UINT8, BASE_DEC, NULL, 0x0,
|
|
|
|
NULL, HFILL }
|
|
|
|
},
|
2016-12-14 19:27:54 +00:00
|
|
|
{ &hf_nordic_ble_legacy_marker,
|
|
|
|
{ "Legacy marker", "nordic_ble.legacy_marker",
|
|
|
|
FT_UINT16, BASE_HEX, NULL, 0x0,
|
|
|
|
NULL, HFILL }
|
|
|
|
},
|
2016-12-14 09:17:42 +00:00
|
|
|
{ &hf_nordic_ble_header,
|
|
|
|
{ "Header", "nordic_ble.header",
|
|
|
|
FT_NONE, BASE_NONE, NULL, 0x0,
|
|
|
|
NULL, HFILL }
|
|
|
|
},
|
|
|
|
{ &hf_nordic_ble_header_length,
|
|
|
|
{ "Length of header", "nordic_ble.hlen",
|
|
|
|
FT_UINT8, BASE_DEC, NULL, 0x0,
|
|
|
|
NULL, HFILL }
|
|
|
|
},
|
|
|
|
{ &hf_nordic_ble_payload_length,
|
|
|
|
{ "Length of payload", "nordic_ble.plen",
|
2018-03-13 08:28:15 +00:00
|
|
|
FT_UINT16, BASE_DEC, NULL, 0x0,
|
2016-12-14 09:17:42 +00:00
|
|
|
"Payload length", HFILL }
|
|
|
|
},
|
|
|
|
{ &hf_nordic_ble_protover,
|
|
|
|
{ "Protocol version", "nordic_ble.protover",
|
|
|
|
FT_UINT8, BASE_DEC, NULL, 0x0,
|
|
|
|
NULL, HFILL }
|
|
|
|
},
|
|
|
|
{ &hf_nordic_ble_packet_counter,
|
|
|
|
{ "Packet counter", "nordic_ble.packet_counter",
|
|
|
|
FT_UINT16, BASE_DEC, NULL, 0x0,
|
|
|
|
"Global packet counter for packets sent on UART", HFILL }
|
|
|
|
},
|
|
|
|
{ &hf_nordic_ble_packet_id,
|
|
|
|
{ "Packet ID", "nordic_ble.packet_id",
|
|
|
|
FT_UINT8, BASE_DEC, NULL, 0x0,
|
|
|
|
NULL, HFILL }
|
|
|
|
},
|
|
|
|
{ &hf_nordic_ble_packet_length,
|
|
|
|
{ "Length of packet", "nordic_ble.len",
|
2018-03-13 08:28:15 +00:00
|
|
|
FT_UINT16, BASE_DEC, NULL, 0x0,
|
2016-12-14 09:17:42 +00:00
|
|
|
NULL, HFILL }
|
|
|
|
},
|
|
|
|
{ &hf_nordic_ble_flags,
|
|
|
|
{ "Flags", "nordic_ble.flags",
|
|
|
|
FT_UINT8, BASE_HEX, NULL, 0x0,
|
|
|
|
NULL, HFILL }
|
|
|
|
},
|
|
|
|
{ &hf_nordic_ble_crcok,
|
|
|
|
{ "CRC", "nordic_ble.crcok",
|
2018-03-13 08:28:15 +00:00
|
|
|
FT_BOOLEAN, 8, TFS(&ok_incorrect), 0x01,
|
2016-12-14 09:17:42 +00:00
|
|
|
"Cyclic Redundancy Check state", HFILL }
|
|
|
|
},
|
|
|
|
{ &hf_nordic_ble_direction,
|
|
|
|
{ "Direction", "nordic_ble.direction",
|
2018-03-13 08:28:15 +00:00
|
|
|
FT_BOOLEAN, 8, TFS(&direction_tfs), 0x02,
|
2016-12-14 09:17:42 +00:00
|
|
|
NULL, HFILL }
|
|
|
|
},
|
2020-04-10 14:44:13 +00:00
|
|
|
{ &hf_nordic_ble_flag_reserved1,
|
|
|
|
{ "Reserved", "nordic_ble.flag_reserved1",
|
|
|
|
FT_UINT8, BASE_DEC, NULL, 0x02,
|
|
|
|
NULL, HFILL }
|
|
|
|
},
|
2016-12-14 09:17:42 +00:00
|
|
|
{ &hf_nordic_ble_encrypted,
|
|
|
|
{ "Encrypted", "nordic_ble.encrypted",
|
2018-03-13 08:28:15 +00:00
|
|
|
FT_BOOLEAN, 8, TFS(&tfs_yes_no), 0x04,
|
2016-12-14 09:17:42 +00:00
|
|
|
"Was the packet encrypted", HFILL }
|
|
|
|
},
|
2020-04-10 14:44:13 +00:00
|
|
|
{ &hf_nordic_ble_flag_reserved2,
|
|
|
|
{ "Reserved", "nordic_ble.flag_reserved2",
|
|
|
|
FT_UINT8, BASE_DEC, NULL, 0x04,
|
|
|
|
NULL, HFILL }
|
|
|
|
},
|
|
|
|
{ &hf_nordic_ble_aux_type,
|
|
|
|
{ "Aux Type", "nordic_ble.aux_type",
|
|
|
|
FT_UINT8, BASE_DEC, VALS(le_aux_ext_adv), 0x06,
|
|
|
|
NULL, HFILL }
|
|
|
|
},
|
2016-12-14 09:17:42 +00:00
|
|
|
{ &hf_nordic_ble_micok,
|
|
|
|
{ "MIC", "nordic_ble.micok",
|
2018-03-13 08:28:15 +00:00
|
|
|
FT_BOOLEAN, 8, TFS(&ok_incorrect), 0x08,
|
2016-12-14 09:17:42 +00:00
|
|
|
"Message Integrity Check state", HFILL }
|
|
|
|
},
|
2018-03-13 08:28:15 +00:00
|
|
|
{ &hf_nordic_ble_mic_not_relevant,
|
2020-07-05 21:16:21 +00:00
|
|
|
{ "MIC (not relevant)", "nordic_ble.mic_not_relevant",
|
|
|
|
FT_UINT8, BASE_DEC, NULL, 0x08,
|
|
|
|
"Message Integrity Check state is only relevant when encrypted", HFILL }
|
2018-03-13 08:28:15 +00:00
|
|
|
},
|
2020-04-10 14:44:13 +00:00
|
|
|
{ &hf_nordic_ble_flag_reserved3,
|
|
|
|
{ "Reserved", "nordic_ble.flag_reserved3",
|
|
|
|
FT_UINT8, BASE_DEC, NULL, 0x08,
|
|
|
|
NULL, HFILL }
|
|
|
|
},
|
2018-03-13 08:28:15 +00:00
|
|
|
{ &hf_nordic_ble_le_phy,
|
|
|
|
{ "PHY", "nordic_ble.phy",
|
2018-08-21 14:00:57 +00:00
|
|
|
FT_UINT8, BASE_DEC, VALS(le_phys), 0x70,
|
2018-03-13 08:28:15 +00:00
|
|
|
"Physical Layer", HFILL }
|
|
|
|
},
|
2020-04-10 14:44:13 +00:00
|
|
|
{ &hf_nordic_ble_flag_reserved7,
|
|
|
|
{ "Reserved", "nordic_ble.flag_reserved7",
|
2018-03-13 08:28:15 +00:00
|
|
|
FT_UINT8, BASE_DEC, NULL, 0x80,
|
|
|
|
"Reserved for Future Use", HFILL }
|
|
|
|
},
|
2016-12-14 09:17:42 +00:00
|
|
|
{ &hf_nordic_ble_channel,
|
|
|
|
{ "Channel", "nordic_ble.channel",
|
|
|
|
FT_UINT8, BASE_DEC, NULL, 0x0,
|
|
|
|
NULL, HFILL }
|
|
|
|
},
|
|
|
|
{ &hf_nordic_ble_rssi,
|
2020-04-04 10:53:49 +00:00
|
|
|
{ "RSSI", "nordic_ble.rssi",
|
|
|
|
FT_INT8, BASE_DEC | BASE_UNIT_STRING, &units_dbm, 0x0,
|
2016-12-14 09:17:42 +00:00
|
|
|
"Received Signal Strength Indicator", HFILL }
|
|
|
|
},
|
|
|
|
{ &hf_nordic_ble_event_counter,
|
|
|
|
{ "Event counter", "nordic_ble.event_counter",
|
|
|
|
FT_UINT16, BASE_DEC, NULL, 0x0,
|
|
|
|
NULL, HFILL }
|
|
|
|
},
|
2020-04-10 14:44:13 +00:00
|
|
|
{ &hf_nordic_ble_time,
|
|
|
|
{ "Timestamp", "nordic_ble.time",
|
|
|
|
FT_UINT32, BASE_DEC | BASE_UNIT_STRING, &units_microseconds, 0x0,
|
|
|
|
"Firmware timestamp", HFILL }
|
|
|
|
},
|
2016-12-14 09:17:42 +00:00
|
|
|
{ &hf_nordic_ble_delta_time,
|
2020-04-10 14:44:13 +00:00
|
|
|
{ "Delta time (end to start)", "nordic_ble.delta_time",
|
|
|
|
FT_UINT32, BASE_DEC | BASE_UNIT_STRING, &units_microseconds, 0x0,
|
|
|
|
"Time since end of last reported packet", HFILL }
|
2016-12-14 09:17:42 +00:00
|
|
|
},
|
|
|
|
{ &hf_nordic_ble_delta_time_ss,
|
2020-04-10 14:44:13 +00:00
|
|
|
{ "Delta time (start to start)", "nordic_ble.delta_time_ss",
|
|
|
|
FT_UINT32, BASE_DEC | BASE_UNIT_STRING, &units_microseconds, 0x0,
|
|
|
|
"Time since start of last reported packet", HFILL }
|
|
|
|
},
|
|
|
|
{ &hf_nordic_ble_packet_time,
|
|
|
|
{ "Packet time (start to end)", "nordic_ble.packet_time",
|
|
|
|
FT_UINT32, BASE_DEC | BASE_UNIT_STRING, &units_microseconds, 0x0,
|
|
|
|
"Time of packet", HFILL }
|
|
|
|
},
|
2016-07-21 07:55:03 +00:00
|
|
|
};
|
|
|
|
|
|
|
|
static gint *ett[] = {
|
|
|
|
&ett_nordic_ble,
|
2016-12-14 09:17:42 +00:00
|
|
|
&ett_packet_header,
|
2016-07-21 07:55:03 +00:00
|
|
|
&ett_flags
|
|
|
|
};
|
|
|
|
|
2016-12-14 09:17:42 +00:00
|
|
|
static ei_register_info ei[] = {
|
|
|
|
{ &ei_nordic_ble_bad_crc, { "nordic_ble.crc.bad", PI_CHECKSUM, PI_ERROR, "CRC is bad", EXPFILL }},
|
|
|
|
{ &ei_nordic_ble_bad_mic, { "nordic_ble.mic.bad", PI_CHECKSUM, PI_ERROR, "MIC is bad", EXPFILL }},
|
|
|
|
{ &ei_nordic_ble_bad_length, { "nordic_ble.length.bad", PI_MALFORMED, PI_ERROR, "Length is incorrect", EXPFILL }},
|
2018-03-13 08:28:15 +00:00
|
|
|
{ &ei_nordic_ble_unknown_version, { "nordic_ble.protover.bad", PI_PROTOCOL, PI_ERROR, "Unknown version", EXPFILL }},
|
2016-12-14 09:17:42 +00:00
|
|
|
};
|
|
|
|
|
|
|
|
expert_module_t *expert_nordic_ble;
|
2016-07-21 07:55:03 +00:00
|
|
|
|
2021-06-25 11:02:52 +00:00
|
|
|
packet_time_context_tree = wmem_tree_new_autoreset(wmem_epan_scope(), wmem_file_scope());
|
|
|
|
|
2021-03-25 19:35:10 +00:00
|
|
|
proto_nordic_ble = proto_register_protocol("nRF Sniffer for Bluetooth LE", "NORDIC_BLE", "nordic_ble");
|
2016-07-21 07:55:03 +00:00
|
|
|
|
|
|
|
register_dissector("nordic_ble", dissect_nordic_ble, proto_nordic_ble);
|
|
|
|
|
|
|
|
expert_nordic_ble = expert_register_protocol(proto_nordic_ble);
|
|
|
|
expert_register_field_array(expert_nordic_ble, ei, array_length(ei));
|
|
|
|
|
|
|
|
proto_register_field_array(proto_nordic_ble, hf, array_length(hf));
|
|
|
|
proto_register_subtree_array(ett, array_length(ett));
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
proto_reg_handoff_nordic_ble(void)
|
|
|
|
{
|
2016-10-05 20:33:54 +00:00
|
|
|
dissector_handle_t nordic_ble_handle;
|
2016-07-21 07:55:03 +00:00
|
|
|
|
2016-10-05 20:33:54 +00:00
|
|
|
nordic_ble_handle = create_dissector_handle(dissect_nordic_ble, proto_nordic_ble);
|
2016-07-21 07:55:03 +00:00
|
|
|
|
2016-10-05 20:33:54 +00:00
|
|
|
btle_dissector_handle = find_dissector("btle");
|
|
|
|
debug_handle = find_dissector("nordic_debug");
|
2016-07-21 07:55:03 +00:00
|
|
|
|
2016-10-05 20:33:54 +00:00
|
|
|
dissector_add_for_decode_as_with_preference("udp.port", nordic_ble_handle);
|
2017-08-26 09:21:52 +00:00
|
|
|
dissector_add_uint("wtap_encap", WTAP_ENCAP_NORDIC_BLE, nordic_ble_handle);
|
2016-07-21 07:55:03 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/*
|
2019-07-26 18:43:17 +00:00
|
|
|
* Editor modelines - https://www.wireshark.org/tools/modelines.html
|
2016-07-21 07:55:03 +00:00
|
|
|
*
|
|
|
|
* Local variables:
|
|
|
|
* c-basic-offset: 4
|
|
|
|
* tab-width: 8
|
|
|
|
* indent-tabs-mode: nil
|
|
|
|
* End:
|
|
|
|
*
|
|
|
|
* vi: set shiftwidth =4 tabstop =8 expandtab:
|
|
|
|
* :indentSize =4:tabSize =8:noTabs =true:
|
|
|
|
*/
|