RTP: SSRCs on the same RTP session have their own number space

RFC 3350 Section 5.2 notes: "An SSRC is defined to identify a single
timing and sequence number space." (See also RFC 8872 Section 3.2.2.
"Note that the RTP sequence number and RTP timestamp are scoped by
the SSRC and are thus specific per RTP stream."

Therefore, the RTP conversation data needs to store the most
recently seen sequence number and timestamp scoped by SSRC, to
avoid incorrect judgments about when the sequence number and
timestamp have undergone cycles (and thus incorrect extended
sequence number and extended timestamp calculations.)

The RTP packet data, being for a single SSRC, can continue
to store only a single value for the extended sequence number
and timestamp. This means that the conversation level data
and packet data are no longer the same struct. Rename a
few things to make it clearer when the packet data is being
references versus the conversation data.

In addition to fixing certain RTP sessions with multiple SSRCs,
this better handles cases where the same 5-tuple is reused, and
the new RTP session starts transmitting packets after a SDP offer
but before an answer, in the SIP offer/answer model. In such
cases we may still associate the RTP packets before the answer
with the previous SDP, but (if this is the first time the SSRC
is used, which it should be for that RTP sender) the extended
sequence number will in both cases be that of the first cycle,
instead of possibly being associated with a later cycle due to
a different SSRC's sequence number space.

Fix #19219.
This commit is contained in:
John Thacker 2023-07-21 10:48:26 -04:00
parent 13f21ebd59
commit a1e4aea6ff
2 changed files with 190 additions and 158 deletions

View File

