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:
parent
28509cb311
commit
1814821adc
|
@ -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);
|
||||
}
|
||||
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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",
|
||||
|
|
|
@ -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")) ||
|
||||
|
|
|
@ -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 */
|
||||
|
|
|
@ -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
|
||||
|
||||
|
|
Loading…
Reference in New Issue