diff options
author | Michal Labedzki <michal.labedzki@tieto.com> | 2014-03-30 12:03:18 +0200 |
---|---|---|
committer | Michal Labedzki <michal.labedzki@tieto.com> | 2014-05-30 11:24:59 +0000 |
commit | 2abc54158dd6c7c66680ddddb9927501d9e12d50 (patch) | |
tree | 8b173675412614016f6c1bf68fe8968a7858b6bf | |
parent | 32e66a4cc663e5ec351872f6d4445d2b8c53a071 (diff) |
Bluetooth AVDTP/RTP: Separate the streams
The Stream is defined here as media stream that beginning on
AVDTP Start (ResponseAccept).
Also fix recognizing Channel streams by AVDTP according to the
specification that says:
1. First channel is always Signaling.
2. Second may be Media.
3. Third may be Reporting.
4. Fourth may be Recovery.
First and second will be supported right now.
Change-Id: Id6d4dae6be1b9df68382288c2d520b7ed3661237
Reviewed-on: https://code.wireshark.org/review/1053
Reviewed-by: Michal Labedzki <michal.labedzki@tieto.com>
-rw-r--r-- | epan/dissectors/packet-btavdtp.c | 537 | ||||
-rw-r--r-- | epan/dissectors/packet-btavdtp.h | 1 | ||||
-rw-r--r-- | epan/dissectors/packet-btl2cap.c | 10 | ||||
-rw-r--r-- | epan/dissectors/packet-btl2cap.h | 2 | ||||
-rw-r--r-- | epan/dissectors/packet-rtp.c | 6 | ||||
-rw-r--r-- | epan/dissectors/packet-rtp.h | 2 |
6 files changed, 315 insertions, 243 deletions
diff --git a/epan/dissectors/packet-btavdtp.c b/epan/dissectors/packet-btavdtp.c index a717091329..d6471930dd 100644 --- a/epan/dissectors/packet-btavdtp.c +++ b/epan/dissectors/packet-btavdtp.c @@ -100,6 +100,34 @@ #define SEP_MAX 64 #define SEP_SIZE 2 +/* ========================================================== */ +/* Story: RTP Player, conversation (probably reassemble too) use address:port as + "key" to separate devices/streams. In Bluetooth World it is not enough to + separate devices/streams. Example key: + guint32 interface_id (aka frame.interface_id) + guint32 adapter_id (interface like "bluetooth-monitor" or USB provide + more than one device over interface, so we must + separate information provided by each one) + guint16 hci_chandle (aka "connection handle" use to separate connections to devices) + guint16 l2cap_psm (like hci_chandle but over l2cap layer, need hci_chandle info because + the same PSM can be used over chandles) + guint8 rfcomm_channel (like l2cap_psm, but over RFCOMM layer...) + etc. like + guint8 stram_endpoint_number + guint32 stream_number (to separate multiple streams for RTP Player) + + So keys can be various (length or type) and "ports" are not enough to sore + all needed information. If one day that changed then all RTP_PLAYER_WORKAROUND + block can be removed. This workaround use global number of streams (aka stream ID) + to be used as port number in RTP Player to separate streams. + */ +#define RTP_PLAYER_WORKAROUND TRUE + +#if RTP_PLAYER_WORKAROUND == TRUE + wmem_tree_t *file_scope_stream_number = NULL; +#endif +/* ========================================================== */ + static int proto_btavdtp = -1; static int hf_btavdtp_data = -1; @@ -239,18 +267,15 @@ static expert_field ei_btavdtp_sbc_min_bitpool_out_of_range = EI_INIT; static expert_field ei_btavdtp_sbc_max_bitpool_out_of_range = EI_INIT; static expert_field ei_btavdtp_unexpected_losc_data = EI_INIT; -static gboolean force_avdtp = FALSE; - static dissector_handle_t btavdtp_handle; static dissector_handle_t bta2dp_handle; static dissector_handle_t btvdp_handle; static dissector_handle_t rtp_handle; - -static wmem_tree_t *sep_list = NULL; -static wmem_tree_t *sep_open = NULL; -static wmem_tree_t *cid_to_type_table = NULL; -static wmem_tree_t *media_packet_times = NULL; +static wmem_tree_t *channels = NULL; +static wmem_tree_t *sep_list = NULL; +static wmem_tree_t *sep_open = NULL; +static wmem_tree_t *media_packet_times = NULL; /* A2DP declarations */ static gint proto_bta2dp = -1; @@ -262,6 +287,7 @@ static int hf_bta2dp_acp_seid = -1; static int hf_bta2dp_int_seid = -1; static int hf_bta2dp_codec = -1; static int hf_bta2dp_content_protection = -1; +static int hf_bta2dp_stream_number = -1; static int hf_bta2dp_l_bit = -1; static int hf_bta2dp_cp_bit = -1; static int hf_bta2dp_reserved = -1; @@ -461,24 +487,32 @@ typedef struct _sep_entry_t { enum sep_state state; } sep_entry_t; -typedef struct _cid_type_data_t { - guint32 interface_id; - guint32 adapter_id; - guint32 chandle; - guint32 type; - guint16 cid; - sep_entry_t *sep; -} cid_type_data_t; - typedef struct _sep_data_t { gint codec; guint8 acp_seid; guint8 int_seid; gint content_protection_type; + guint32 stream_number; media_packet_info_t *previous_media_packet_info; media_packet_info_t *current_media_packet_info; } sep_data_t; +typedef struct _media_stream_number_value_t { + guint32 stream_number; +} media_stream_number_value_t; + +typedef struct _channels_info_t { + gint32 control_scid; + gint32 control_dcid; + gint32 media_scid; + gint32 media_dcid; + gboolean media_is_local_psm; + wmem_tree_t *stream_numbers; + guint32 disconnect_in_frame; + sep_entry_t *sep; +} channels_info_t; + + void proto_register_btavdtp(void); void proto_reg_handoff_btavdtp(void); void proto_register_bta2dp(void); @@ -488,6 +522,7 @@ void proto_register_btvdp(void); void proto_reg_handoff_btvdp(void); void proto_register_btvdp_content_protection_header_scms_t(void); + static const char * get_sep_type(guint32 interface_id, guint32 adapter_id, guint32 chandle, guint32 direction, guint32 seid, guint32 frame_number) @@ -827,7 +862,7 @@ dissect_capabilities(tvbuff_t *tvb, packet_info *pinfo, case SERVICE_CATEGORY_MEDIA_TRANSPORT: case SERVICE_CATEGORY_REPORTING: case SERVICE_CATEGORY_DELAY_REPORTING: - /* losc should be 0*/ + /* losc should be 0 */ break; case SERVICE_CATEGORY_RECOVERY: recovery_type = tvb_get_guint8(tvb, offset); @@ -979,7 +1014,6 @@ dissect_capabilities(tvbuff_t *tvb, packet_info *pinfo, return offset; } - static gint dissect_seid(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, gint offset, gint seid_side, gint i_item, guint32 *sep_seid, @@ -1047,14 +1081,14 @@ dissect_btavdtp(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void *data) guint delay; wmem_tree_t *subtree; wmem_tree_key_t key[8]; + channels_info_t *channels_info; guint32 interface_id; guint32 adapter_id; guint32 chandle; + guint32 psm; guint32 direction; - guint32 type; guint32 cid; guint32 frame_number; - cid_type_data_t *cid_type_data; sep_entry_t *sep; tvbuff_t *next_tvb; guint32 seid; @@ -1082,234 +1116,186 @@ dissect_btavdtp(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void *data) l2cap_data = (btl2cap_data_t *) data; DISSECTOR_ASSERT(l2cap_data); - if (!force_avdtp && !pinfo->fd->flags.visited && (l2cap_data->first_scid_frame == pinfo->fd->num || - l2cap_data->first_dcid_frame == pinfo->fd->num)) { - cid_type_data = wmem_new(wmem_file_scope(), cid_type_data_t); - cid_type_data->interface_id = l2cap_data->interface_id; - cid_type_data->adapter_id = l2cap_data->adapter_id; - cid_type_data->chandle = l2cap_data->chandle; - cid_type_data->type = STREAM_TYPE_MEDIA; - cid_type_data->cid = l2cap_data->cid; - cid_type_data->sep = NULL; - - /* heuristics for recognize signal AVDTP: first packet must be Discover Command */ - if ((tvb_get_guint8(tvb, offset) & 0x0F) == 0x00 && - tvb_get_guint8(tvb, offset + 1) == 0x01 && - tvb_length_remaining(tvb, offset) == HEADER_SIZE) { - /* It is AVDTP Signaling cmd side */ - cid_type_data->type = STREAM_TYPE_SIGNAL; - } else if ((tvb_get_guint8(tvb, offset) & 0x0F) == 0x02 && - tvb_get_guint8(tvb, offset + 1) == 0x01 && - tvb_length_remaining(tvb, offset) <= SEP_MAX * SEP_SIZE + HEADER_SIZE && - !(tvb_length_remaining(tvb, offset) % SEP_SIZE)) { - /* It is AVDTP Signaling rsp side */ - cid_type_data->type = STREAM_TYPE_SIGNAL; - } else { - interface_id = cid_type_data->interface_id; - adapter_id = cid_type_data->adapter_id; - chandle = cid_type_data->chandle; - frame_number = pinfo->fd->num; - - key[0].length = 1; - key[0].key = &interface_id; - key[1].length = 1; - key[1].key = &adapter_id; - key[2].length = 1; - key[2].key = &chandle; - key[3].length = 0; - key[3].key = NULL; - - subtree = (wmem_tree_t *) wmem_tree_lookup32_array(sep_open, key); - sep = (subtree) ? (sep_entry_t *) wmem_tree_lookup32_le(subtree, frame_number) : NULL; - if (sep && sep->state == SEP_STATE_OPEN) { - sep->state = SEP_STATE_IN_USE; - cid_type_data->sep = sep; - } - } - - interface_id = cid_type_data->interface_id; - adapter_id = cid_type_data->adapter_id; - chandle = cid_type_data->chandle; - type = cid_type_data->type; - cid = cid_type_data->cid; - frame_number = pinfo->fd->num; - - key[0].length = 1; - key[0].key = &interface_id; - key[1].length = 1; - key[1].key = &adapter_id; - key[2].length = 1; - key[2].key = &chandle; - key[3].length = 1; - key[3].key = &cid; - key[4].length = 1; - key[4].key = &direction; - key[5].length = 1; - key[5].key = &type; - key[6].length = 1; - key[6].key = &frame_number; - key[7].length = 0; - key[7].key = NULL; - - wmem_tree_insert32_array(cid_to_type_table, key, cid_type_data); - } - interface_id = l2cap_data->interface_id; adapter_id = l2cap_data->adapter_id; chandle = l2cap_data->chandle; + psm = l2cap_data->psm; cid = l2cap_data->cid; frame_number = pinfo->fd->num; - if (!force_avdtp) { - key[0].length = 1; - key[0].key = &interface_id; - key[1].length = 1; - key[1].key = &adapter_id; - key[2].length = 1; - key[2].key = &chandle; - key[3].length = 1; - key[3].key = &cid; - key[4].length = 1; - key[4].key = &direction; - key[5].length = 0; - key[5].key = NULL; - subtree = (wmem_tree_t *) wmem_tree_lookup32_array(cid_to_type_table, key); - if (subtree) { - wmem_tree_t *type_tree; - - type_tree = (wmem_tree_t *) wmem_tree_lookup32(subtree, STREAM_TYPE_MEDIA); - if (!type_tree) - type_tree = (wmem_tree_t *) wmem_tree_lookup32(subtree, STREAM_TYPE_SIGNAL); - subtree = type_tree; - } - cid_type_data = (subtree) ? (cid_type_data_t *) wmem_tree_lookup32_le(subtree, frame_number) : NULL; - if (cid_type_data && cid_type_data->type == STREAM_TYPE_MEDIA) { - /* AVDTP Media */ + key[0].length = 1; + key[0].key = &interface_id; + key[1].length = 1; + key[1].key = &adapter_id; + key[2].length = 1; + key[2].key = &chandle; + key[3].length = 1; + key[3].key = &psm; + key[4].length = 0; + key[4].key = NULL; + + subtree = (wmem_tree_t *) wmem_tree_lookup32_array(channels, key); + channels_info = (subtree) ? (channels_info_t *) wmem_tree_lookup32_le(subtree, frame_number) : NULL; + if (!(channels_info && channels_info->disconnect_in_frame >= pinfo->fd->num)) { + + channels_info = (channels_info_t *) wmem_new (wmem_file_scope(), channels_info_t); + channels_info->control_scid = l2cap_data->scid; + channels_info->control_dcid = l2cap_data->dcid; + channels_info->media_scid = -1; + channels_info->media_dcid = -1; + channels_info->disconnect_in_frame = G_MAXUINT32; + channels_info->sep = NULL; - if (!cid_type_data->sep) { - ti = proto_tree_add_item(tree, proto_btavdtp, tvb, offset, -1, ENC_NA); - btavdtp_tree = proto_item_add_subtree(ti, ett_btavdtp); + if (!pinfo->fd->flags.visited) { + key[4].length = 1; + key[4].key = &frame_number; + key[5].length = 0; + key[5].key = NULL; - col_append_fstr(pinfo->cinfo, COL_INFO, "Media stream on cid=0x%04x", l2cap_data->cid); - proto_tree_add_item(btavdtp_tree, hf_btavdtp_data, tvb, offset, -1, ENC_NA); - } else { - col_append_fstr(pinfo->cinfo, COL_INFO, "Media stream ACP SEID [%u - %s %s]", - cid_type_data->sep->seid, get_sep_media_type( - cid_type_data->interface_id, - cid_type_data->adapter_id, - cid_type_data->chandle, - direction, - cid_type_data->sep->seid, - pinfo->fd->num), - get_sep_type(cid_type_data->interface_id, - cid_type_data->adapter_id, - cid_type_data->chandle, - direction, - cid_type_data->sep->seid, - pinfo->fd->num)); - - if (cid_type_data->sep->media_type == MEDIA_TYPE_AUDIO) { - sep_data_t sep_data; - media_packet_info_t *previous_media_packet_info; - media_packet_info_t *current_media_packet_info; - nstime_t first_abs_ts; - gdouble cummulative_frame_duration; - - sep_data.codec = cid_type_data->sep->codec; - sep_data.acp_seid = cid_type_data->sep->seid; - sep_data.int_seid = cid_type_data->sep->int_seid; - sep_data.content_protection_type = cid_type_data->sep->content_protection_type; - - interface_id = cid_type_data->interface_id; - adapter_id = cid_type_data->adapter_id; - chandle = cid_type_data->chandle; - cid = cid_type_data->cid; - frame_number = pinfo->fd->num; + channels_info->stream_numbers = wmem_tree_new(wmem_file_scope()); + wmem_tree_insert32_array(channels, key, channels_info); + } else { + channels_info->stream_numbers = NULL; + } + } - key[0].length = 1; - key[0].key = &interface_id; - key[1].length = 1; - key[1].key = &adapter_id; - key[2].length = 1; - key[2].key = &chandle; - key[3].length = 1; - key[3].key = &cid; - key[4].length = 1; - key[4].key = &direction; - key[5].length = 0; - key[5].key = NULL; - subtree = (wmem_tree_t *) wmem_tree_lookup32_array(media_packet_times, key); + if (!(l2cap_data->scid == channels_info->control_scid && + l2cap_data->dcid == channels_info->control_dcid) && + (channels_info->media_scid == -1 || + (l2cap_data->scid == channels_info->media_scid && + l2cap_data->dcid == channels_info->media_dcid))) { - previous_media_packet_info = (subtree) ? (media_packet_info_t *) wmem_tree_lookup32_le(subtree, frame_number - 1) : NULL; - if (previous_media_packet_info) { - sep_data.previous_media_packet_info = previous_media_packet_info; - first_abs_ts = previous_media_packet_info->first_abs_ts; - cummulative_frame_duration = previous_media_packet_info->cummulative_frame_duration; - } else { - first_abs_ts = pinfo->fd->abs_ts; - cummulative_frame_duration = 0.0; - sep_data.previous_media_packet_info = (media_packet_info_t *) wmem_new(wmem_epan_scope(), media_packet_info_t); - sep_data.previous_media_packet_info->abs_ts = pinfo->fd->abs_ts; - sep_data.previous_media_packet_info->first_abs_ts = first_abs_ts; - sep_data.previous_media_packet_info->cummulative_frame_duration = cummulative_frame_duration; - } + if (!pinfo->fd->flags.visited && channels_info->media_scid == -1) { + channels_info->media_scid = l2cap_data->scid; + channels_info->media_dcid = l2cap_data->dcid; + channels_info->media_is_local_psm = l2cap_data->is_local_psm; + } + /* Media Channel */ - if (!pinfo->fd->flags.visited) { - key[5].length = 1; - key[5].key = &frame_number; - key[6].length = 0; - key[6].key = NULL; + if (!channels_info->sep) { + ti = proto_tree_add_item(tree, proto_btavdtp, tvb, offset, -1, ENC_NA); + btavdtp_tree = proto_item_add_subtree(ti, ett_btavdtp); - current_media_packet_info = wmem_new(wmem_file_scope(), media_packet_info_t); - current_media_packet_info->abs_ts = pinfo->fd->abs_ts; - current_media_packet_info->first_abs_ts = first_abs_ts; - current_media_packet_info->cummulative_frame_duration = cummulative_frame_duration; + col_append_fstr(pinfo->cinfo, COL_INFO, "Media stream on cid=0x%04x", l2cap_data->cid); + proto_tree_add_item(btavdtp_tree, hf_btavdtp_data, tvb, offset, -1, ENC_NA); + } else { + col_append_fstr(pinfo->cinfo, COL_INFO, "Media stream ACP SEID [%u - %s %s]", + channels_info->sep->seid, get_sep_media_type( + interface_id, adapter_id, chandle, direction, + channels_info->sep->seid, + frame_number), + get_sep_type(interface_id, adapter_id, chandle, direction, + channels_info->sep->seid, + frame_number)); + + if (channels_info->sep->media_type == MEDIA_TYPE_AUDIO) { + sep_data_t sep_data; + media_stream_number_value_t *media_stream_number_value; + media_packet_info_t *previous_media_packet_info; + media_packet_info_t *current_media_packet_info; + nstime_t first_abs_ts; + gdouble cummulative_frame_duration; + + sep_data.codec = channels_info->sep->codec; + sep_data.acp_seid = channels_info->sep->seid; + sep_data.int_seid = channels_info->sep->int_seid; + sep_data.content_protection_type = channels_info->sep->content_protection_type; + + media_stream_number_value = (media_stream_number_value_t *) wmem_tree_lookup32_le(channels_info->stream_numbers, frame_number - 1); + if (media_stream_number_value) { + sep_data.stream_number = media_stream_number_value->stream_number; + } else { + sep_data.stream_number = 1; + } - wmem_tree_insert32_array(media_packet_times, key, current_media_packet_info); - } + key[0].length = 1; + key[0].key = &interface_id; + key[1].length = 1; + key[1].key = &adapter_id; + key[2].length = 1; + key[2].key = &chandle; + key[3].length = 1; + key[3].key = &cid; + key[4].length = 1; + key[4].key = &direction; + key[5].length = 0; + key[5].key = NULL; - key[5].length = 0; - key[5].key = NULL; - subtree = (wmem_tree_t *) wmem_tree_lookup32_array(media_packet_times, key); - current_media_packet_info = (subtree) ? (media_packet_info_t *) wmem_tree_lookup32(subtree, frame_number) : NULL; - if (current_media_packet_info) - sep_data.current_media_packet_info = current_media_packet_info; - else - sep_data.current_media_packet_info = NULL; - - next_tvb = tvb_new_subset_remaining(tvb, offset); - call_dissector_with_data(bta2dp_handle, next_tvb, pinfo, tree, &sep_data); - } else if (cid_type_data->sep->media_type == MEDIA_TYPE_VIDEO) { - sep_data_t sep_data; - - sep_data.codec = cid_type_data->sep->codec; - sep_data.acp_seid = cid_type_data->sep->seid; - sep_data.int_seid = cid_type_data->sep->int_seid; - sep_data.content_protection_type = cid_type_data->sep->content_protection_type; - - next_tvb = tvb_new_subset_remaining(tvb, offset); - call_dissector_with_data(btvdp_handle, next_tvb, pinfo, tree, &sep_data); + subtree = (wmem_tree_t *) wmem_tree_lookup32_array(media_packet_times, key); + previous_media_packet_info = (subtree) ? (media_packet_info_t *) wmem_tree_lookup32_le(subtree, frame_number - 1) : NULL; + if (previous_media_packet_info && previous_media_packet_info->stream_number == sep_data.stream_number ) { + sep_data.previous_media_packet_info = previous_media_packet_info; + first_abs_ts = previous_media_packet_info->first_abs_ts; + cummulative_frame_duration = previous_media_packet_info->cummulative_frame_duration; } else { - ti = proto_tree_add_item(tree, proto_btavdtp, tvb, offset, -1, ENC_NA); - btavdtp_tree = proto_item_add_subtree(ti, ett_btavdtp); + first_abs_ts = pinfo->fd->abs_ts; + cummulative_frame_duration = 0.0; + sep_data.previous_media_packet_info = (media_packet_info_t *) wmem_new(wmem_epan_scope(), media_packet_info_t); + sep_data.previous_media_packet_info->abs_ts = pinfo->fd->abs_ts; + sep_data.previous_media_packet_info->first_abs_ts = first_abs_ts; + sep_data.previous_media_packet_info->cummulative_frame_duration = cummulative_frame_duration; + sep_data.previous_media_packet_info->stream_number = sep_data.stream_number; + } - col_append_fstr(pinfo->cinfo, COL_INFO, "Media stream on cid=0x%04x", l2cap_data->cid); - proto_tree_add_item(btavdtp_tree, hf_btavdtp_data, tvb, offset, -1, ENC_NA); + if (!pinfo->fd->flags.visited) { + key[5].length = 1; + key[5].key = &frame_number; + key[6].length = 0; + key[6].key = NULL; + + current_media_packet_info = wmem_new(wmem_file_scope(), media_packet_info_t); + current_media_packet_info->abs_ts = pinfo->fd->abs_ts; + current_media_packet_info->first_abs_ts = first_abs_ts; + current_media_packet_info->cummulative_frame_duration = cummulative_frame_duration; + current_media_packet_info->stream_number = sep_data.stream_number; + + wmem_tree_insert32_array(media_packet_times, key, current_media_packet_info); } - } - return tvb_length(tvb); - } else if (!(cid_type_data && cid_type_data->type == STREAM_TYPE_SIGNAL)) { - /* AVDTP not signaling - Unknown Media stream */ - ti = proto_tree_add_item(tree, proto_btavdtp, tvb, offset, -1, ENC_NA); - btavdtp_tree = proto_item_add_subtree(ti, ett_btavdtp); + key[5].length = 0; + key[5].key = NULL; - col_append_fstr(pinfo->cinfo, COL_INFO, "Unknown stream on cid=0x%04x", l2cap_data->cid); - proto_tree_add_item(btavdtp_tree, hf_btavdtp_data, tvb, offset, -1, ENC_NA); - return tvb_length(tvb); + subtree = (wmem_tree_t *) wmem_tree_lookup32_array(media_packet_times, key); + current_media_packet_info = (subtree) ? (media_packet_info_t *) wmem_tree_lookup32(subtree, frame_number) : NULL; + if (current_media_packet_info) + sep_data.current_media_packet_info = current_media_packet_info; + else + sep_data.current_media_packet_info = NULL; + + next_tvb = tvb_new_subset_remaining(tvb, offset); + call_dissector_with_data(bta2dp_handle, next_tvb, pinfo, tree, &sep_data); + } else if (channels_info->sep->media_type == MEDIA_TYPE_VIDEO) { + sep_data_t sep_data; + + sep_data.codec = channels_info->sep->codec; + sep_data.acp_seid = channels_info->sep->seid; + sep_data.int_seid = channels_info->sep->int_seid; + sep_data.content_protection_type = channels_info->sep->content_protection_type; + + next_tvb = tvb_new_subset_remaining(tvb, offset); + call_dissector_with_data(btvdp_handle, next_tvb, pinfo, tree, &sep_data); + } else { + ti = proto_tree_add_item(tree, proto_btavdtp, tvb, offset, -1, ENC_NA); + btavdtp_tree = proto_item_add_subtree(ti, ett_btavdtp); + + col_append_fstr(pinfo->cinfo, COL_INFO, "Media stream on cid=0x%04x", l2cap_data->cid); + proto_tree_add_item(btavdtp_tree, hf_btavdtp_data, tvb, offset, -1, ENC_NA); + } } + + return tvb_length(tvb); + } else if (!(l2cap_data->scid == channels_info->control_scid && + l2cap_data->dcid == channels_info->control_dcid)) { + /* Unknown Stream Channel */ + ti = proto_tree_add_item(tree, proto_btavdtp, tvb, offset, -1, ENC_NA); + btavdtp_tree = proto_item_add_subtree(ti, ett_btavdtp); + + col_append_fstr(pinfo->cinfo, COL_INFO, "Unknown channel stream on cid=0x%04x", l2cap_data->cid); + proto_tree_add_item(btavdtp_tree, hf_btavdtp_data, tvb, offset, -1, ENC_NA); + return tvb_length(tvb); } + /* Signaling Channel */ ti = proto_tree_add_item(tree, proto_btavdtp, tvb, offset, -1, ENC_NA); btavdtp_tree = proto_item_add_subtree(ti, ett_btavdtp); @@ -1508,6 +1494,24 @@ dissect_btavdtp(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void *data) offset += 1; break; } + if (message_type == MESSAGE_TYPE_ACCEPT && !pinfo->fd->flags.visited) { + + key[0].length = 1; + key[0].key = &interface_id; + key[1].length = 1; + key[1].key = &adapter_id; + key[2].length = 1; + key[2].key = &chandle; + key[3].length = 0; + key[3].key = NULL; + + subtree = (wmem_tree_t *) wmem_tree_lookup32_array(sep_open, key); + sep = (subtree) ? (sep_entry_t *) wmem_tree_lookup32_le(subtree, frame_number) : NULL; + if (sep && sep->state == SEP_STATE_OPEN) { + sep->state = SEP_STATE_IN_USE; + channels_info->sep = sep; + } + } break; case SIGNAL_ID_START: if (message_type == MESSAGE_TYPE_COMMAND) { @@ -1528,6 +1532,42 @@ dissect_btavdtp(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void *data) offset += 1; break; } + + if (message_type == MESSAGE_TYPE_ACCEPT && !pinfo->fd->flags.visited) { + media_stream_number_value_t *media_stream_number_value; + guint32 stream_number = 0; + + media_stream_number_value = (media_stream_number_value_t *) wmem_tree_lookup32_le(channels_info->stream_numbers, frame_number - 1); +#if RTP_PLAYER_WORKAROUND == TRUE + { + media_stream_number_value_t *file_scope_stream_number_value; + + if (media_stream_number_value) { + stream_number = media_stream_number_value->stream_number; + } else { + file_scope_stream_number_value = (media_stream_number_value_t *) wmem_tree_lookup32_le(file_scope_stream_number, frame_number - 1); + if (file_scope_stream_number_value) + stream_number = file_scope_stream_number_value->stream_number + 1; + else + stream_number = 0; + } + + file_scope_stream_number_value = wmem_new(wmem_file_scope(), media_stream_number_value_t); + file_scope_stream_number_value->stream_number = stream_number; + wmem_tree_insert32(file_scope_stream_number, frame_number, file_scope_stream_number_value); + } +#else + if (media_stream_number_value) + stream_number = media_stream_number_value->stream_number; + else + stream_number = 0; +#endif + + media_stream_number_value = wmem_new(wmem_file_scope(), media_stream_number_value_t); + media_stream_number_value->stream_number = stream_number + 1; + + wmem_tree_insert32(channels_info->stream_numbers, frame_number, media_stream_number_value); + } break; case SIGNAL_ID_CLOSE: if (message_type == MESSAGE_TYPE_COMMAND) { @@ -1541,6 +1581,10 @@ dissect_btavdtp(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void *data) offset += 1; break; } + if (!pinfo->fd->flags.visited && message_type == MESSAGE_TYPE_ACCEPT && + channels_info->disconnect_in_frame == G_MAXUINT32) { + channels_info->disconnect_in_frame = pinfo->fd->num; + } break; case SIGNAL_ID_SUSPEND: if (message_type == MESSAGE_TYPE_COMMAND) { @@ -1574,6 +1618,10 @@ dissect_btavdtp(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void *data) offset += 1; break; } + if (!pinfo->fd->flags.visited && message_type == MESSAGE_TYPE_ACCEPT && + channels_info->disconnect_in_frame == G_MAXUINT32) { + channels_info->disconnect_in_frame = pinfo->fd->num; + } break; case SIGNAL_ID_SECURITY_CONTROL: if (message_type == MESSAGE_TYPE_COMMAND) { @@ -2285,15 +2333,13 @@ proto_register_btavdtp(void) "Bluetooth Protocol AVDTP version: 1.3", "Version of protocol supported by this dissector."); - prefs_register_bool_preference(module, "avdtp.force", - "Force decoding as AVDTP Signaling", - "Force decoding as AVDTP Signaling", - &force_avdtp); - - sep_list = wmem_tree_new_autoreset(wmem_epan_scope(), wmem_file_scope()); - sep_open = wmem_tree_new_autoreset(wmem_epan_scope(), wmem_file_scope()); - cid_to_type_table = wmem_tree_new_autoreset(wmem_epan_scope(), wmem_file_scope()); /* cid: type */ - media_packet_times = wmem_tree_new_autoreset(wmem_epan_scope(), wmem_file_scope()); + channels = wmem_tree_new_autoreset(wmem_epan_scope(), wmem_file_scope()); + sep_list = wmem_tree_new_autoreset(wmem_epan_scope(), wmem_file_scope()); + sep_open = wmem_tree_new_autoreset(wmem_epan_scope(), wmem_file_scope()); + media_packet_times = wmem_tree_new_autoreset(wmem_epan_scope(), wmem_file_scope()); +#if RTP_PLAYER_WORKAROUND == TRUE + file_scope_stream_number = wmem_tree_new_autoreset(wmem_epan_scope(), wmem_file_scope()); +#endif } void @@ -2324,6 +2370,7 @@ dissect_bta2dp(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void *data) sep_data.int_seid = 0; sep_data.previous_media_packet_info = NULL; sep_data.current_media_packet_info = NULL; + sep_data.stream_number = 1; if (force_a2dp_scms_t || force_a2dp_codec != CODEC_DEFAULT) { if (force_a2dp_scms_t) @@ -2382,6 +2429,9 @@ dissect_bta2dp(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void *data) PROTO_ITEM_SET_GENERATED(pitem); } + pitem = proto_tree_add_uint(bta2dp_tree, hf_bta2dp_stream_number, tvb, 0, 0, sep_data.stream_number); + PROTO_ITEM_SET_GENERATED(pitem); + switch (sep_data.codec) { case CODEC_SBC: codec_dissector = sbc_handle; @@ -2402,8 +2452,16 @@ dissect_bta2dp(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void *data) bta2dp_codec_info.previous_media_packet_info = sep_data.previous_media_packet_info; bta2dp_codec_info.current_media_packet_info = sep_data.current_media_packet_info; - bluetooth_add_address(pinfo, &pinfo->net_dst, "BT A2DP", pinfo->fd->num, FALSE, &bta2dp_codec_info); +#if RTP_PLAYER_WORKAROUND == TRUE + /* XXX: Workaround to get multiple RTP streams, because converation are too + weak to recognize Bluetooth streams (key is: guint32 interface_id, guint32 adapter_id, guint32 chandle, guint32 cid, guint32 direction -> guint32 stream_number) */ + pinfo->srcport = sep_data.stream_number; + pinfo->destport = sep_data.stream_number; +#endif + + bluetooth_add_address(pinfo, &pinfo->net_dst, sep_data.stream_number, "BT A2DP", pinfo->fd->num, FALSE, &bta2dp_codec_info); call_dissector(rtp_handle, tvb, pinfo, tree); + offset += tvb_length_remaining(tvb, offset); return offset; @@ -2435,6 +2493,11 @@ proto_register_bta2dp(void) FT_UINT16, BASE_HEX, VALS(content_protection_type_vals), 0x0000, NULL, HFILL } }, + { &hf_bta2dp_stream_number, + { "Stream Number", "bta2dp.stream_number", + FT_UINT32, BASE_DEC, NULL, 0x00, + NULL, HFILL } + }, }; static gint *ett[] = { @@ -2567,7 +2630,7 @@ dissect_btvdp(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void *data) btvdp_codec_info.codec_dissector = codec_dissector; btvdp_codec_info.content_protection_type = sep_data.content_protection_type; - bluetooth_add_address(pinfo, &pinfo->net_dst, "BT VDP", pinfo->fd->num, TRUE, &btvdp_codec_info); + bluetooth_add_address(pinfo, &pinfo->net_dst, 0, "BT VDP", pinfo->fd->num, TRUE, &btvdp_codec_info); call_dissector(rtp_handle, tvb, pinfo, tree); offset += tvb_length_remaining(tvb, offset); diff --git a/epan/dissectors/packet-btavdtp.h b/epan/dissectors/packet-btavdtp.h index 33f44c8165..2f16e59673 100644 --- a/epan/dissectors/packet-btavdtp.h +++ b/epan/dissectors/packet-btavdtp.h @@ -31,6 +31,7 @@ typedef struct _media_packet_info_t { nstime_t abs_ts; nstime_t first_abs_ts; gdouble cummulative_frame_duration; + guint32 stream_number; } media_packet_info_t; typedef struct _bta2dp_codec_info_t { diff --git a/epan/dissectors/packet-btl2cap.c b/epan/dissectors/packet-btl2cap.c index 1dab0b2b77..09f71ec1a6 100644 --- a/epan/dissectors/packet-btl2cap.c +++ b/epan/dissectors/packet-btl2cap.c @@ -176,8 +176,8 @@ typedef struct _psm_data_t { guint32 interface_id; guint32 adapter_id; guint32 chandle; - guint32 scid; - guint32 dcid; + gint32 scid; + gint32 dcid; guint32 first_scid_frame; guint32 first_dcid_frame; guint16 psm; @@ -1708,6 +1708,8 @@ dissect_btl2cap(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void *data) l2cap_data->adapter_id = (acl_data) ? acl_data->adapter_id : HCI_ADAPTER_DEFAULT; l2cap_data->chandle = (acl_data) ? acl_data->chandle : 0; l2cap_data->cid = cid; + l2cap_data->scid = -1; + l2cap_data->dcid = -1; l2cap_data->is_local_psm = FALSE; l2cap_data->psm = 0; l2cap_data->first_scid_frame = 0; @@ -1880,6 +1882,8 @@ dissect_btl2cap(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void *data) col_append_str(pinfo->cinfo, COL_INFO, "Connectionless reception channel"); psm = tvb_get_letohs(tvb, offset); + l2cap_data->scid = psm_data->scid; + l2cap_data->dcid = psm_data->dcid; l2cap_data->psm = psm; if (p_get_proto_data(pinfo->pool, pinfo, proto_btl2cap, BTL2CAP_PSM_CONV ) == NULL) { @@ -2006,6 +2010,8 @@ dissect_btl2cap(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void *data) } psm = psm_data->psm; + l2cap_data->scid = psm_data->scid; + l2cap_data->dcid = psm_data->dcid; l2cap_data->psm = psm; l2cap_data->is_local_psm = psm_data->local_service; l2cap_data->first_scid_frame = psm_data->first_scid_frame; diff --git a/epan/dissectors/packet-btl2cap.h b/epan/dissectors/packet-btl2cap.h index 66ad217c81..cd3258548d 100644 --- a/epan/dissectors/packet-btl2cap.h +++ b/epan/dissectors/packet-btl2cap.h @@ -54,6 +54,8 @@ typedef struct _btl2cap_data_t { guint32 adapter_id; guint16 chandle; /* only low 12 bits used */ guint16 cid; + gint32 scid; + gint32 dcid; gboolean is_local_psm; /* otherwise it is PSM in remote device */ guint16 psm; guint32 first_scid_frame; diff --git a/epan/dissectors/packet-rtp.c b/epan/dissectors/packet-rtp.c index cf7fe6da5b..6ca1e8d428 100644 --- a/epan/dissectors/packet-rtp.c +++ b/epan/dissectors/packet-rtp.c @@ -1131,7 +1131,7 @@ rtp_dyn_payload_free(rtp_dyn_payload_t *rtp_dyn_payload) } void -bluetooth_add_address(packet_info *pinfo, address *addr, +bluetooth_add_address(packet_info *pinfo, address *addr, guint32 stream_number, const gchar *setup_method, guint32 setup_frame_number, gboolean is_video, void *data) { @@ -1154,14 +1154,14 @@ bluetooth_add_address(packet_info *pinfo, address *addr, * Check if the ip address and port combination is not * already registered as a conversation. */ - p_conv = find_conversation(setup_frame_number, addr, &null_addr, PT_BLUETOOTH, 0, 0, + p_conv = find_conversation(setup_frame_number, addr, &null_addr, PT_BLUETOOTH, stream_number, stream_number, NO_ADDR_B | NO_PORT_B); /* * If not, create a new conversation. */ if (!p_conv || p_conv->setup_frame != setup_frame_number) { - p_conv = conversation_new(setup_frame_number, addr, &null_addr, PT_BLUETOOTH, 0, 0, + p_conv = conversation_new(setup_frame_number, addr, &null_addr, PT_BLUETOOTH, stream_number, stream_number, NO_ADDR2 | NO_PORT2); } diff --git a/epan/dissectors/packet-rtp.h b/epan/dissectors/packet-rtp.h index 5fea4739bf..db60be435e 100644 --- a/epan/dissectors/packet-rtp.h +++ b/epan/dissectors/packet-rtp.h @@ -210,6 +210,6 @@ void srtp_add_address(packet_info *pinfo, /* Add an Bluetooth conversation with the given details */ void -bluetooth_add_address(packet_info *pinfo, address *addr, +bluetooth_add_address(packet_info *pinfo, address *addr, guint32 stream_number, const gchar *setup_method, guint32 setup_frame_number, gboolean is_video, void *data); |