diff options
author | Guy Harris <guy@alum.mit.edu> | 2020-03-17 23:16:43 -0700 |
---|---|---|
committer | Guy Harris <guy@alum.mit.edu> | 2020-03-18 06:56:22 +0000 |
commit | c38f97aa22724f4c8cd28663acf26c908e7fcd02 (patch) | |
tree | bee1d3904cb216516e27e0915c88b527b52adfd1 | |
parent | ac82fd63534e6044a07896a519726ced78270882 (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.c | 370 |
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"); |