aboutsummaryrefslogtreecommitdiffstats
path: root/epan/dissectors/packet-btrfcomm.c
diff options
context:
space:
mode:
authorMichal Labedzki <michal.labedzki@tieto.com>2014-03-24 11:54:00 +0100
committerAnders Broman <a.broman58@gmail.com>2014-03-25 09:13:13 +0000
commita99a0360c47c689abdf1ef09e09dea02749824d2 (patch)
tree6dca992dcf6a103beedaaf61582c58f81d6f4318 /epan/dissectors/packet-btrfcomm.c
parentab42220b6549630c99ca3a066b7943876e901843 (diff)
Bluetooth: Fix wrong recognized RFCOMM services
It seems that RFCOMM service can be dynamically changed while connection is still alive. In other words: host can connect to remote device and set one RFCOMM service (remote service), but later remote device can change service to one of host service without any disconnection. This patch add support for this case. Also improve searching for useful UUID service through SDP. Change-Id: I9e03b9b965d6b0d9761b4a451cdeb4a1a33ca017 Reviewed-on: https://code.wireshark.org/review/808 Reviewed-by: Anders Broman <a.broman58@gmail.com>
Diffstat (limited to 'epan/dissectors/packet-btrfcomm.c')
-rw-r--r--epan/dissectors/packet-btrfcomm.c102
1 files changed, 79 insertions, 23 deletions
diff --git a/epan/dissectors/packet-btrfcomm.c b/epan/dissectors/packet-btrfcomm.c
index 2e51253c2d..60b1ddb689 100644
--- a/epan/dissectors/packet-btrfcomm.c
+++ b/epan/dissectors/packet-btrfcomm.c
@@ -128,6 +128,13 @@ static dissector_handle_t btgnss_handle;
static dissector_table_t rfcomm_service_dissector_table;
static dissector_table_t rfcomm_channel_dissector_table;
+static wmem_tree_t *service_directions = NULL;
+
+typedef struct {
+ guint32 direction;
+ guint32 end_in;
+} service_direction_t;
+
typedef struct {
guint channel;
gchar* payload_proto_name;
@@ -204,6 +211,8 @@ static const value_string vs_frame_type_short[] = {
{0, NULL}
};
+#define FRAME_TYPE_SABM 0x2F
+#define FRAME_TYPE_UIH 0xEF
static const value_string vs_ctl[] = {
/* masked 0xfc */
@@ -616,22 +625,73 @@ dissect_btrfcomm(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void *data
/* payload length */
offset = dissect_btrfcomm_payload_length(tvb, offset, rfcomm_tree, &frame_len);
- if (dlci && (frame_len || (frame_type == 0xef) || (frame_type == 0x2f))) {
- wmem_tree_key_t key[10];
- guint32 k_interface_id;
- guint32 k_adapter_id;
- guint32 k_sdp_psm;
- guint32 k_direction;
- guint32 k_bd_addr_oui;
- guint32 k_bd_addr_id;
- guint32 k_service_type;
- guint32 k_service_channel;
- guint32 k_frame_number;
+ if (dlci && (frame_len || (frame_type == FRAME_TYPE_UIH) || (frame_type == FRAME_TYPE_SABM))) {
+ wmem_tree_key_t key[10];
+ guint32 k_interface_id;
+ guint32 k_adapter_id;
+ guint32 k_psm;
+ guint32 k_direction;
+ guint32 k_bd_addr_oui;
+ guint32 k_bd_addr_id;
+ guint32 k_service_type;
+ guint32 k_frame_number;
+ guint32 k_chandle;
+ guint32 k_channel;
+ service_direction_t *service_direction;
+ wmem_tree_t *subtree;
k_interface_id = l2cap_data->interface_id;
k_adapter_id = l2cap_data->adapter_id;
- k_sdp_psm = SDP_PSM_DEFAULT;
- k_direction = (l2cap_data->is_local_psm) ? P2P_DIR_SENT : P2P_DIR_RECV;
+ k_chandle = l2cap_data->chandle;
+ k_psm = l2cap_data->psm;
+ k_channel = dlci >> 1;
+ k_frame_number = pinfo->fd->num;
+
+ key[0].length = 1;
+ key[0].key = &k_interface_id;
+ key[1].length = 1;
+ key[1].key = &k_adapter_id;
+ key[2].length = 1;
+ key[2].key = &k_chandle;
+ key[3].length = 1;
+ key[3].key = &k_psm;
+ key[4].length = 1;
+ key[4].key = &k_channel;
+
+ if (!pinfo->fd->flags.visited && frame_type == FRAME_TYPE_SABM) {
+ key[5].length = 0;
+ key[5].key = NULL;
+
+ subtree = (wmem_tree_t *) wmem_tree_lookup32_array(service_directions, key);
+ service_direction = (subtree) ? (service_direction_t *) wmem_tree_lookup32_le(subtree, k_frame_number) : NULL;
+ if (service_direction && service_direction->end_in == G_MAXUINT32) {
+ service_direction->end_in = k_frame_number;
+ }
+
+ key[5].length = 1;
+ key[5].key = &k_frame_number;
+ key[6].length = 0;
+ key[6].key = NULL;
+
+ service_direction = wmem_new(wmem_file_scope(), service_direction_t);
+ service_direction->direction = (pinfo->p2p_dir == P2P_DIR_RECV) ? P2P_DIR_SENT : P2P_DIR_RECV;
+ service_direction->end_in = G_MAXUINT32;
+
+ wmem_tree_insert32_array(service_directions, key, service_direction);
+ }
+
+ key[5].length = 0;
+ key[5].key = NULL;
+
+ subtree = (wmem_tree_t *) wmem_tree_lookup32_array(service_directions, key);
+ service_direction = (subtree) ? (service_direction_t *) wmem_tree_lookup32_le(subtree, k_frame_number) : NULL;
+ if (service_direction && service_direction->end_in > k_frame_number) {
+ k_direction = service_direction->direction;
+ } else {
+ k_direction = (l2cap_data->is_local_psm) ? P2P_DIR_SENT : P2P_DIR_RECV;
+ }
+
+ k_psm = SDP_PSM_DEFAULT;
if (k_direction == P2P_DIR_RECV) {
k_bd_addr_oui = l2cap_data->remote_bd_addr_oui;
k_bd_addr_id = l2cap_data->remote_bd_addr_id;
@@ -640,15 +700,9 @@ dissect_btrfcomm(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void *data
k_bd_addr_id = 0;
}
k_service_type = BTSDP_RFCOMM_PROTOCOL_UUID;
- k_service_channel = dlci >> 1;
- k_frame_number = pinfo->fd->num;
- key[0].length = 1;
- key[0].key = &k_interface_id;
- key[1].length = 1;
- key[1].key = &k_adapter_id;
key[2].length = 1;
- key[2].key = &k_sdp_psm;
+ key[2].key = &k_psm;
key[3].length = 1;
key[3].key = &k_direction;
key[4].length = 1;
@@ -658,7 +712,7 @@ dissect_btrfcomm(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void *data
key[6].length = 1;
key[6].key = &k_service_type;
key[7].length = 1;
- key[7].key = &k_service_channel;
+ key[7].key = &k_channel;
key[8].length = 1;
key[8].key = &k_frame_number;
key[9].length = 0;
@@ -685,12 +739,12 @@ dissect_btrfcomm(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void *data
col_append_fstr(pinfo->cinfo, COL_INFO, "%s Channel=%u ",
val_to_str_const(frame_type, vs_frame_type_short, "Unknown"), dlci >> 1);
- if (dlci && (frame_type == 0x2f))
+ if (dlci && (frame_type == FRAME_TYPE_SABM))
col_append_fstr(pinfo->cinfo, COL_INFO, "(%s) ",
val_to_str_ext_const(service_info->uuid.bt_uuid, &bt_sig_uuid_vals_ext, "Unknown"));
/* UID frame */
- if ((frame_type == 0xef) && dlci && pf_flag) {
+ if ((frame_type == FRAME_TYPE_UIH) && dlci && pf_flag) {
col_append_str(pinfo->cinfo, COL_INFO, "UID ");
/* add credit based flow control byte */
@@ -1072,6 +1126,8 @@ proto_register_btrfcomm(void)
expert_btrfcomm = expert_register_protocol(proto_btrfcomm);
expert_register_field_array(expert_btrfcomm, ei, array_length(ei));
+ service_directions = wmem_tree_new_autoreset(wmem_epan_scope(), wmem_file_scope());
+
rfcomm_service_dissector_table = register_dissector_table("btrfcomm.service", "BT RFCOMM Service", FT_UINT16, BASE_HEX);
rfcomm_channel_dissector_table = register_dissector_table("btrfcomm.channel", "BT RFCOMM Channel", FT_UINT16, BASE_DEC);