From Martin Mathieson:

- Many DCT2000 protocols can be embedded within an IP primitive 
message.  Add a heuristic to see if we can find the protocol payload 
within in IP primitive message, and look for an ethereal dissector 
matching the DCT2000 protocol name (this is useful for simple protocol 
testing where no physical links are involved)
- Make some more of these protocols (diameter, http, mgcp) findable by name
- Adds protocol 'variant' number to stub and dissector
- Break the duplicated writing of the stub header out into a separate 
function

svn path=/trunk/; revision=18212
This commit is contained in:
Anders Broman 2006-05-23 05:48:00 +00:00
parent 28509cb311
commit 1814821adc
6 changed files with 190 additions and 54 deletions

View File

@ -41,11 +41,14 @@ static int hf_catapult_dct2000_context = -1;
static int hf_catapult_dct2000_port_number = -1;
static int hf_catapult_dct2000_timestamp = -1;
static int hf_catapult_dct2000_protocol = -1;
static int hf_catapult_dct2000_variant = -1;
static int hf_catapult_dct2000_direction = -1;
static int hf_catapult_dct2000_encap = -1;
static int hf_catapult_dct2000_unparsed_data = -1;
/* Variables used for preferences */
gboolean catapult_dct2000_board_ports_only;
gboolean catapult_dct2000_try_ipprim_heuristic = TRUE;
/* Protocol subtree. */
static int ett_catapult_dct2000 = -1;
@ -69,6 +72,56 @@ static const value_string encap_vals[] = {
{ 0, NULL },
};
/* Look for the protocol data within an ipprim packet.
Only set *data_offset if data field found. */
gboolean find_ipprim_data_offset(tvbuff_t *tvb, int *data_offset)
{
guint8 length;
int offset = *data_offset;
gboolean is_udp;
/* Get the ipprim command code. */
guint8 tag = tvb_get_guint8(tvb, offset++);
/* Only accept UDP or TCP data request or indication */
switch (tag)
{
case 0x23: /* UDP data request */
case 0x24: /* UDP data indication */
is_udp = TRUE;
break;
case 0x45: /* TCP data request */
case 0x46: /* TCP data indication */
is_udp = FALSE;
break;
default:
return FALSE;
}
/* Skip any other TLC fields before reach payload */
while (tvb_length_remaining(tvb, offset) > 2)
{
/* Look at next tag */
tag = tvb_get_guint8(tvb, offset++);
/* Is this the data payload we're expecting? */
if ((tag == 0x34 && is_udp) || (tag == 0x48 && !is_udp))
{
*data_offset = offset;
return TRUE;
}
else
{
/* Read length in next byte */
length = tvb_get_guint8(tvb, offset++);
/* Skip the following value */
offset += length;
}
}
/* No data found... */
return FALSE;
}
/*****************************************/
/* Main dissection function. */
@ -81,6 +134,7 @@ dissect_catapult_dct2000(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
gint offset = 0;
gint context_length;
guint8 port_number;
guint8 variant;
gint protocol_start;
gint protocol_length;
gint timestamp_start;
@ -89,6 +143,7 @@ dissect_catapult_dct2000(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
tvbuff_t *next_tvb;
int encap;
dissector_handle_t protocol_handle = 0;
dissector_handle_t heur_ipprim_protocol_handle = 0;
int sub_dissector_result = 0;
/* Protocol name */
@ -134,6 +189,12 @@ dissect_catapult_dct2000(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
offset, protocol_length, FALSE);
offset += protocol_length;
/* Variant */
variant = tvb_get_guint8(tvb, offset);
proto_tree_add_item(dct2000_tree, hf_catapult_dct2000_variant, tvb,
offset, 1, FALSE);
offset++;
/* Direction */
direction = tvb_get_guint8(tvb, offset);
proto_tree_add_item(dct2000_tree, hf_catapult_dct2000_direction, tvb,
@ -149,12 +210,13 @@ dissect_catapult_dct2000(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
proto_item_set_len(dct2000_tree, offset);
/* Add useful details to protocol tree label */
proto_item_append_text(ti, " context=%s.%u t=%s %c prot=%s",
proto_item_append_text(ti, " context=%s.%u t=%s %c prot=%s (v=%d)",
tvb_get_ephemeral_string(tvb, 0, context_length),
port_number,
tvb_get_ephemeral_string(tvb, timestamp_start, timestamp_length),
(direction == 0) ? 'S' : 'R',
tvb_get_ephemeral_string(tvb, protocol_start, protocol_length));
tvb_get_ephemeral_string(tvb, protocol_start, protocol_length),
variant);
/* Note that the first item of pinfo->pseudo_header->dct2000 will contain
@ -197,7 +259,24 @@ dissect_catapult_dct2000(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
protocol_handle = find_dissector("mtp2");
break;
case DCT2000_ENCAP_UNHANDLED:
/* Many DCT2000 protocols have at least one IPPrim variant. If the
protocol names match, try to find the UDP/TCP data inside them and
pass that offset to dissector
*/
protocol_handle = 0;
/* Try IP Prim heuristic if configured to */
if (catapult_dct2000_try_ipprim_heuristic)
{
heur_ipprim_protocol_handle =
find_dissector(tvb_get_ephemeral_string(tvb, protocol_start,
protocol_length));
if ((heur_ipprim_protocol_handle != 0) &&
find_ipprim_data_offset(tvb, &offset))
{
protocol_handle = heur_ipprim_protocol_handle;
}
}
break;
default:
@ -205,7 +284,7 @@ dissect_catapult_dct2000(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
this dissector and the wiretap module catapult_dct2000.c !!
*/
DISSECTOR_ASSERT_NOT_REACHED();
return;
return;
}
@ -230,12 +309,13 @@ dissect_catapult_dct2000(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
if (check_col(pinfo->cinfo, COL_INFO))
{
col_add_fstr(pinfo->cinfo, COL_INFO,
"Unparsed protocol data (context=%s.%u t=%s %c prot=%s)",
"Unparsed protocol data (context=%s.%u t=%s %c prot=%s (v=%d))",
tvb_get_ephemeral_string(tvb, 0, context_length),
port_number,
tvb_get_ephemeral_string(tvb, timestamp_start, timestamp_length),
(direction == 0) ? 'S' : 'R',
tvb_get_ephemeral_string(tvb, protocol_start, protocol_length));
tvb_get_ephemeral_string(tvb, protocol_start, protocol_length),
variant);
}
}
}
@ -283,6 +363,12 @@ void proto_register_catapult_dct2000(void)
"Original (DCT2000) protocol name", HFILL
}
},
{ &hf_catapult_dct2000_variant,
{ "Protocol variant",
"dct2000.variant", FT_UINT8, BASE_DEC, NULL, 0x0,
"DCT2000 protocol variant", HFILL
}
},
{ &hf_catapult_dct2000_direction,
{ "Direction",
"dct2000.direction", FT_UINT8, BASE_DEC, VALS(direction_vals), 0x0,
@ -331,5 +417,16 @@ void proto_register_catapult_dct2000(void)
"contexts on the same card. The capture file "
"needs to be (re)-loaded before effect will be seen",
&catapult_dct2000_board_ports_only);
/* Determines whether for not-handled protocols we should try to parse it if:
- it looks like its embedded in an ipprim message, AND
- the DCT2000 protocol name matches an ethereal dissector name */
prefs_register_bool_preference(catapult_dct2000_module, "ipprim_heuristic",
"Use IP Primitive heuristic",
"If a payload looks like its embedded in an "
"IP primitive messages, and there is an ethereal "
"dissector matching the DCT2000 protocol name, "
"try parsing the payload using that dissector",
&catapult_dct2000_try_ipprim_heuristic);
}