@ -98,6 +98,31 @@ typedef struct _rtp_private_conv_info {
wmem_tree_t *multisegment_pdus;
} rtp_private_conv_info;
typedef struct _rtp_number_space {
uint32_t extended_seqno;
uint64_t extended_timestamp;
} rtp_number_space;
/** Info to save in RTP conversation */
struct _rtp_internal_conversation_info
{
gchar method[MAX_RTP_SETUP_METHOD_SIZE + 1];
guint32 frame_number; /**> the frame where this conversation is started */
guint32 media_types;
rtp_dyn_payload_t* rtp_dyn_payload; /**> the dynamic RTP payload info - see comments above */
wmem_map_t* ssrc_number_space; /**> maps the SSRCs to the last seen seqno and timestamp
* for that SSRC in the conversation */
struct _rtp_private_conv_info* rtp_conv_info; /**> conversation info private
* to the rtp dissector
*/
struct srtp_info* srtp_info; /* SRTP context */
bta2dp_codec_info_t* bta2dp_info;
btvdp_codec_info_t* btvdp_info;
wmem_array_t* rtp_sdp_setup_info_list; /**> List with data from all SDP occurencies for this steram holding a call ID)*/
};
typedef struct {
char *encoding_name;
int sample_rate;
@ -271,7 +296,7 @@ void proto_reg_handoff_pkt_ccc(void);
static gint dissect_rtp(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void *data);
static void show_setup_info(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree);
static struct _rtp_conversation_info *get_conv_info(packet_info *pinfo, struct _rtp_info *rtp_info);
static struct _rtp_conversation_info *get_rtp_packet_info(packet_info *pinfo, struct _rtp_info *rtp_info);
/* Preferences bool to control whether or not setup info should be shown */
static gboolean global_rtp_show_setup_info = TRUE;
@ -1061,7 +1086,7 @@ bluetooth_add_address(packet_info *pinfo, address *addr, guint32 stream_number,
{
address null_addr;
conversation_t* p_conv;
struct _rtp_conversation_info *p_conv_data = NULL;
struct _rtp_internal_conversation_info *p_conv_data = NULL;
/*
* If this isn't the first time this packet has been processed,
* we've already done this work, so we don't need to do it
@ -1095,20 +1120,16 @@ bluetooth_add_address(packet_info *pinfo, address *addr, guint32 stream_number,
/*
* Check if the conversation has data associated with it.
*/
p_conv_data = (struct _rtp_conversation_info *)conversation_get_proto_data(p_conv, proto_rtp);
p_conv_data = (struct _rtp_internal_conversation_info *)conversation_get_proto_data(p_conv, proto_rtp);
/*
* If not, add a new data item.
*/
if (! p_conv_data) {
/* Create conversation data */
p_conv_data = wmem_new0(wmem_file_scope(), struct _rtp_conversation_info);
p_conv_data = wmem_new0(wmem_file_scope(), struct _rtp_internal_conversation_info);
/* start this at 0x10000 so that we cope gracefully with the
* first few packets being out of order (hence 0,65535,1,2,...)
*/
p_conv_data->extended_seqno = 0x10000;
p_conv_data->extended_timestamp = 0x100000000;
p_conv_data->ssrc_number_space = wmem_map_new(wmem_file_scope(), g_direct_hash, g_direct_equal);
p_conv_data->rtp_conv_info = wmem_new(wmem_file_scope(), rtp_private_conv_info);
p_conv_data->rtp_conv_info->multisegment_pdus = wmem_tree_new(wmem_file_scope());
conversation_add_proto_data(p_conv, proto_rtp, p_conv_data);
@ -1165,7 +1186,7 @@ srtp_add_address(packet_info *pinfo, const port_type ptype, address *addr, int p
{
address null_addr;
conversation_t* p_conv, *sdp_conv;
struct _rtp_conversation_info *p_conv_data;
struct _rtp_internal_conversation_info *p_conv_data;
wmem_array_t *rtp_conv_info_list = NULL;
/*
@ -1196,7 +1217,7 @@ srtp_add_address(packet_info *pinfo, const port_type ptype, address *addr, int p
/*
* Check if the conversation has data associated with it.
*/
p_conv_data = (struct _rtp_conversation_info *)conversation_get_proto_data(p_conv, proto_rtp);
p_conv_data = (struct _rtp_internal_conversation_info *)conversation_get_proto_data(p_conv, proto_rtp);
if (p_conv_data) {
rtp_conv_info_list = p_conv_data->rtp_sdp_setup_info_list;
}
@ -1237,7 +1258,7 @@ srtp_add_address(packet_info *pinfo, const port_type ptype, address *addr, int p
/*
* Check if the conversation has data associated with it.
*/
p_conv_data = (struct _rtp_conversation_info *)conversation_get_proto_data(p_conv, proto_rtp);
p_conv_data = (struct _rtp_internal_conversation_info *)conversation_get_proto_data(p_conv, proto_rtp);
/*
* If not, add a new data item.
@ -1246,13 +1267,9 @@ srtp_add_address(packet_info *pinfo, const port_type ptype, address *addr, int p
DPRINT(("creating new conversation data"));
/* Create conversation data */
p_conv_data = wmem_new0(wmem_file_scope(), struct _rtp_conversation_info);
p_conv_data = wmem_new0(wmem_file_scope(), struct _rtp_internal_conversation_info);
/* start this at 0x10000 so that we cope gracefully with the
* first few packets being out of order (hence 0,65535,1,2,...)
*/
p_conv_data->extended_seqno = 0x10000;
p_conv_data->extended_timestamp = 0x100000000;
p_conv_data->ssrc_number_space = wmem_map_new(wmem_file_scope(), g_direct_hash, g_direct_equal);
p_conv_data->rtp_conv_info = wmem_new(wmem_file_scope(), rtp_private_conv_info);
p_conv_data->rtp_conv_info->multisegment_pdus = wmem_tree_new(wmem_file_scope());
DINDENT();
@ -1408,15 +1425,14 @@ dissect_rtp_heur(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void* data
if (!find_conversation(pinfo->num, &pinfo->net_dst, &pinfo->net_src, conversation_pt_to_conversation_type(pinfo->ptype),
pinfo->destport, pinfo->srcport, NO_ADDR_B)) {
conversation_t *p_conv;
struct _rtp_conversation_info *p_conv_data;
struct _rtp_internal_conversation_info *p_conv_data;
p_conv = conversation_new(pinfo->num, &pinfo->net_dst, &pinfo->net_src, conversation_pt_to_conversation_type(pinfo->ptype),
pinfo->destport, pinfo->srcport, NO_ADDR2);
p_conv_data = (struct _rtp_conversation_info *)conversation_get_proto_data(p_conv, proto_rtp);
p_conv_data = (struct _rtp_internal_conversation_info *)conversation_get_proto_data(p_conv, proto_rtp);
if (! p_conv_data) {
/* Create conversation data */
p_conv_data = wmem_new0(wmem_file_scope(), struct _rtp_conversation_info);
p_conv_data->extended_seqno = 0x10000;
p_conv_data->extended_timestamp = 0x100000000;
p_conv_data = wmem_new0(wmem_file_scope(), struct _rtp_internal_conversation_info);
p_conv_data->ssrc_number_space = wmem_map_new(wmem_file_scope(), g_direct_hash, g_direct_equal);
p_conv_data->rtp_conv_info = wmem_new(wmem_file_scope(), rtp_private_conv_info);
p_conv_data->rtp_conv_info->multisegment_pdus = wmem_tree_new(wmem_file_scope());
conversation_add_proto_data(p_conv, proto_rtp, p_conv_data);
@ -1440,7 +1456,7 @@ process_rtp_payload(tvbuff_t *newtvb, packet_info *pinfo, proto_tree *tree,
proto_tree *rtp_tree, unsigned int payload_type,
struct _rtp_info *rtp_info)
{
struct _rtp_conversation_info *p_conv_data;
struct _rtp_conversation_info *p_packet_data;
int payload_len;
struct srtp_info *srtp_info;
int offset = 0;
@ -1449,9 +1465,9 @@ process_rtp_payload(tvbuff_t *newtvb, packet_info *pinfo, proto_tree *tree,
payload_len = tvb_captured_length_remaining(newtvb, offset);
/* first check if this is added as an SRTP stream - if so, don't try to dissector the payload data for now */
p_conv_data = (struct _rtp_conversation_info *)p_get_proto_data(wmem_file_scope(), pinfo, proto_rtp, RTP_CONVERSATION_PROTO_DATA);
if (p_conv_data && p_conv_data->srtp_info) {
srtp_info = p_conv_data->srtp_info;
p_packet_data = (struct _rtp_conversation_info *)p_get_proto_data(wmem_file_scope(), pinfo, proto_rtp, RTP_CONVERSATION_PROTO_DATA);
if (p_packet_data && p_packet_data->srtp_info) {
srtp_info = p_packet_data->srtp_info;
payload_len -= srtp_info->mki_len + srtp_info->auth_tag_len;
#if 0
#error Currently the srtp_info structure contains no cipher data, see packet-sdp.c adding dummy_srtp_info structure
@ -1478,37 +1494,37 @@ process_rtp_payload(tvbuff_t *newtvb, packet_info *pinfo, proto_tree *tree,
}
return;
} if (p_conv_data && p_conv_data->bta2dp_info) {
} if (p_packet_data && p_packet_data->bta2dp_info) {
tvbuff_t *nexttvb;
gint suboffset = 0;
if (p_conv_data->bta2dp_info->content_protection_type == BTAVDTP_CONTENT_PROTECTION_TYPE_SCMS_T) {
if (p_packet_data->bta2dp_info->content_protection_type == BTAVDTP_CONTENT_PROTECTION_TYPE_SCMS_T) {
nexttvb = tvb_new_subset_length(newtvb, 0, 1);
call_dissector(bta2dp_content_protection_header_scms_t, nexttvb, pinfo, tree);
suboffset = 1;
}
nexttvb = tvb_new_subset_remaining(newtvb, suboffset);
if (p_conv_data->bta2dp_info->codec_dissector)
call_dissector_with_data(p_conv_data->bta2dp_info->codec_dissector, nexttvb, pinfo, tree, p_conv_data->bta2dp_info);
if (p_packet_data->bta2dp_info->codec_dissector)
call_dissector_with_data(p_packet_data->bta2dp_info->codec_dissector, nexttvb, pinfo, tree, p_packet_data->bta2dp_info);
else
call_data_dissector(nexttvb, pinfo, tree);
return;
} if (p_conv_data && p_conv_data->btvdp_info) {
} if (p_packet_data && p_packet_data->btvdp_info) {
tvbuff_t *nexttvb;
gint suboffset = 0;
if (p_conv_data->btvdp_info->content_protection_type == BTAVDTP_CONTENT_PROTECTION_TYPE_SCMS_T) {
if (p_packet_data->btvdp_info->content_protection_type == BTAVDTP_CONTENT_PROTECTION_TYPE_SCMS_T) {
nexttvb = tvb_new_subset_length(newtvb, 0, 1);
call_dissector(btvdp_content_protection_header_scms_t, nexttvb, pinfo, tree);
suboffset = 1;
}
nexttvb = tvb_new_subset_remaining(newtvb, suboffset);
if (p_conv_data->btvdp_info->codec_dissector)
call_dissector_with_data(p_conv_data->btvdp_info->codec_dissector, nexttvb, pinfo, tree, p_conv_data->btvdp_info);
if (p_packet_data->btvdp_info->codec_dissector)
call_dissector_with_data(p_packet_data->btvdp_info->codec_dissector, nexttvb, pinfo, tree, p_packet_data->btvdp_info);
else
call_data_dissector(nexttvb, pinfo, tree);
@ -1518,10 +1534,10 @@ process_rtp_payload(tvbuff_t *newtvb, packet_info *pinfo, proto_tree *tree,
rtp_data = proto_tree_add_item(rtp_tree, hf_rtp_data, newtvb, 0, -1, ENC_NA);
/* We have checked for !p_conv_data->bta2dp_info && !p_conv_data->btvdp_info above*/
if (p_conv_data && payload_type >= PT_UNDF_96 && payload_type <= PT_UNDF_127) {
if (p_packet_data && payload_type >= PT_UNDF_96 && payload_type <= PT_UNDF_127) {
/* if the payload type is dynamic, we check if the conv is set and we look for the pt definition */
if (p_conv_data->rtp_dyn_payload) {
const gchar *payload_type_str = rtp_dyn_payload_get_name(p_conv_data->rtp_dyn_payload, payload_type);
if (p_packet_data->rtp_dyn_payload) {
const gchar *payload_type_str = rtp_dyn_payload_get_name(p_packet_data->rtp_dyn_payload, payload_type);
if (payload_type_str) {
int len;
len = dissector_try_string(rtp_dyn_pt_dissector_table,
@ -1564,17 +1580,17 @@ dissect_rtp_data(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree,
struct _rtp_info *rtp_info)
{
tvbuff_t *newtvb;
struct _rtp_conversation_info *p_conv_data;
struct _rtp_conversation_info *p_packet_data;
gboolean must_desegment = FALSE;
rtp_private_conv_info *finfo = NULL;
rtp_multisegment_pdu *msp;
guint32 seqno;
/* Retrieve RTPs idea of a converation */
p_conv_data = (struct _rtp_conversation_info *)p_get_proto_data(wmem_file_scope(), pinfo, proto_rtp, RTP_CONVERSATION_PROTO_DATA);
/* Retrieve RTPs idea of a conversation */
p_packet_data = (struct _rtp_conversation_info *)p_get_proto_data(wmem_file_scope(), pinfo, proto_rtp, RTP_CONVERSATION_PROTO_DATA);
if(p_conv_data != NULL)
finfo = p_conv_data->rtp_conv_info;
if(p_packet_data != NULL)
finfo = p_packet_data->rtp_conv_info;
if(finfo == NULL || !desegment_rtp) {
/* Hand the whole lot off to the subdissector */
@ -1583,7 +1599,7 @@ dissect_rtp_data(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree,
return;
}
seqno = p_conv_data->extended_seqno;
seqno = p_packet_data->extended_seqno;
pinfo->can_desegment = 2;
pinfo->desegment_offset = 0;
@ -1592,7 +1608,7 @@ dissect_rtp_data(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree,
#ifdef DEBUG_FRAGMENTS
ws_debug("%d: RTP Part of convo %d(%p); seqno %d",
pinfo->num,
p_conv_data->frame_number, p_conv_data,
p_packet_data->frame_number, p_packet_data,
seqno
);
#endif
@ -1764,7 +1780,7 @@ dissect_rtp_rfc2198(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void* d
proto_tree *rfc2198_tree;
rfc2198_hdr *hdr_last;
rfc2198_hdr *hdr_chain = NULL;
struct _rtp_conversation_info *p_conv_data;
struct _rtp_conversation_info *p_packet_data;
struct _rtp_info* rtp_info = NULL;
struct _rtp_info rfc2198_rtp_info;
volatile unsigned rtp_info_offset = 0;
@ -1775,8 +1791,8 @@ dissect_rtp_rfc2198(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void* d
rtp_info_offset = rtp_info->info_payload_offset;
}
/* Retrieve RTPs idea of a converation */
p_conv_data = (struct _rtp_conversation_info *)p_get_proto_data(wmem_file_scope(), pinfo, proto_rtp, RTP_CONVERSATION_PROTO_DATA);
/* Retrieve RTPs idea of a conversation */
p_packet_data = (struct _rtp_conversation_info *)p_get_proto_data(wmem_file_scope(), pinfo, proto_rtp, RTP_CONVERSATION_PROTO_DATA);
/* Add try to RFC 2198 data */
rfc2198_tree = proto_tree_add_subtree(tree, tvb, offset, -1, ett_rtp_rfc2198, NULL, "RFC 2198: Redundant Audio Data");
@ -1805,8 +1821,8 @@ dissect_rtp_rfc2198(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void* d
/* if it is dynamic payload, let use the conv data to see if it is defined */
if ((hdr_new->pt > 95) && (hdr_new->pt < 128)) {
if (p_conv_data && p_conv_data->rtp_dyn_payload){
rtp_dyn_payload_get_full(p_conv_data->rtp_dyn_payload, hdr_new->pt, &payload_type_str, &hdr_new->payload_rate, &hdr_new->payload_channels, &hdr_new->payload_fmtp_map);
if (p_packet_data && p_packet_data->rtp_dyn_payload){
rtp_dyn_payload_get_full(p_packet_data->rtp_dyn_payload, hdr_new->pt, &payload_type_str, &hdr_new->payload_rate, &hdr_new->payload_channels, &hdr_new->payload_fmtp_map);
hdr_new->payload_type_str = payload_type_str;
} else {
/* See if we have a dissector tied to the dynamic payload
@ -2082,7 +2098,7 @@ dissect_rtp( tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void *data _U_
guint16 seq_num;
guint32 timestamp;
guint32 sync_src;
struct _rtp_conversation_info *p_conv_data;
struct _rtp_conversation_info *p_packet_data;
/*struct srtp_info *srtp_info = NULL;*/
/*unsigned int srtp_offset;*/
const char *pt = NULL;
@ -2304,36 +2320,15 @@ dissect_rtp( tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void *data _U_
}
/* Look for conv and add to the frame if found */
p_conv_data = get_conv_info(pinfo, rtp_info);
if (p_conv_data) {
rtp_info->info_media_types = p_conv_data->media_types;
rtp_info->info_extended_seq_num = p_conv_data->extended_seqno;
rtp_info->info_extended_timestamp = p_conv_data->extended_timestamp;
} else {
/* Create a conversation in case none exists (decode as is used for marking the packet as RTP) */
conversation_t *p_conv;
p_conv = conversation_new(pinfo->num, &pinfo->net_dst, &pinfo->net_src, conversation_pt_to_conversation_type(pinfo->ptype),
pinfo->destport, pinfo->srcport, NO_ADDR2);
p_conv_data = (struct _rtp_conversation_info *)conversation_get_proto_data(p_conv, proto_rtp);
if (! p_conv_data) {
/* Create conversation data */
p_conv_data = wmem_new0(wmem_file_scope(), struct _rtp_conversation_info);
p_conv_data->extended_seqno = 0x10000;
p_conv_data->extended_timestamp = 0x100000000;
p_conv_data->rtp_conv_info = wmem_new(wmem_file_scope(), rtp_private_conv_info);
p_conv_data->rtp_conv_info->multisegment_pdus = wmem_tree_new(wmem_file_scope());
conversation_add_proto_data(p_conv, proto_rtp, p_conv_data);
}
(void) g_strlcpy(p_conv_data->method, "DECODE AS", MAX_RTP_SETUP_METHOD_SIZE+1);
p_conv_data->frame_number = pinfo->num;
p_conv_data->media_types = 0;
p_conv_data->srtp_info = NULL;
p_conv_data->bta2dp_info = NULL;
p_conv_data->btvdp_info = NULL;
p_packet_data = get_rtp_packet_info(pinfo, rtp_info);
if (p_packet_data) {
rtp_info->info_media_types = p_packet_data->media_types;
rtp_info->info_extended_seq_num = p_packet_data->extended_seqno;
rtp_info->info_extended_timestamp = p_packet_data->extended_timestamp;
}
if (p_conv_data && p_conv_data->srtp_info) is_srtp = TRUE;
if (p_packet_data && p_packet_data->srtp_info) is_srtp = TRUE;
rtp_info->info_is_srtp = is_srtp;
col_set_str( pinfo->cinfo, COL_PROTOCOL, (is_srtp) ? "SRTP" : "RTP" );
@ -2348,15 +2343,15 @@ dissect_rtp( tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void *data _U_
}
#endif
if (p_conv_data && p_conv_data->bta2dp_info && p_conv_data->bta2dp_info->codec_dissector) {
rtp_info->info_payload_type_str = (const char *) dissector_handle_get_protocol_short_name(p_conv_data->bta2dp_info->codec_dissector);
} else if (p_conv_data && p_conv_data->btvdp_info && p_conv_data->btvdp_info->codec_dissector) {
rtp_info->info_payload_type_str = (const char *) dissector_handle_get_protocol_short_name(p_conv_data->btvdp_info->codec_dissector);
if (p_packet_data && p_packet_data->bta2dp_info && p_packet_data->bta2dp_info->codec_dissector) {
rtp_info->info_payload_type_str = (const char *) dissector_handle_get_protocol_short_name(p_packet_data->bta2dp_info->codec_dissector);
} else if (p_packet_data && p_packet_data->btvdp_info && p_packet_data->btvdp_info->codec_dissector) {
rtp_info->info_payload_type_str = (const char *) dissector_handle_get_protocol_short_name(p_packet_data->btvdp_info->codec_dissector);
}
/* if it is dynamic payload, let use the conv data to see if it is defined */
if ( (payload_type>95) && (payload_type<128) ) {
if (p_conv_data && p_conv_data->rtp_dyn_payload) {
if (p_packet_data && p_packet_data->rtp_dyn_payload) {
int sample_rate = 0;
unsigned channels = 1;
wmem_map_t *fmtp_map;
@ -2366,7 +2361,7 @@ dissect_rtp( tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void *data _U_
#endif
DPRINT(("looking up conversation data for dyn_pt=%d", payload_type));
if (rtp_dyn_payload_get_full(p_conv_data->rtp_dyn_payload, payload_type,
if (rtp_dyn_payload_get_full(p_packet_data->rtp_dyn_payload, payload_type,
&payload_type_str, &sample_rate,
&channels, &fmtp_map)) {
DPRINT(("found conversation data for dyn_pt=%d, enc_name=%s",
@ -2391,10 +2386,10 @@ dissect_rtp( tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void *data _U_
}
}
if (p_conv_data && p_conv_data->bta2dp_info) {
pt = (p_conv_data->bta2dp_info->codec_dissector) ? dissector_handle_get_protocol_short_name(p_conv_data->bta2dp_info->codec_dissector) : "Unknown";
} else if (p_conv_data && p_conv_data->btvdp_info) {
pt = (p_conv_data->btvdp_info->codec_dissector) ? dissector_handle_get_protocol_short_name(p_conv_data->btvdp_info->codec_dissector) : "Unknown";
if (p_packet_data && p_packet_data->bta2dp_info) {
pt = (p_packet_data->bta2dp_info->codec_dissector) ? dissector_handle_get_protocol_short_name(p_packet_data->bta2dp_info->codec_dissector) : "Unknown";
} else if (p_packet_data && p_packet_data->btvdp_info) {
pt = (p_packet_data->btvdp_info->codec_dissector) ? dissector_handle_get_protocol_short_name(p_packet_data->btvdp_info->codec_dissector) : "Unknown";
} else {
pt = (payload_type_str ? payload_type_str : val_to_str_ext(payload_type, &rtp_payload_type_vals_ext, "Unknown (%u)"));
}
@ -2432,8 +2427,8 @@ dissect_rtp( tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void *data _U_
/* Sequence number 16 bits (2 octets) */
proto_tree_add_uint( rtp_tree, hf_rtp_seq_nr, tvb, offset, 2, seq_num );
if(p_conv_data != NULL) {
item = proto_tree_add_uint( rtp_tree, hf_rtp_ext_seq_nr, tvb, offset, 2, p_conv_data->extended_seqno );
if(p_packet_data != NULL) {
item = proto_tree_add_uint(rtp_tree, hf_rtp_ext_seq_nr, tvb, offset, 2, p_packet_data->extended_seqno);
proto_item_set_generated(item);
}
offset += 2;
@ -2548,20 +2543,20 @@ dissect_rtp( tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void *data _U_
rtp_info->info_payload_len = tvb_captured_length_remaining(tvb, offset);
rtp_info->info_padding_count = padding_count;
if (p_conv_data && p_conv_data->bta2dp_info) {
if (p_conv_data->bta2dp_info->codec_dissector == sbc_handle) {
if (p_packet_data && p_packet_data->bta2dp_info) {
if (p_packet_data->bta2dp_info->codec_dissector == sbc_handle) {
rtp_info->info_payload_offset += 1;
rtp_info->info_payload_len -= 1;
}
if (p_conv_data->bta2dp_info->content_protection_type == BTAVDTP_CONTENT_PROTECTION_TYPE_SCMS_T) {
if (p_packet_data->bta2dp_info->content_protection_type == BTAVDTP_CONTENT_PROTECTION_TYPE_SCMS_T) {
rtp_info->info_payload_offset += 1;
rtp_info->info_payload_len -= 1;
}
}
if (p_conv_data && p_conv_data->btvdp_info &&
p_conv_data->btvdp_info->content_protection_type == BTAVDTP_CONTENT_PROTECTION_TYPE_SCMS_T) {
if (p_packet_data && p_packet_data->btvdp_info &&
p_packet_data->btvdp_info->content_protection_type == BTAVDTP_CONTENT_PROTECTION_TYPE_SCMS_T) {
rtp_info->info_payload_offset += 1;
rtp_info->info_payload_len -= 1;
}
@ -2628,20 +2623,20 @@ dissect_rtp( tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void *data _U_
rtp_info->info_payload_offset = offset;
rtp_info->info_payload_len = tvb_captured_length_remaining(tvb, offset);
if (p_conv_data && p_conv_data->bta2dp_info) {
if (p_conv_data->bta2dp_info->codec_dissector == sbc_handle) {
if (p_packet_data && p_packet_data->bta2dp_info) {
if (p_packet_data->bta2dp_info->codec_dissector == sbc_handle) {
rtp_info->info_payload_offset += 1;
rtp_info->info_payload_len -= 1;
}
if (p_conv_data->bta2dp_info->content_protection_type == BTAVDTP_CONTENT_PROTECTION_TYPE_SCMS_T) {
if (p_packet_data->bta2dp_info->content_protection_type == BTAVDTP_CONTENT_PROTECTION_TYPE_SCMS_T) {
rtp_info->info_payload_offset += 1;
rtp_info->info_payload_len -= 1;
}
}
if (p_conv_data && p_conv_data->btvdp_info &&
p_conv_data->btvdp_info->content_protection_type == BTAVDTP_CONTENT_PROTECTION_TYPE_SCMS_T) {
if (p_packet_data && p_packet_data->btvdp_info &&
p_packet_data->btvdp_info->content_protection_type == BTAVDTP_CONTENT_PROTECTION_TYPE_SCMS_T) {
rtp_info->info_payload_offset += 1;
rtp_info->info_payload_len -= 1;
}
@ -2875,15 +2870,15 @@ calculate_extended_timestamp(guint64 previous_timestamp, guint32 raw_timestamp)
/* Look for conversation info */
static struct _rtp_conversation_info *
get_conv_info(packet_info *pinfo, struct _rtp_info *rtp_info)
get_rtp_packet_info(packet_info *pinfo, struct _rtp_info *rtp_info)
{
/* Conversation and current data */
struct _rtp_conversation_info *p_conv_data;
struct _rtp_conversation_info *p_packet_data;
/* Use existing packet info if available */
p_conv_data = (struct _rtp_conversation_info *)p_get_proto_data(wmem_file_scope(), pinfo, proto_rtp, RTP_CONVERSATION_PROTO_DATA);
p_packet_data = (struct _rtp_conversation_info *)p_get_proto_data(wmem_file_scope(), pinfo, proto_rtp, RTP_CONVERSATION_PROTO_DATA);
if (!p_conv_data)
if (!p_packet_data)
{
conversation_t *p_conv;
@ -2891,52 +2886,85 @@ get_conv_info(packet_info *pinfo, struct _rtp_info *rtp_info)
p_conv = find_conversation(pinfo->num, &pinfo->net_dst, &pinfo->net_src,
conversation_pt_to_conversation_type(pinfo->ptype),
pinfo->destport, pinfo->srcport, NO_ADDR_B);
if (p_conv)
{
/* Create space for packet info */
struct _rtp_conversation_info *p_conv_packet_data;
p_conv_data = (struct _rtp_conversation_info *)conversation_get_proto_data(p_conv, proto_rtp);
if (p_conv_data) {
guint32 seqno;
guint64 timestamp;
/* Save this conversation info into packet info */
/* XXX: why is this file pool not pinfo->pool? */
p_conv_packet_data = wmem_new(wmem_file_scope(), struct _rtp_conversation_info);
(void) g_strlcpy(p_conv_packet_data->method, p_conv_data->method, MAX_RTP_SETUP_METHOD_SIZE+1);
p_conv_packet_data->frame_number = p_conv_data->frame_number;
p_conv_packet_data->media_types = p_conv_data->media_types;
/* do not increment ref count for the rtp_dyn_payload */
p_conv_packet_data->rtp_dyn_payload = p_conv_data->rtp_dyn_payload;
p_conv_packet_data->rtp_conv_info = p_conv_data->rtp_conv_info;
p_conv_packet_data->srtp_info = p_conv_data->srtp_info;
p_conv_packet_data->rtp_sdp_setup_info_list = p_conv_data->rtp_sdp_setup_info_list;
p_conv_packet_data->bta2dp_info = p_conv_data->bta2dp_info;
p_conv_packet_data->btvdp_info = p_conv_data->btvdp_info;
/* XXX: why is this file pool not pinfo->pool? */
p_add_proto_data(wmem_file_scope(), pinfo, proto_rtp, RTP_CONVERSATION_PROTO_DATA, p_conv_packet_data);
/* calculate extended sequence number */
seqno = calculate_extended_seqno(p_conv_data->extended_seqno,
rtp_info->info_seq_num);
p_conv_packet_data->extended_seqno = seqno;
p_conv_data->extended_seqno = seqno;
/* calculate extended timestamp */
timestamp = calculate_extended_timestamp(p_conv_data->extended_timestamp,
rtp_info->info_timestamp);
p_conv_packet_data->extended_timestamp = timestamp;
p_conv_data->extended_timestamp = timestamp;
}
if (!p_conv) {
/* Create a conversation in case none exists (decode as is used for marking the packet as RTP) */
p_conv = conversation_new(pinfo->num, &pinfo->net_dst, &pinfo->net_src,
conversation_pt_to_conversation_type(pinfo->ptype),
pinfo->destport, pinfo->srcport, NO_ADDR2);
}
/* Create space for packet info */
struct _rtp_internal_conversation_info *p_conv_data;
p_conv_data = (struct _rtp_internal_conversation_info *)conversation_get_proto_data(p_conv, proto_rtp);
if (!p_conv_data) {
/* Create conversation data. If RTP was set up by an SDP or by
* the heuristic dissector, conversation data should already
* have been created. Therefore, we should only reach this
* case if Decode As is being used (See Issue #18829).
*/
p_conv_data = wmem_new0(wmem_file_scope(), struct _rtp_internal_conversation_info);
p_conv_data->ssrc_number_space = wmem_map_new(wmem_file_scope(), g_direct_hash, g_direct_equal);
p_conv_data->rtp_conv_info = wmem_new(wmem_file_scope(), rtp_private_conv_info);
p_conv_data->rtp_conv_info->multisegment_pdus = wmem_tree_new(wmem_file_scope());
(void)g_strlcpy(p_conv_data->method, "DECODE AS", MAX_RTP_SETUP_METHOD_SIZE + 1);
p_conv_data->frame_number = pinfo->num;
p_conv_data->media_types = 0;
p_conv_data->srtp_info = NULL;
p_conv_data->bta2dp_info = NULL;
p_conv_data->btvdp_info = NULL;
conversation_add_proto_data(p_conv, proto_rtp, p_conv_data);
}
guint32 seqno;
guint64 timestamp;
/* Save this conversation info into packet info */
/* This is file scoped because we only do this on the first pass.
* On nonsequential passes, the conversation data has the values
* from the last dissected frame, which is not necessarily the
* immediately previous frame.
*/
p_packet_data = wmem_new(wmem_file_scope(), struct _rtp_conversation_info);
(void)g_strlcpy(p_packet_data->method, p_conv_data->method, MAX_RTP_SETUP_METHOD_SIZE + 1);
p_packet_data->frame_number = p_conv_data->frame_number;
p_packet_data->media_types = p_conv_data->media_types;
/* do not increment ref count for the rtp_dyn_payload */
p_packet_data->rtp_dyn_payload = p_conv_data->rtp_dyn_payload;
p_packet_data->rtp_conv_info = p_conv_data->rtp_conv_info;
p_packet_data->srtp_info = p_conv_data->srtp_info;
p_packet_data->rtp_sdp_setup_info_list = p_conv_data->rtp_sdp_setup_info_list;
p_packet_data->bta2dp_info = p_conv_data->bta2dp_info;
p_packet_data->btvdp_info = p_conv_data->btvdp_info;
p_add_proto_data(wmem_file_scope(), pinfo, proto_rtp, RTP_CONVERSATION_PROTO_DATA, p_packet_data);
rtp_number_space* number_space = wmem_map_lookup(p_conv_data->ssrc_number_space, GUINT_TO_POINTER(rtp_info->info_sync_src));
if (number_space == NULL) {
/* Start the extended numbers up one cycle, to cope gracefully
with the first few packets being out of order. */
number_space = wmem_new0(wmem_file_scope(), rtp_number_space);
number_space->extended_seqno = 0x10000;
number_space->extended_timestamp = 0x100000000;
wmem_map_insert(p_conv_data->ssrc_number_space, GUINT_TO_POINTER(rtp_info->info_sync_src), number_space);
}
/* calculate extended sequence number */
seqno = calculate_extended_seqno(number_space->extended_seqno,
rtp_info->info_seq_num);
p_packet_data->extended_seqno = seqno;
number_space->extended_seqno = seqno;
/* calculate extended timestamp */
timestamp = calculate_extended_timestamp(number_space->extended_timestamp,
rtp_info->info_timestamp);
p_packet_data->extended_timestamp = timestamp;
number_space->extended_timestamp = timestamp;
}
if (p_conv_data) {
rtp_info->info_setup_frame_num = p_conv_data->frame_number;
if (p_packet_data) {
rtp_info->info_setup_frame_num = p_packet_data->frame_number;
}
return p_conv_data;
return p_packet_data;
}
@ -2945,37 +2973,37 @@ static void
show_setup_info(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
{
/* Conversation and current data */
struct _rtp_conversation_info *p_conv_data;
struct _rtp_conversation_info *p_packet_data;
proto_tree *rtp_setup_tree;
proto_item *ti;
/* Use existing packet info if available */
p_conv_data = (struct _rtp_conversation_info *)p_get_proto_data(wmem_file_scope(), pinfo, proto_rtp, RTP_CONVERSATION_PROTO_DATA);
p_packet_data = (struct _rtp_conversation_info *)p_get_proto_data(wmem_file_scope(), pinfo, proto_rtp, RTP_CONVERSATION_PROTO_DATA);
if (!p_conv_data) return;
if (!p_packet_data) return;
/* Create setup info subtree with summary info. */
ti = proto_tree_add_string_format(tree, hf_rtp_setup, tvb, 0, 0,
"", "Stream setup by %s (frame %u)",
p_conv_data->method,
p_conv_data->frame_number);
p_packet_data->method,
p_packet_data->frame_number);
proto_item_set_generated(ti);
rtp_setup_tree = proto_item_add_subtree(ti, ett_rtp_setup);
if (rtp_setup_tree)
{
/* Add details into subtree */
proto_item* item = proto_tree_add_uint(rtp_setup_tree, hf_rtp_setup_frame,
tvb, 0, 0, p_conv_data->frame_number);
tvb, 0, 0, p_packet_data->frame_number);
proto_item_set_generated(item);
item = proto_tree_add_string(rtp_setup_tree, hf_rtp_setup_method,
tvb, 0, 0, p_conv_data->method);
tvb, 0, 0, p_packet_data->method);
proto_item_set_generated(item);
if (p_conv_data->rtp_sdp_setup_info_list){
if (p_packet_data->rtp_sdp_setup_info_list){
guint i;
sdp_setup_info_t *stored_setup_info;
for (i = 0; i < wmem_array_get_count(p_conv_data->rtp_sdp_setup_info_list); i++) {
stored_setup_info = (sdp_setup_info_t *)wmem_array_index(p_conv_data->rtp_sdp_setup_info_list, i);
for (i = 0; i < wmem_array_get_count(p_packet_data->rtp_sdp_setup_info_list); i++) {
stored_setup_info = (sdp_setup_info_t *)wmem_array_index(p_packet_data->rtp_sdp_setup_info_list, i);
if (stored_setup_info->hf_id) {
if (stored_setup_info->hf_type == SDP_TRACE_ID_HF_TYPE_STR) {
item = proto_tree_add_string(rtp_setup_tree, stored_setup_info->hf_id, tvb, 0, 0, stored_setup_info->trace_id.str);

View File

@ -237,8 +237,12 @@ void rtp_dyn_payload_free(rtp_dyn_payload_t *rtp_dyn_payload);
void rtp_dump_dyn_payload(rtp_dyn_payload_t *rtp_dyn_payload);
#endif
/** Info to save in RTP conversation / packet-info */
#define MAX_RTP_SETUP_METHOD_SIZE 11
/** Info to save in RTP packet-info */
/** XXX: This is wasteful of memory. The only things that really need
* to be saved per-packet, as opposed to once per conversation, are the
* extended seqno and timestamp.
*/
struct _rtp_conversation_info
{
gchar method[MAX_RTP_SETUP_METHOD_SIZE + 1];