From Martin Mathieson:

- allow SDP to parse the IP address + port for the MSRP session from the 
path attribute
- setup an MSRP conversation using this address, whose data points back 
to the SDP frame
- link to the SDP setup frame while dissecting MSRP (can be switched off 
by a preference)
- I also changed sdp.media.port to be a numeric field

svn path=/trunk/; revision=18806
This commit is contained in:
Anders Broman 2006-07-28 21:26:39 +00:00
parent ed3b76044e
commit 4f7ff62fcf
4 changed files with 310 additions and 26 deletions

View File

@ -841,6 +841,7 @@ DISSECTOR_INCLUDES = \
packet-mq.h \
packet-mrdisc.h \
packet-msnip.h \
packet-msrp.h \
packet-mtp3.h \
packet-nbap.h \
packet-ncp-int.h \

View File

@ -39,8 +39,11 @@
#include <epan/conversation.h>
#include <epan/packet.h>
#include <epan/emem.h>
#include "prefs.h"
#include "packet-msrp.h"
#define TCP_PORT_MSRP 0
#define MSRP_HDR "MSRP"
@ -57,6 +60,7 @@ static int ett_msrp_hdr = -1;
static int ett_msrp_element = -1;
static int ett_msrp_data = -1;
static int ett_msrp_end_line = -1;
static int ett_msrp_setup = -1;
static int hf_msrp_response_line = -1;
static int hf_msrp_request_line = -1;
@ -67,6 +71,11 @@ static int hf_msrp_msg_hdr = -1;
static int hf_msrp_end_line = -1;
static int hf_msrp_cnt_flg = -1;
/* MSRP setup fields */
static int hf_msrp_setup = -1;
static int hf_msrp_setup_frame = -1;
static int hf_msrp_setup_method = -1;
typedef struct {
const char *name;
} msrp_header_t;
@ -136,6 +145,145 @@ static dissector_table_t media_type_dissector_table;
static int dissect_msrp(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree);
/* Displaying conversation setup info */
static gboolean global_msrp_show_setup_info = TRUE;
static void show_setup_info(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree);
/* Set up an MSRP conversation using the info given */
void msrp_add_address( packet_info *pinfo,
address *addr, int port,
const gchar *setup_method, guint32 setup_frame_number)
{
address null_addr;
conversation_t* p_conv;
struct _msrp_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
* again.
*/
if (pinfo->fd->flags.visited)
{
return;
}
SET_ADDRESS(&null_addr, AT_NONE, 0, NULL);
/*
* Check if the ip address and port combination is not
* already registered as a conversation.
*/
p_conv = find_conversation( pinfo->fd->num, addr, &null_addr, PT_TCP, port, 0,
NO_ADDR_B | NO_PORT_B);
/*
* If not, create a new conversation.
*/
if (!p_conv) {
p_conv = conversation_new( pinfo->fd->num, addr, &null_addr, PT_TCP,
(guint32)port, 0,
NO_ADDR2 | NO_PORT2);
}
/* Set dissector */
conversation_set_dissector(p_conv, msrp_handle);
/*
* Check if the conversation has data associated with it.
*/
p_conv_data = conversation_get_proto_data(p_conv, proto_msrp);
/*
* If not, add a new data item.
*/
if (!p_conv_data) {
/* Create conversation data */
p_conv_data = se_alloc(sizeof(struct _msrp_conversation_info));
if (!p_conv_data)
{
return;
}
memset(p_conv_data, 0, sizeof(struct _msrp_conversation_info));
conversation_add_proto_data(p_conv, proto_msrp, p_conv_data);
}
/*
* Update the conversation data.
*/
p_conv_data->setup_method_set = TRUE;
strncpy(p_conv_data->setup_method, setup_method, MAX_MSRP_SETUP_METHOD_SIZE);
p_conv_data->setup_method[MAX_MSRP_SETUP_METHOD_SIZE] = '\0';
p_conv_data->setup_frame_number = setup_frame_number;
}
/* Look for conversation info and display any setup info found */
void show_setup_info(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
{
/* Conversation and current data */
conversation_t *p_conv = NULL;
struct _msrp_conversation_info *p_conv_data = NULL;
/* Use existing packet data if available */
p_conv_data = p_get_proto_data(pinfo->fd, proto_msrp);
if (!p_conv_data)
{
/* First time, get info from conversation */
p_conv = find_conversation(pinfo->fd->num, &pinfo->net_dst, &pinfo->net_src,
PT_TCP,
pinfo->destport, pinfo->srcport, 0);//NO_ADDR_B | NO_PORT_B);
if (p_conv)
{
/* Look for data in conversation */
struct _msrp_conversation_info *p_conv_packet_data;
p_conv_data = conversation_get_proto_data(p_conv, proto_msrp);
if (p_conv_data)
{
/* Save this conversation info into packet info */
p_conv_packet_data = se_alloc(sizeof(struct _msrp_conversation_info));
if (!p_conv_packet_data)
{
return;
}
memcpy(p_conv_packet_data, p_conv_data,
sizeof(struct _msrp_conversation_info));
p_add_proto_data(pinfo->fd, proto_msrp, p_conv_packet_data);
}
}
}
/* Create setup info subtree with summary info. */
if (p_conv_data && p_conv_data->setup_method_set)
{
proto_tree *msrp_setup_tree;
proto_item *ti = proto_tree_add_string_format(tree, hf_msrp_setup, tvb, 0, 0,
"",
"Stream setup by %s (frame %u)",
p_conv_data->setup_method,
p_conv_data->setup_frame_number);
PROTO_ITEM_SET_GENERATED(ti);
msrp_setup_tree = proto_item_add_subtree(ti, ett_msrp_setup);
if (msrp_setup_tree)
{
/* Add details into subtree */
proto_item* item = proto_tree_add_uint(msrp_setup_tree, hf_msrp_setup_frame,
tvb, 0, 0, p_conv_data->setup_frame_number);
PROTO_ITEM_SET_GENERATED(item);
item = proto_tree_add_string(msrp_setup_tree, hf_msrp_setup_method,
tvb, 0, 0, p_conv_data->setup_method);
PROTO_ITEM_SET_GENERATED(item);
}
}
}
/* Returns index of headers */
static gint msrp_is_known_msrp_header(tvbuff_t *tvb, int offset, guint header_len)
{
@ -286,8 +434,10 @@ dissect_msrp_heur(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
* TODO Set up conversation here
*/
if (pinfo->fd->flags.visited){
/* Look for existing conversation */
conversation = find_conversation(pinfo->fd->num, &pinfo->src, &pinfo->dst, pinfo->ptype,
pinfo->srcport, pinfo->destport, 0);
/* Create new one if not found */
if (conversation == NULL){
conversation = conversation_new(pinfo->fd->num, &pinfo->src, &pinfo->dst,
pinfo->ptype, pinfo->srcport, pinfo->destport, 0);
@ -447,6 +597,12 @@ dissect_msrp(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
proto_tree_add_item(reqresp_tree,hf_msrp_method,tvb,token_3_start,token_3_len,FALSE);
}
/* Conversation setup info */
if (global_msrp_show_setup_info)
{
show_setup_info(tvb, pinfo, msrp_tree);
}
/* Headers */
msrp_headers_item = proto_tree_add_item(msrp_tree, hf_msrp_msg_hdr, tvb, offset,(end_line_offset - offset), FALSE);
msrp_hdr_tree = proto_item_add_subtree(msrp_headers_item, ett_msrp_hdr);
@ -633,6 +789,7 @@ proto_register_msrp(void)
&ett_msrp_element,
&ett_msrp_data,
&ett_msrp_end_line,
&ett_msrp_setup
};
/* Setup list of header fields */
@ -752,6 +909,21 @@ proto_register_msrp(void)
FT_STRING, BASE_NONE,NULL,0x0,
"Authentication-Info", HFILL }
},
{ &hf_msrp_setup,
{ "Stream setup", "msrp.setup",
FT_STRING, BASE_NONE, NULL, 0x0,
"Stream setup, method and frame number", HFILL}
},
{ &hf_msrp_setup_frame,
{ "Setup frame", "msrp.setup-frame",
FT_FRAMENUM, BASE_NONE, NULL, 0x0,
"Frame that set up this stream", HFILL}
},
{ &hf_msrp_setup_method,
{ "Setup Method", "msrp.setup-method",
FT_STRING, BASE_NONE, NULL, 0x0,
"Method used to set up this stream", HFILL}
},
};
module_t *msrp_module;
@ -772,7 +944,14 @@ proto_register_msrp(void)
"MSRP message should be displayed "
"in addition to the dissection tree",
&global_msrp_raw_text);
prefs_register_bool_preference(msrp_module, "show_setup_info",
"Show stream setup information",
"Where available, show which protocol and frame caused "
"this MSRP stream to be created",
&global_msrp_show_setup_info);
/*
* Register the dissector by name, so other dissectors can
* grab it by name rather than just referring to it directly.

View File

@ -0,0 +1,38 @@
/* packet-msrp.h
*
* $Id$
*
* Wireshark - Network traffic analyzer
* By Gerald Combs <gerald@wireshark.org>
* Copyright 1998 Gerald Combs
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
/* Info to save in MSRP conversation / packet-info. */
#define MAX_MSRP_SETUP_METHOD_SIZE 7
struct _msrp_conversation_info
{
guchar setup_method_set;
gchar setup_method[MAX_MSRP_SETUP_METHOD_SIZE + 1];
guint32 setup_frame_number;
};
/* Add an MSRP conversation with the given details */
void msrp_add_address(packet_info *pinfo,
address *addr, int port,
const gchar *setup_method, guint32 setup_frame_number);

