diff options
-rw-r--r-- | epan/dissectors/packet-btrfcomm.c | 102 | ||||
-rw-r--r-- | epan/dissectors/packet-btsdp.c | 35 |
2 files changed, 105 insertions, 32 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); diff --git a/epan/dissectors/packet-btsdp.c b/epan/dissectors/packet-btsdp.c index 133d219eae..64ae9bad22 100644 --- a/epan/dissectors/packet-btsdp.c +++ b/epan/dissectors/packet-btsdp.c @@ -347,6 +347,9 @@ static expert_field ei_data_element_value_large = EI_INIT; static dissector_handle_t btsdp_handle; +static dissector_table_t btrfcomm_service_table; +static dissector_table_t btl2cap_service_table; + static wmem_tree_t *tid_requests = NULL; static wmem_tree_t *continuation_states = NULL; static wmem_tree_t *record_handle_services = NULL; @@ -858,16 +861,27 @@ service_info_t* btsdp_get_service_info(wmem_tree_key_t* key) } static uuid_t -get_most_specified_uuid(wmem_array_t *uuid_array) +get_specified_uuid(wmem_array_t *uuid_array) { uuid_t uuid; -/* TODO: For now try to use first (most specified) UUID, this may sometimes fail */ +/* Try to find UUID that is already use in RFCOMM or L2CAP, otherwise try to + return last one (most generic). + NOTE: UUIDs in array are from (most specified) to (most generic) */ if (uuid_array) { + guint32 i_uuid; + guint32 size; uuid_t *p_uuid = NULL; - if (wmem_array_get_count(uuid_array) > 0) - p_uuid = (uuid_t *) wmem_array_index(uuid_array, 0); + size = wmem_array_get_count(uuid_array); + + for (i_uuid = 0; i_uuid < size; i_uuid += 1) { + p_uuid = (uuid_t *) wmem_array_index(uuid_array, i_uuid); + if (dissector_get_uint_handle(btrfcomm_service_table, p_uuid->bt_uuid)) + break; + if (dissector_get_uint_handle(btl2cap_service_table, p_uuid->bt_uuid)) + break; + } if (p_uuid) return *p_uuid; } @@ -3617,7 +3631,7 @@ dissect_sdp_service_attribute_list(proto_tree *tree, tvbuff_t *tvb, gint offset, number_of_attributes += 1; } - uuid = get_most_specified_uuid(uuid_array); + uuid = get_specified_uuid(uuid_array); if (uuid.size == 0 && service_uuid) uuid = *service_uuid; @@ -3950,7 +3964,7 @@ dissect_sdp_service_attribute_request(proto_tree *tree, tvbuff_t *tvb, offset += 2; uuid_array = get_uuids(pinfo, record_handle, l2cap_data); - uuid = get_most_specified_uuid(uuid_array); + uuid = get_specified_uuid(uuid_array); offset += dissect_attribute_id_list(tree, tvb, offset, pinfo, &uuid); @@ -3988,7 +4002,7 @@ dissect_sdp_service_attribute_response(proto_tree *tree, tvbuff_t *tvb, wmem_array_t *uuid_array; uuid_array = get_uuids(pinfo, record_handle, l2cap_data); - uuid = get_most_specified_uuid(uuid_array); + uuid = get_specified_uuid(uuid_array); } else { memset(&uuid, 0, sizeof(uuid_t)); } @@ -4081,7 +4095,7 @@ dissect_sdp_service_search_attribute_request(proto_tree *tree, tvbuff_t *tvb, proto_tree_add_item(tree, hf_maximum_attribute_byte_count, tvb, offset, 2, ENC_BIG_ENDIAN); offset += 2; - uuid = get_most_specified_uuid(uuid_array); + uuid = get_specified_uuid(uuid_array); offset += dissect_attribute_id_list(tree, tvb, offset, pinfo, &uuid); @@ -4115,7 +4129,7 @@ dissect_sdp_service_search_attribute_response(proto_tree *tree, tvbuff_t *tvb, PDU_TYPE_SERVICE_SEARCH_ATTRIBUTE, &new_tvb, &is_first, &is_continued, &uuid_array, NULL, l2cap_data); - uuid = get_most_specified_uuid(uuid_array); + uuid = get_specified_uuid(uuid_array); if (is_first && !is_continued) { dissect_sdp_service_attribute_list_array(tree, tvb, offset, pinfo, @@ -5668,6 +5682,9 @@ proto_reg_handoff_btsdp(void) { dissector_add_uint("btl2cap.psm", BTL2CAP_PSM_SDP, btsdp_handle); dissector_add_handle("btl2cap.cid", btsdp_handle); + + btrfcomm_service_table = find_dissector_table("btrfcomm.service"); + btl2cap_service_table = find_dissector_table("btl2cap.service"); } /* |