View File

@ -2291,6 +2291,9 @@ proto_register_diameter(void)
proto_register_field_array(proto_diameter, hf, array_length(hf));
proto_register_subtree_array(ett, array_length(ett));
/* Allow dissector to find be found by name. */
new_register_dissector("diameter", dissect_diameter, proto_diameter);
/* Register a configuration option for port */
diameter_module = prefs_register_protocol(proto_diameter,
proto_reg_handoff_diameter);

View File

@ -2036,6 +2036,7 @@ proto_register_http(void)
"HTTP", "http");
proto_register_field_array(proto_http, hf, array_length(hf));
proto_register_subtree_array(ett, array_length(ett));
register_dissector("http", dissect_http, proto_http);
http_module = prefs_register_protocol(proto_http, reinit_http);
prefs_register_bool_preference(http_module, "desegment_headers",
"Reassemble HTTP headers spanning multiple TCP segments",

View File

@ -847,6 +847,8 @@ void proto_register_mgcp(void)
proto_register_subtree_array(ett, array_length(ett));
register_init_routine(&mgcp_init_protocol);
register_dissector("mgcp", dissect_mgcp, proto_mgcp);
/* Register our configuration options */
mgcp_module = prefs_register_protocol(proto_mgcp, proto_reg_handoff_mgcp);
@ -950,7 +952,7 @@ static gboolean is_mgcp_verb(tvbuff_t *tvb, gint offset, gint maxlength, const g
/* Read the string into 'word' and see if it looks like the start of a verb */
if ((maxlength >= 4) && tvb_get_nstringz0(tvb, offset, sizeof(word), word))
{
if (((strncasecmp(word, "EPCF", 4) == 0) && (*verb_name = "EndpointConfiguration|")) ||
if (((strncasecmp(word, "EPCF", 4) == 0) && (*verb_name = "EndpointConfiguration")) ||
((strncasecmp(word, "CRCX", 4) == 0) && (*verb_name = "CreateConnection")) ||
((strncasecmp(word, "MDCX", 4) == 0) && (*verb_name = "ModifyConnection")) ||
((strncasecmp(word, "DLCX", 4) == 0) && (*verb_name = "DeleteConnection")) ||

View File

@ -42,6 +42,7 @@
#define MAX_CONTEXT_NAME 64
#define MAX_PROTOCOL_NAME 64
#define MAX_PORT_DIGITS 2
#define MAX_VARIANT_DIGITS 2
#define AAL_HEADER_CHARS 12
/* TODO:
@ -101,8 +102,10 @@ static const gchar catapult_dct2000_magic[] = "Session Transcript";
static gchar context_name[MAX_CONTEXT_NAME];
static guint8 context_port;
/* The DCT2000 protocol name of the packet */
/* The DCT2000 protocol name of the packet, plus variant number */
static gchar protocol_name[MAX_PROTOCOL_NAME+1];
static gchar variant;
/*************************************************/
/* Preference state (shared with stub protocol). */
@ -136,6 +139,8 @@ static gboolean parse_line(gint line_length, gint *seconds, gint *useconds,
packet_direction_t *direction,
int *encap,
gboolean seek_read);
int write_stub_header(guchar *frame_buffer, char *timestamp_string,
packet_direction_t direction, int encap);
static guchar hex_from_char(gchar c);
static gchar char_from_hex(guchar hex);
@ -356,30 +361,8 @@ gboolean catapult_dct2000_read(wtap *wth, int *err, gchar **err_info _U_,
/*********************/
/* Write stub header */
/* Context name */
strcpy((char*)frame_buffer, context_name);
stub_offset += (strlen(context_name) + 1);
/* Context port number */
frame_buffer[stub_offset] = context_port;
stub_offset++;
/* Timestamp within file */
strcpy((char*)&frame_buffer[stub_offset], timestamp_string);
stub_offset += (strlen(timestamp_string) + 1);
/* Protocol name */
strcpy((char*)&frame_buffer[stub_offset], protocol_name);
stub_offset += (strlen(protocol_name) + 1);
/* Direction */
frame_buffer[stub_offset] = direction;
stub_offset++;
/* Encap */
frame_buffer[stub_offset] = (guint8)encap;
stub_offset++;
stub_offset = write_stub_header(frame_buffer, timestamp_string,
direction, encap);
/* Binary data length is half bytestring length + stub header */
wth->phdr.len = data_chars/2 + stub_offset;
@ -394,7 +377,7 @@ gboolean catapult_dct2000_read(wtap *wth, int *err, gchar **err_info _U_,
(hex_from_char(linebuff[dollar_offset+n]) << 4) |
hex_from_char(linebuff[dollar_offset+n+1]);
}
/* Store the packet prefix in the hash table */
line_prefix_info = g_malloc(sizeof(line_prefix_info_t));
@ -474,29 +457,9 @@ catapult_dct2000_seek_read(wtap *wth, long seek_off,
/*********************/
/* Write stub header */
stub_offset = write_stub_header((char*)pd, timestamp_string,
direction, encap);
strcpy((char*)pd, context_name);
stub_offset += (strlen(context_name) + 1);
/* Context port number */
pd[stub_offset] = context_port;
stub_offset++;
/* Timestamp within file */
strcpy((char*)&pd[stub_offset], timestamp_string);
stub_offset += (strlen(timestamp_string) + 1);
/* Protocol name */
strcpy((char*)&pd[stub_offset], protocol_name);
stub_offset += (strlen(protocol_name) + 1);
/* Direction */
pd[stub_offset] = direction;
stub_offset++;
/* Encap */
pd[stub_offset] = encap;
stub_offset++;
/********************************/
/* Copy packet data into buffer */
@ -776,6 +739,9 @@ gboolean parse_line(gint line_length, gint *seconds, gint *useconds,
int n = 0;
int port_digits = 0;
char port_number_string[MAX_PORT_DIGITS+1];
int variant_digits = 0;
char variant_number_string[MAX_VARIANT_DIGITS+1];
int protocol_chars = 0;
char seconds_buff[MAX_SECONDS_CHARS+1];
@ -859,6 +825,8 @@ gboolean parse_line(gint line_length, gint *seconds, gint *useconds,
{
return FALSE;
}
/* Skip it */
n++;
/******************************************************************/
@ -931,6 +899,32 @@ gboolean parse_line(gint line_length, gint *seconds, gint *useconds,
}
/* Following the / is the variant number. No digits indicate 1 */
for (variant_digits = 0;
(isdigit(linebuff[n])) && (variant_digits <= MAX_VARIANT_DIGITS) && (n+1 < line_length);
n++, variant_digits++)
{
if (!isdigit(linebuff[n]))
{
return FALSE;
}
variant_number_string[variant_digits] = linebuff[n];
}
if (variant_digits > MAX_VARIANT_DIGITS || (n+1 >= line_length))
{
return FALSE;
}
if (variant_digits > 0)
{
variant_number_string[variant_digits] = '\0';
variant = atoi(variant_number_string);
}
else
{
variant = 1;
}
/* Find separate ATM header if necessary */
if (atm_header_present)
{
@ -1088,6 +1082,44 @@ gboolean parse_line(gint line_length, gint *seconds, gint *useconds,
return TRUE;
}
/*****************************************************************/
/* Write the stub info to the data buffer while reading a packet */
/*****************************************************************/
int write_stub_header(guchar *frame_buffer, char *timestamp_string,
packet_direction_t direction, int encap)
{
int stub_offset = 0;
strcpy((char*)frame_buffer, context_name);
stub_offset += (strlen(context_name) + 1);
/* Context port number */
frame_buffer[stub_offset] = context_port;
stub_offset++;
/* Timestamp within file */
strcpy((char*)&frame_buffer[stub_offset], timestamp_string);
stub_offset += (strlen(timestamp_string) + 1);
/* Protocol name */
strcpy((char*)&frame_buffer[stub_offset], protocol_name);
stub_offset += (strlen(protocol_name) + 1);
/* Protocol variant number */
frame_buffer[stub_offset] = variant;
stub_offset++;
/* Direction */
frame_buffer[stub_offset] = direction;
stub_offset++;
/* Encap */
frame_buffer[stub_offset] = (guint8)encap;
stub_offset++;
return stub_offset;
}
/**************************************************************/
/* Set pseudo-header info depending upon packet encapsulation */

View File

@ -27,3 +27,4 @@ int catapult_dct2000_dump_can_write_encap(int encap);
#define DCT2000_ENCAP_UNHANDLED 0
#define DCT2000_ENCAP_SSCOP 101
#define DCT2000_ENCAP_MTP2 102