aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorGuy Harris <guy@alum.mit.edu>2020-03-17 23:16:43 -0700
committerGuy Harris <guy@alum.mit.edu>2020-03-18 06:56:22 +0000
commitc38f97aa22724f4c8cd28663acf26c908e7fcd02 (patch)
treebee1d3904cb216516e27e0915c88b527b52adfd1
parentac82fd63534e6044a07896a519726ced78270882 (diff)
Add support for more monitor opcodes.
Support more of what current Linux kernels generate. We don't yet dissect control event payloads. While we're at it: Opcodes are defined in the kernel source in decimal; define and show them as decimal. Use #defines for a bunch of enumerated values, such as opcodes Show the opcode's numerical value in the Info column if it's not one we know about. Change-Id: I915981a46d1a4a544a5e036e69d9a9de8cb8cb30 Reviewed-on: https://code.wireshark.org/review/36487 Petri-Dish: Guy Harris <guy@alum.mit.edu> Tested-by: Petri Dish Buildbot Reviewed-by: Guy Harris <guy@alum.mit.edu>
-rw-r--r--epan/dissectors/packet-hci_mon.c370
1 files changed, 351 insertions, 19 deletions
diff --git a/epan/dissectors/packet-hci_mon.c b/epan/dissectors/packet-hci_mon.c
index 3efc7d2739..d88e10f6f6 100644
--- a/epan/dissectors/packet-hci_mon.c
+++ b/epan/dissectors/packet-hci_mon.c
@@ -27,8 +27,23 @@ static int hf_type = -1;
static int hf_bus = -1;
static int hf_bd_addr = -1;
static int hf_name = -1;
+static int hf_manufacturer = -1;
+static int hf_system_note = -1;
+static int hf_priority = -1;
+static int hf_ident_length = -1;
+static int hf_ident = -1;
+static int hf_cookie = -1;
+static int hf_format = -1;
+static int hf_version = -1;
+static int hf_revision = -1;
+static int hf_flags = -1;
+static int hf_flags_trusted_socket = -1;
+static int hf_command_length = -1;
+static int hf_command = -1;
+static int hf_event = -1;
static gint ett_hci_mon = -1;
+static gint ett_flags = -1;
static expert_field ei_unknown_data = EI_INIT;
@@ -40,16 +55,45 @@ static dissector_handle_t bthci_evt_handle;
static dissector_handle_t bthci_acl_handle;
static dissector_handle_t bthci_sco_handle;
+#define OPCODE_NEW_INDEX 0
+#define OPCODE_DELETE_INDEX 1
+#define OPCODE_HCI_COMMAND_PKT 2
+#define OPCODE_HCI_EVENT_PKT 3
+#define OPCODE_ACL_TX_PACKET 4
+#define OPCODE_ACL_RX_PACKET 5
+#define OPCODE_SCO_TX_PACKET 6
+#define OPCODE_SCO_RX_PACKET 7
+#define OPCODE_OPEN_INDEX 8
+#define OPCODE_CLOSE_INDEX 9
+#define OPCODE_INDEX_INFO 10
+#define OPCODE_VENDOR_DIAGNOSTIC 11
+#define OPCODE_SYSTEM_NOTE 12
+#define OPCODE_USER_LOGGING 13
+#define OPCODE_CONTROL_OPEN 14
+#define OPCODE_CONTROL_CLOSE 15
+#define OPCODE_CONTROL_COMMAND 16
+#define OPCODE_CONTROL_EVENT 17
+
static const value_string opcode_vals[] = {
- { 0x00, "New Index" },
- { 0x01, "Delete Index" },
- { 0x02, "HCI Command Packet" },
- { 0x03, "HCI Event Packet" },
- { 0x04, "ACL Tx Packet" },
- { 0x05, "ACL Rx Packet" },
- { 0x06, "SCO Tx Packet" },
- { 0x07, "SCO Rx Packet" },
- { 0x00, NULL }
+ { OPCODE_NEW_INDEX, "New Index" },
+ { OPCODE_DELETE_INDEX, "Delete Index" },
+ { OPCODE_HCI_COMMAND_PKT, "HCI Command Packet" },
+ { OPCODE_HCI_EVENT_PKT, "HCI Event Packet" },
+ { OPCODE_ACL_TX_PACKET, "ACL Tx Packet" },
+ { OPCODE_ACL_RX_PACKET, "ACL Rx Packet" },
+ { OPCODE_SCO_TX_PACKET, "SCO Tx Packet" },
+ { OPCODE_SCO_RX_PACKET, "SCO Rx Packet" },
+ { OPCODE_OPEN_INDEX, "Open Index" },
+ { OPCODE_CLOSE_INDEX, "Close Index" },
+ { OPCODE_INDEX_INFO, "Index Info" },
+ { OPCODE_VENDOR_DIAGNOSTIC, "Vendor Diagnostic" },
+ { OPCODE_SYSTEM_NOTE, "System Note" },
+ { OPCODE_USER_LOGGING, "User Logging" },
+ { OPCODE_CONTROL_OPEN, "Control Open" },
+ { OPCODE_CONTROL_CLOSE, "Control Close" },
+ { OPCODE_CONTROL_COMMAND, "Control Command" },
+ { OPCODE_CONTROL_EVENT, "Control Event" },
+ { 0, NULL }
};
value_string_ext(hci_mon_opcode_vals_ext) = VALUE_STRING_EXT_INIT(opcode_vals);
@@ -72,6 +116,100 @@ static const value_string bus_vals[] = {
};
static value_string_ext(bus_vals_ext) = VALUE_STRING_EXT_INIT(bus_vals);
+#define CTRL_OPEN_RAW 0x0000
+#define CTRL_OPEN_USER 0x0001
+#define CTRL_OPEN_CONTROL 0x0002
+
+static const value_string format_vals[] = {
+ { CTRL_OPEN_RAW, "Rqw" },
+ { CTRL_OPEN_USER, "User" },
+ { CTRL_OPEN_CONTROL, "Control" },
+ { 0x00, NULL }
+};
+static value_string_ext(format_vals_ext) = VALUE_STRING_EXT_INIT(format_vals);
+
+#define EVENT_COMMAND_COMPLETE 0x0001
+#define EVENT_COMMAND_STATUS 0x0002
+#define EVENT_CONTROLLER_ERROR 0x0003
+#define EVENT_INDEX_ADDED 0x0004
+#define EVENT_INDEX_REMOVED 0x0005
+#define EVENT_NEW_SETTINGS 0x0006
+#define EVENT_CLASS_OF_DEVICE_CHANGED 0x0007
+#define EVENT_LOCAL_NAME_CHANGED 0x0008
+#define EVENT_NEW_LINK_KEY 0x0009
+#define EVENT_NEW_LONG_TERM_KEY 0x000a
+#define EVENT_DEVICE_CONNECTED 0x000b
+#define EVENT_DEVICE_DISCONNECTED 0x000c
+#define EVENT_CONNECT_FAILED 0x000d
+#define EVENT_PIN_CODE_REQUEST 0x000e
+#define EVENT_USER_CONFIRMATION_REQUEST 0x000f
+#define EVENT_USER_PASSKEY_REQUEST 0x0010
+#define EVENT_AUTHENTICAION_FAILED 0x0011
+#define EVENT_DEVICE_FOUND 0x0012
+#define EVENT_DISCOVERING 0x0013
+#define EVENT_DEVICE_BLOCKED 0x0014
+#define EVENT_DEVICE_UNBLOCKED 0x0015
+#define EVENT_DEVICE_UNPAIRED 0x0016
+#define EVENT_PASSKEY_NOTIFY 0x0017
+#define EVENT_NEW_IRK 0x0018
+#define EVENT_NEW_CSRK 0x0019
+#define EVENT_DEVICE_ADDED 0x001a
+#define EVENT_DEVICE_REMOVED 0x001b
+#define EVENT_NEW_CONNECTION_PARAMETER 0x001c
+#define EVENT_UNCONFIGURED_INDEX_ADDED 0x001d
+#define EVENT_UNCONFIGURED_INDEX_REMOVED 0x001e
+#define EVENT_NEW_CONFIGURATION_OPTIONS 0x001f
+#define EVENT_EXTENDED_INDEX_ADDED 0x0020
+#define EVENT_EXTENDED_INDEX_REMOVED 0x0021
+#define EVENT_LOCAL_OUT_OF_BAND_DATA_UPDATED 0x0022
+#define EVENT_ADVERTISING_ADDED 0x0023
+#define EVENT_ADVERTISING_REMOVED 0x0024
+#define EVENT_EXTENDED_INFO_CHANGED 0x0025
+#define EVENT_PHY_CONFIGURATION_CHANGED 0x0026
+
+static const value_string event_vals[] = {
+ { EVENT_COMMAND_COMPLETE, "Command complete" },
+ { EVENT_COMMAND_STATUS, "Command status" },
+ { EVENT_CONTROLLER_ERROR, "Controller error" },
+ { EVENT_INDEX_ADDED, "Index added" },
+ { EVENT_INDEX_REMOVED, "Index removed" },
+ { EVENT_NEW_SETTINGS, "New settings" },
+ { EVENT_CLASS_OF_DEVICE_CHANGED, "Class of device changed" },
+ { EVENT_LOCAL_NAME_CHANGED, "Local name changed" },
+ { EVENT_NEW_LINK_KEY, "New link key" },
+ { EVENT_NEW_LONG_TERM_KEY, "New long-term key" },
+ { EVENT_DEVICE_CONNECTED, "Device connected" },
+ { EVENT_DEVICE_DISCONNECTED, "Device disconnected" },
+ { EVENT_CONNECT_FAILED, "Connect failed" },
+ { EVENT_PIN_CODE_REQUEST, "PIN code request" },
+ { EVENT_USER_CONFIRMATION_REQUEST, "User confirmation request" },
+ { EVENT_USER_PASSKEY_REQUEST, "User passkey request" },
+ { EVENT_AUTHENTICAION_FAILED, "Authentication failed" },
+ { EVENT_DEVICE_FOUND, "Device found" },
+ { EVENT_DISCOVERING, "Discovering" },
+ { EVENT_DEVICE_BLOCKED, "Device blocked" },
+ { EVENT_DEVICE_UNBLOCKED, "Device unblocked" },
+ { EVENT_DEVICE_UNPAIRED, "Device unpaired" },
+ { EVENT_PASSKEY_NOTIFY, "Passkey notify" },
+ { EVENT_NEW_IRK, "New IRK" },
+ { EVENT_NEW_CSRK, "New CSRK" },
+ { EVENT_DEVICE_ADDED, "Device added" },
+ { EVENT_DEVICE_REMOVED, "Device removed" },
+ { EVENT_NEW_CONNECTION_PARAMETER, "New connection parameter" },
+ { EVENT_UNCONFIGURED_INDEX_ADDED, "Unconfigured index added" },
+ { EVENT_UNCONFIGURED_INDEX_REMOVED, "Unconfigured index removed" },
+ { EVENT_NEW_CONFIGURATION_OPTIONS, "New configuration options" },
+ { EVENT_EXTENDED_INDEX_ADDED, "Extended index added" },
+ { EVENT_EXTENDED_INDEX_REMOVED, "Extended index removed" },
+ { EVENT_LOCAL_OUT_OF_BAND_DATA_UPDATED, "Local out-of-band data updated" },
+ { EVENT_ADVERTISING_ADDED, "Advertising added" },
+ { EVENT_ADVERTISING_REMOVED, "Advertising removed" },
+ { EVENT_EXTENDED_INFO_CHANGED, "Extended info changed" },
+ { EVENT_PHY_CONFIGURATION_CHANGED, "PHY configuration changed" },
+ { 0x00, NULL }
+};
+static value_string_ext(event_vals_ext) = VALUE_STRING_EXT_INIT(event_vals);
+
void proto_register_hci_mon(void);
void proto_reg_handoff_hci_mon(void);
@@ -92,9 +230,22 @@ dissect_hci_mon(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void *data)
guint32 k_interface_id;
guint32 k_adapter_id;
guint32 k_frame_number;
+ guint32 ident_length;
+ guint32 command_length;
+ static const int *flags_fields[] = {
+ &hf_flags_trusted_socket,
+ NULL
+ };
bluetooth_data = (bluetooth_data_t *) data;
+ /*
+ * XXX - the raw data sent to a Bluetooth monitor socket has a 6-byte
+ * header, the last 2 bytes of which are a big-endian length field,
+ * giving the length of the payload.
+ *
+ * Somehow, the length field disappears.
+ */
DISSECTOR_ASSERT(bluetooth_data->previous_protocol_data_type == BT_PD_BTMON);
adapter_id = bluetooth_data->previous_protocol_data.btmon->adapter_id;
opcode = bluetooth_data->previous_protocol_data.btmon->opcode;
@@ -135,7 +286,7 @@ dissect_hci_mon(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void *data)
proto_item_set_generated(sub_item);
col_append_fstr(pinfo->cinfo, COL_INFO, "Adapter Id: %u, Opcode: %s",
- adapter_id, val_to_str_ext_const(opcode, &hci_mon_opcode_vals_ext, "Unknown"));
+ adapter_id, val_to_str_ext_const(opcode, &hci_mon_opcode_vals_ext, "Unknown (%u)"));
bluetooth_data->adapter_id = adapter_id;
@@ -181,7 +332,7 @@ dissect_hci_mon(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void *data)
next_tvb = tvb_new_subset_remaining(tvb, offset);
switch(opcode) {
- case 0x00: /* New Index */
+ case OPCODE_NEW_INDEX:
proto_tree_add_item(hci_mon_tree, hf_bus, tvb, offset, 1, ENC_BIG_ENDIAN);
offset += 1;
@@ -194,32 +345,142 @@ dissect_hci_mon(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void *data)
offset += 8;
break;
- case 0x01: /* Delete Index */
+ case OPCODE_DELETE_INDEX:
/* No parameters */
break;
- case 0x02: /* HCI Command Packet */
+ case OPCODE_HCI_COMMAND_PKT:
call_dissector_with_data(bthci_cmd_handle, next_tvb, pinfo, tree, bluetooth_data);
offset = tvb_reported_length(tvb);
break;
- case 0x03: /* HCI Event Packet */
+ case OPCODE_HCI_EVENT_PKT:
call_dissector_with_data(bthci_evt_handle, next_tvb, pinfo, tree, bluetooth_data);
offset = tvb_reported_length(tvb);
break;
- case 0x04: /* ACL Tx Packet */
- case 0x05: /* ACL Rx Packet */
+ case OPCODE_ACL_TX_PACKET:
+ case OPCODE_ACL_RX_PACKET:
call_dissector_with_data(bthci_acl_handle, next_tvb, pinfo, tree, bluetooth_data);
offset = tvb_reported_length(tvb);
break;
- case 0x06: /* SCO Tx Packet */
- case 0x07: /* SCO Rx Packet */
+ case OPCODE_SCO_TX_PACKET:
+ case OPCODE_SCO_RX_PACKET:
call_dissector_with_data(bthci_sco_handle, next_tvb, pinfo, tree, bluetooth_data);
offset = tvb_reported_length(tvb);
break;
+
+ case OPCODE_OPEN_INDEX:
+ /* No parameters */
+
+ break;
+
+ case OPCODE_CLOSE_INDEX:
+ /* No parameters */
+
+ break;
+
+ case OPCODE_INDEX_INFO:
+ offset = dissect_bd_addr(hf_bd_addr, pinfo, hci_mon_tree, tvb, offset, TRUE, bluetooth_data->interface_id, bluetooth_data->adapter_id, NULL);
+
+ proto_tree_add_item(hci_mon_tree, hf_manufacturer, tvb, offset, 2, ENC_LITTLE_ENDIAN);
+ offset += 2;
+
+ break;
+
+ case OPCODE_VENDOR_DIAGNOSTIC:
+ /* XXX - what are the parameters, if any? */
+
+ break;
+
+ case OPCODE_SYSTEM_NOTE:
+ /*
+ * XXX - NUL-terminated, so that you always have a NUL at the
+ * end of the message?
+ *
+ * Or is it data from userland, which might or might not be
+ * NUL-terminated?
+ *
+ * We make it FT_STRINGZPAD, just in case.
+ */
+ proto_tree_add_item(hci_mon_tree, hf_system_note, tvb, offset, tvb_reported_length_remaining(tvb, offset), ENC_NA | ENC_ASCII);
+ offset = tvb_reported_length(tvb);
+
+ break;
+
+ case OPCODE_USER_LOGGING:
+ proto_tree_add_item(hci_mon_tree, hf_priority, tvb, offset, 1, ENC_NA);
+ offset += 1;
+
+ proto_tree_add_item_ret_uint(hci_mon_tree, hf_priority, tvb, offset, 1, ENC_NA, &ident_length);
+ offset += 1;
+
+ /*
+ * XXX - this is both counted and NUL-terminated, so you have
+ * <length> bytes of string followed by a NUL. We'll just
+ * treat it as counted.
+ */
+ proto_tree_add_item(hci_mon_tree, hf_priority, tvb, offset, ident_length, ENC_NA | ENC_ASCII);
+ offset += ident_length + 1; /* Skip the terminating NUL */
+
+ break;
+
+ case OPCODE_CONTROL_OPEN:
+ proto_tree_add_item(hci_mon_tree, hf_cookie, tvb, offset, 4, ENC_LITTLE_ENDIAN);
+ offset += 4;
+
+ proto_tree_add_item(hci_mon_tree, hf_format, tvb, offset, 2, ENC_LITTLE_ENDIAN);
+ offset += 2;
+
+ proto_tree_add_item(hci_mon_tree, hf_version, tvb, offset, 1, ENC_NA);
+ proto_tree_add_item(hci_mon_tree, hf_revision, tvb, offset + 1, 2, ENC_LITTLE_ENDIAN);
+ offset += 3;
+
+ proto_tree_add_bitmask(hci_mon_tree, tvb, offset, hf_flags, ett_flags,
+ flags_fields, ENC_LITTLE_ENDIAN);
+ offset += 4;
+
+ proto_tree_add_item_ret_uint(hci_mon_tree, hf_command_length, tvb, offset, 1, ENC_NA, &command_length);
+ offset += 1;
+
+ /*
+ * XXX - null-padded? We assume so; the Linux kernel code, as of
+ * the 5.3 kernel, always copies TASK_COMM_LEN bytes and sets the
+ * command length to TASK_COMM_LEN.
+ */
+ proto_tree_add_item(hci_mon_tree, hf_command, tvb, offset, command_length, ENC_NA | ENC_ASCII);
+ offset += command_length;
+
+ break;
+
+ case OPCODE_CONTROL_CLOSE:
+ proto_tree_add_item(hci_mon_tree, hf_cookie, tvb, offset, 4, ENC_LITTLE_ENDIAN);
+ offset += 4;
+
+ break;
+
+ case OPCODE_CONTROL_COMMAND:
+ proto_tree_add_item(hci_mon_tree, hf_cookie, tvb, offset, 4, ENC_LITTLE_ENDIAN);
+ offset += 4;
+
+ /* XXX - different field for this opcode? */
+ proto_tree_add_item(hci_mon_tree, hf_opcode, tvb, offset, 2, ENC_LITTLE_ENDIAN);
+ offset += 2;
+
+ break;
+
+ case OPCODE_CONTROL_EVENT:
+ proto_tree_add_item(hci_mon_tree, hf_cookie, tvb, offset, 4, ENC_LITTLE_ENDIAN);
+ offset += 4;
+
+ proto_tree_add_item(hci_mon_tree, hf_event, tvb, offset, 2, ENC_LITTLE_ENDIAN);
+ offset += 2;
+
+ /* XXX - dissect the payload of the event */
+
+ break;
}
if (tvb_reported_length_remaining(tvb, offset) > 0) {
@@ -249,7 +510,7 @@ proto_register_hci_mon(void)
},
{ &hf_opcode,
{ "Opcode", "hci_mon.opcode",
- FT_UINT16, BASE_HEX | BASE_EXT_STRING, &hci_mon_opcode_vals_ext, 0x00,
+ FT_UINT16, BASE_DEC | BASE_EXT_STRING, &hci_mon_opcode_vals_ext, 0x00,
NULL, HFILL }
},
{ &hf_type,
@@ -271,6 +532,76 @@ proto_register_hci_mon(void)
{ "Adapter Name", "hci_mon.adapter_name",
FT_STRING, BASE_NONE, NULL, 0x0,
NULL, HFILL}
+ },
+ { &hf_manufacturer,
+ { "Manufacturer", "hci_mon.manufacturer",
+ FT_UINT16, BASE_HEX, NULL, 0x000,
+ NULL, HFILL }
+ },
+ { &hf_system_note,
+ { "System Note", "hci_mon.system_note",
+ FT_STRINGZPAD, BASE_NONE, NULL, 0x0,
+ NULL, HFILL}
+ },
+ { &hf_priority,
+ { "Priority", "hci_mon.priority",
+ FT_UINT8, BASE_DEC, NULL, 0x0,
+ NULL, HFILL}
+ },
+ { &hf_ident_length,
+ { "Ident Length", "hci_mon.ident_length",
+ FT_UINT8, BASE_DEC, NULL, 0x0,
+ NULL, HFILL}
+ },
+ { &hf_ident,
+ { "Ident", "hci_mon.ident",
+ FT_STRING, BASE_NONE, NULL, 0x0,
+ NULL, HFILL}
+ },
+ { &hf_cookie,
+ { "Cookie", "hci_mon.cookie",
+ FT_UINT32, BASE_HEX, NULL, 0x0,
+ NULL, HFILL}
+ },
+ { &hf_format,
+ { "Format", "hci_mon.format",
+ FT_UINT16, BASE_HEX | BASE_EXT_STRING, &format_vals_ext, 0x00,
+ NULL, HFILL}
+ },
+ { &hf_version,
+ { "Version", "hci_mon.version",
+ FT_UINT8, BASE_DEC, NULL, 0x00,
+ NULL, HFILL}
+ },
+ { &hf_revision,
+ { "Revision", "hci_mon.version_minor",
+ FT_UINT16, BASE_DEC, NULL, 0x00,
+ NULL, HFILL}
+ },
+ { &hf_flags,
+ { "Flags", "hci_mon.flags",
+ FT_UINT32, BASE_HEX, NULL, 0x0,
+ NULL, HFILL}
+ },
+ { &hf_flags_trusted_socket,
+ { "Trusted Socket", "hci_mon.flags.trusted_socket",
+ FT_BOOLEAN, 32, NULL, 0x00000001,
+ NULL, HFILL}
+ },
+ { &hf_command_length,
+ { "Command Length", "hci_mon.command_length",
+ FT_UINT8, BASE_DEC, NULL, 0x0,
+ NULL, HFILL}
+ },
+ { &hf_command,
+ { "Command", "hci_mon.command",
+ FT_STRINGZPAD, BASE_NONE, NULL, 0x0,
+ NULL, HFILL}
+ },
+ { &hf_event,
+ { "Event", "hci_mon.event",
+ FT_UINT16, BASE_HEX | BASE_EXT_STRING, &event_vals_ext, 0x0,
+ NULL, HFILL}
}
};
@@ -280,6 +611,7 @@ proto_register_hci_mon(void)
static gint *ett[] = {
&ett_hci_mon,
+ &ett_flags
};
proto_hci_mon = proto_register_protocol("Bluetooth Linux Monitor Transport", "HCI_MON", "hci_mon");