View File

@ -64,13 +64,13 @@
#include <epan/prefs.h>
#include "packet-rtcp.h"
#include "packet-t38.h"
#include "packet-msrp.h"
static dissector_handle_t rtp_handle=NULL;
static dissector_handle_t rtcp_handle=NULL;
static dissector_handle_t t38_handle=NULL;
static dissector_handle_t msrp_handle=NULL;
static int sdp_tap = -1;
@ -190,6 +190,13 @@ typedef struct {
gint8 media_count;
} transport_info_t;
/* MSRP transport info (as set while parsing path attribute) */
static gboolean msrp_transport_address_set = FALSE;
static guint32 msrp_ipaddr[4];
static guint16 msrp_port_number;
/* static functions */
static void call_sdp_subdissector(tvbuff_t *tvb, int hf, proto_tree* ti,
@ -232,6 +239,7 @@ dissect_sdp(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
guint32 port=0;
gboolean is_rtp=FALSE;
gboolean is_t38=FALSE;
gboolean is_msrp=FALSE;
gboolean set_rtp=FALSE;
gboolean is_ipv4_addr=FALSE;
gboolean is_ipv6_addr=FALSE;
@ -397,14 +405,19 @@ dissect_sdp(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
}
if(transport_info.media_proto[n]!=NULL) {
/* Check if media protocol is RTP
* and stream decoding is enabled in preferences
*/
if(global_sdp_establish_conversation){
is_rtp = (strcmp(transport_info.media_proto[n],"RTP/AVP")==0);
/* Check if media protocol is T38 */
is_t38 = ( (strcmp(transport_info.media_proto[n],"UDPTL")==0) || (strcmp(transport_info.media_proto[n],"udptl")==0) );
}
* and stream decoding is enabled in preferences
*/
if(global_sdp_establish_conversation){
/* Check if media protocol is RTP */
is_rtp = (strcmp(transport_info.media_proto[n],"RTP/AVP")==0);
/* Check if media protocol is T38 */
is_t38 = ( (strcmp(transport_info.media_proto[n],"UDPTL")==0) || (strcmp(transport_info.media_proto[n],"udptl")==0) );
/* Check if media protocol is MSRP/TCP */
is_msrp = (strcmp(transport_info.media_proto[n],"msrp/tcp")==0);
}
}
if(transport_info.connection_address!=NULL) {
if(transport_info.connection_type!=NULL) {
if (strcmp(transport_info.connection_type,"IP4")==0) {
@ -438,14 +451,27 @@ dissect_sdp(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
port++;
rtcp_add_address(pinfo, &src_addr, port, 0, "SDP", pinfo->fd->num);
}
}
}
/* Add t38 conversation, if available and only if no rtp */
if((!pinfo->fd->flags.visited) && port!=0 && !set_rtp && is_t38 && is_ipv4_addr){
src_addr.data=(char *)&ipaddr;
if(t38_handle){
t38_add_address(pinfo, &src_addr, port, 0, "SDP", pinfo->fd->num);
}
}
}
/* Add MSRP conversation. Uses addresses discovered in attribute
rather than connection information of media session line */
if (is_msrp ){
if ((!pinfo->fd->flags.visited) && msrp_transport_address_set){
if(msrp_handle){
src_addr.type=AT_IPv4;
src_addr.len=4;
src_addr.data=(char *)&msrp_ipaddr;
msrp_add_address(pinfo, &src_addr, msrp_port_number, "SDP", pinfo->fd->num);
}
}
}
/* Create the RTP summary str for the Voip Call analysis */
@ -879,6 +905,9 @@ dissect_sdp_media(tvbuff_t *tvb, proto_item *ti,
next_offset = 0;
tokenlen = 0;
/* Re-initialise for a new media description */
msrp_transport_address_set = FALSE;
sdp_media_tree = proto_item_add_subtree(ti,ett_sdp_media);
next_offset = tvb_find_guint8(tvb,offset, -1, ' ');
@ -904,8 +933,8 @@ dissect_sdp_media(tvbuff_t *tvb, proto_item *ti,
/* Save port info */
transport_info->media_port[transport_info->media_count] = tvb_get_ephemeral_string(tvb, offset, tokenlen);
proto_tree_add_item(sdp_media_tree, hf_media_port, tvb, offset, tokenlen,
FALSE);
proto_tree_add_uint(sdp_media_tree, hf_media_port, tvb, offset, tokenlen,
atoi(tvb_get_string(tvb, offset, tokenlen)));
offset = next_offset + 1;
next_offset = tvb_find_guint8(tvb,offset, -1, ' ');
if(next_offset == -1)
@ -924,8 +953,8 @@ dissect_sdp_media(tvbuff_t *tvb, proto_item *ti,
transport_info->media_port[transport_info->media_count] = tvb_get_ephemeral_string(tvb, offset, tokenlen);
/* XXX Remember Port */
proto_tree_add_item(sdp_media_tree, hf_media_port, tvb, offset, tokenlen,
FALSE);
proto_tree_add_uint(sdp_media_tree, hf_media_port, tvb, offset, tokenlen,
atoi(tvb_get_string(tvb, offset, tokenlen)));
offset = next_offset + 1;
}
@ -1132,30 +1161,39 @@ static void dissect_sdp_media_attribute(tvbuff_t *tvb, proto_item * ti, transpor
gint offset, next_offset, tokenlen, n;
guint8 *field_name;
guint8 *payload_type;
guint8 *attribute_value;
gint *key;
offset = 0;
next_offset = 0;
tokenlen = 0;
/* Create attribute tree */
sdp_media_attribute_tree = proto_item_add_subtree(ti,
ett_sdp_media_attribute);
/* Find end of field */
next_offset = tvb_find_guint8(tvb,offset,-1,':');
if(next_offset == -1)
return;
/* Attribute field name is token before ':' */
tokenlen = next_offset - offset;
proto_tree_add_item(sdp_media_attribute_tree,
hf_media_attribute_field,
tvb, offset, tokenlen, FALSE);
field_name = tvb_get_ephemeral_string(tvb, offset, tokenlen);
/* Skip colon */
offset = next_offset + 1;
/* Value is the remainder of the line */
attribute_value = tvb_get_string(tvb, offset, tvb_length_remaining(tvb, offset));
/*********************************************/
/* Special parsing for some field name types */
/* decode the rtpmap to see if it is DynamicPayload to dissect them automatic */
if (strcmp(field_name, "rtpmap") == 0) {
@ -1234,6 +1272,7 @@ static void dissect_sdp_media_attribute(tvbuff_t *tvb, proto_item * ti, transpor
return;
}
if (strcmp(field_name, "fmtp") == 0) {
proto_item *fmtp_item, *media_format_item;
proto_tree *fmtp_tree;
@ -1259,8 +1298,8 @@ static void dissect_sdp_media_attribute(tvbuff_t *tvb, proto_item * ti, transpor
offset = next_offset + 1;
/* There may be 2 parameters given
* TODO: Handle arbitarry number of parameters.
*/
* TODO: Handle arbitary number of parameters.
*/
next_offset = tvb_find_guint8(tvb,offset,-1,';');
if(next_offset != -1){
@ -1292,6 +1331,33 @@ static void dissect_sdp_media_attribute(tvbuff_t *tvb, proto_item * ti, transpor
return;
}
/* msrp attributes that contain address needed for conversation */
if (strcmp(field_name, "path") == 0) {
const char *msrp_res = "msrp://";
if (strncmp(attribute_value, msrp_res, strlen(msrp_res)) == 0){
int address_offset, port_offset, port_end_offset;
/* Address starts here */
address_offset = offset + strlen(msrp_res);
/* Port is after next ':' */
port_offset = tvb_find_guint8(tvb, address_offset, -1, ':');
/* Port ends with '/' */
port_end_offset = tvb_find_guint8(tvb, port_offset, -1, '/');
/* Attempt to convert address */
if (inet_pton(AF_INET, tvb_get_ephemeral_string(tvb, address_offset, port_offset-address_offset), &msrp_ipaddr) > 0) {
/* Get port number */
msrp_port_number = atoi(tvb_get_ephemeral_string(tvb, port_offset+1, port_end_offset-port_offset-1));
/* Set flag so this info can be used */
msrp_transport_address_set = TRUE;
}
}
}
/* No special treatment for values of this attribute type, just add as one item. */
proto_tree_add_item(sdp_media_attribute_tree, hf_media_attribute_value,
tvb, offset, -1, FALSE);
@ -1479,7 +1545,7 @@ proto_register_sdp(void)
"Media Type", HFILL }},
{ &hf_media_port,
{ "Media Port",
"sdp.media.port",FT_STRING, BASE_NONE, NULL, 0x0,
"sdp.media.port",FT_UINT16, BASE_DEC, NULL, 0x0,
"Media Port", HFILL }},
{ &hf_media_portcount,
{ "Media Port Count",
@ -1549,8 +1615,8 @@ proto_register_sdp(void)
*/
sdp_module = prefs_register_protocol(proto_sdp, NULL);
prefs_register_bool_preference(sdp_module, "establish_conversation",
"Establish RTP Conversation",
"Specifies that RTP stream is decoded based "
"Establish Media Conversation",
"Specifies that RTP/RTCP/T.38/MSRP/etc streams are decoded based "
"upon port numbers found in SIP/SDP payload",
&global_sdp_establish_conversation);
@ -1571,7 +1637,7 @@ proto_reg_handoff_sdp(void)
rtp_handle = find_dissector("rtp");
rtcp_handle = find_dissector("rtcp");
msrp_handle = find_dissector("msrp");
t38_handle = find_dissector("t38");
sdp_handle = find_dissector("sdp");