Update: Primarily to suggest calling conversation_set_dissector()

once a packet has been identified as being part of
        a particular protocol.

svn path=/trunk/; revision=47621
This commit is contained in:
Bill Meier 2013-02-11 00:12:59 +00:00
parent 2f156d0edc
commit 32834b7881
1 changed files with 88 additions and 113 deletions

View File

@ -64,10 +64,15 @@ SCTP, TCP, TIPC and UDP dissectors all provide this capability via their
"Try heuristic sub-dissectors first" preference, but none of them have this
option enabled by default.
Once a packet for a particular "connection" has been identified as belonging
to a particular protocol, wireshark should then be set up to always directly
call the dissector for that protocol. This removes the overhead of having
to identify each packet of the connection heuristically.
How do these heuristics work?
-----------------------------
Difficult to give a general answer here. The usual heuristic works as follows:
It's difficult to give a general answer here. The usual heuristic works as follows:
A HD looks into the first few packet bytes and searches for common patterns that
are specific to the protocol in question. Most protocols starts with a
@ -96,7 +101,7 @@ Heuristic Code Example
----------------------
You can find a lot of code examples in the wireshark sources, e.g.:
grep -l heur_dissector_add epan/dissectors/*.c
returns (currently) 68 files.
returns 132 files (Feb 2013).
For the above example criteria, the following code example might do the work
(combine this with the dissector skeleton in README.developer):
@ -104,45 +109,68 @@ For the above example criteria, the following code example might do the work
XXX - please note: The following code examples were not tried in reality,
please report problems to the dev-list!
static gboolean dissect_PROTOABBREV(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
--------------------------------------------------------------------------------------------
static dissector_handle_t PROTOABBREV_handle;
static void
dissect_PROTOABBREV(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void *data _U_)
{
/* Dissection ... */
return;
}
static gboolean
dissect_PROTOABBREV_heur(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void *data _U_)
{
...
/* 1) first byte must be 0x42 */
if ( tvb_get_guint8(tvb, 0) != 0x42 )
/* 1) first byte must be 0x42 */
if ( tvb_get_guint8(tvb, 0) != 0x42 )
return (FALSE);
/* 2) second byte is a type field and only can contain values between 0x20-0x33 */
if ( tvb_get_guint8(tvb, 1) < 0x20 || tvb_get_guint8(tvb, 1) > 0x33 )
/* 2) second byte is a type field and only can contain values between 0x20-0x33 */
if ( tvb_get_guint8(tvb, 1) < 0x20 || tvb_get_guint8(tvb, 1) > 0x33 )
return (FALSE);
/* 3) third byte is a flag field, where the lower 4 bits always contain the value 0 */
if ( tvb_get_guint8(tvb, 2) & 0x0f )
/* 3) third byte is a flag field, where the lower 4 bits always contain the value 0 */
if ( tvb_get_guint8(tvb, 2) & 0x0f )
return (FALSE);
/* 4) fourth and fifth bytes contains a 16 bit length field, where the value can't be longer than 10000 bytes */
/* Assumes network byte order */
if ( tvb_get_ntohs(tvb, 3) > 10000 )
/* 4) fourth and fifth bytes contains a 16 bit length field, where the value can't be longer than 10000 bytes */
/* Assumes network byte order */
if ( tvb_get_ntohs(tvb, 3) > 10000 )
return (FALSE);
/* Assume it's your packet and do dissection */
...
/* Assume it's your packet ... */
return (TRUE);
/* specify that dissect_PROTOABBREV is to be called directly from now on for packets for this "connection" ... */
conversation = find_or_create_conversation(pinfo);
conversation_set_dissector(conversation, PROTOABBREV_handle);
/* and do the dissection 8/
dissect_PROTOABBREV(tvb, pinfo, tree, data);
return (TRUE);
}
void
proto_reg_handoff_PROTOABBREV(void)
{
static int PROTOABBREV_inited = FALSE;
PROABBREV_handle = create_dissector_handle(dissect_PROTOABBREV,
proto_PROTOABBREV);
if ( !PROTOABBREV_inited )
{
/* register as heuristic dissector for both TCP and UDP */
heur_dissector_add("tcp", dissect_PROTOABBREV, proto_PROTOABBREV);
heur_dissector_add("udp", dissect_PROTOABBREV, proto_PROTOABBREV);
}
#ifdef OPTIONAL
/* It's possible to write a dissector to be a dual heuristic/normal dissector */
/* by also registering the dissector "normally". */
dissector_add_uint("ip.proto", IP_PROTO_PROTOABBREV, PROTOABBREV_handle);
#endif
}
@ -155,58 +183,5 @@ tendency to reuse known port numbers for new protocols. But TCP and UDP are
not the only dissectors that provide support for HDs. You can find more
examples by searching the Wireshark sources as follows:
grep -l register_heur_dissector_list epan/dissectors/packet-*.c
returns (currently) 25 files.
It's possible to write a dissector to be a dual heuristic/normal dissector.
In that the case, dissect_PROTOABBREV should return an int with the number of
bytes dissected by your protocol rather than simply returning TRUE. If
heuristics fail, still just return 0.
static int dissect_PROTOABBREV(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
{
...
/* 1) first byte must be 0x42 */
if ( tvb_get_guint8(tvb, 0) != 0x42 )
return 0;
/* 2) second byte is a type field and only can contain values between 0x20-0x33 */
if ( tvb_get_guint8(tvb, 1) < 0x20 || tvb_get_guint8(tvb, 1) > 0x33 )
return 0;
/* 3) third byte is a flag field, where the lower 4 bits always contain the value 0 */
if ( tvb_get_guint8(tvb, 2) & 0x0f )
return 0;
/* 4) fourth and fifth bytes contains a 16 bit length field, where the value can't be longer than 10000 bytes */
/* Assumes network byte order */
if ( tvb_get_ntohs(tvb, 3) > 10000 )
return 0;
/* Assume it's your packet and do dissection */
...
return number_of_bytes_dissected;
}
void
proto_reg_handoff_PROTOABBREV(void)
{
static int PROTOABBREV_inited = FALSE;
dissector_handle_t PROTOABBREV_handle;
if ( !PROTOABBREV_inited )
{
/* register as heuristic dissector for both TCP and UDP */
heur_dissector_add("tcp", dissect_PROTOABBREV, proto_PROTOABBREV);
heur_dissector_add("udp", dissect_PROTOABBREV, proto_PROTOABBREV);
/* register as normal dissector for IP as well */
PROTOABBREV_handle = new_create_dissector_handle(dissect_PROTOABBREV,
proto_PROTOABBREV);
dissector_add_uint("ip.proto", IP_PROTO_PROTOABBREV, PROTOABBREV_handle);
PROTOABBREV_inited = TRUE;
}
}
returns 38 files (Feb 2013).