aboutsummaryrefslogtreecommitdiffstats
path: root/doc
diff options
context:
space:
mode:
authorMichael Mann <mmann78@netscape.net>2015-08-18 23:14:09 -0400
committerMichael Mann <mmann78@netscape.net>2015-11-01 21:42:51 +0000
commitad1b785fe80df6ecffee396a617960e1af390274 (patch)
tree0243a68966024410257dc7004688bb3f3ef3869d /doc
parent69e61db3aea6fa70e8ff38c9184b0206ce85ebd3 (diff)
udp_dissect_pdus follow-up
Add heuristic support Better documentation Change-Id: I236c1f4d3613aa58d608aee0e5edc40c3b158d25 Reviewed-on: https://code.wireshark.org/review/10120 Petri-Dish: Michael Mann <mmann78@netscape.net> Tested-by: Petri Dish Buildbot <buildbot-no-reply@wireshark.org> Reviewed-by: Michael Mann <mmann78@netscape.net>
Diffstat (limited to 'doc')
-rw-r--r--doc/README.dissector93
-rw-r--r--doc/README.heuristic35
2 files changed, 104 insertions, 24 deletions
diff --git a/doc/README.dissector b/doc/README.dissector
index 97db00b14f..0a9d7ae043 100644
--- a/doc/README.dissector
+++ b/doc/README.dissector
@@ -3147,7 +3147,92 @@ will then be added to the protocol tree. Note that there may be more
than one complete C string in the tvbuff, so the dissection is done in a
loop.
-2.8 ptvcursors.
+2.8 Using udp_dissect_pdus().
+
+As noted in section 2.7.1, TCP has an API to dissect its PDU that can handle
+a PDU spread across multiple packets or multiple PDUs spread across a single
+packet. This section describes a similar mechanism for UDP, but is only
+applicable for one or more PDUs in a single packet. If a protocol runs on top
+of TCP as well as UDP, a common PDU dissection function can be created for both.
+
+To register the distinct dissector functions, consider the following
+example using UDP and TCP dissection, stolen from packet-dnp.c:
+
+ #include "packet-tcp.h"
+ #include "packet-udp.h"
+
+ dissector_handle_t dnp3_tcp_handle;
+ dissector_handle_t dnp3_udp_handle;
+
+ dnp3_tcp_handle = new_create_dissector_handle(dissect_dnp3_tcp, proto_dnp3);
+ dnp3_udp_handle = new_create_dissector_handle(dissect_dnp3_udp, proto_dnp3);
+
+ dissector_add_uint("tcp.port", TCP_PORT_DNP, dnp3_tcp_handle);
+ dissector_add_uint("udp.port", UDP_PORT_DNP, dnp3_udp_handle);
+
+Both dissect_dnp3_tcp and dissect_dnp3_udp call tcp_dissect_pdus and
+udp_dissect_pdus respectively, with a reference to the same callbacks which
+are called to handle PDU data.
+
+ static int
+ dissect_dnp3_udp(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void *data)
+ {
+ return udp_dissect_pdus(tvb, pinfo, tree, DNP_HDR_LEN, dnp3_udp_check_header,
+ get_dnp3_message_len, dissect_dnp3_message, data);
+ }
+
+ static int
+ dissect_dnp3_tcp(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void *data)
+ {
+ if (!check_dnp3_header(tvb, FALSE)) {
+ return 0;
+ }
+
+ tcp_dissect_pdus(tvb, pinfo, tree, TRUE, DNP_HDR_LEN,
+ get_dnp3_message_len, dissect_dnp3_message, data);
+
+ return tvb_captured_length(tvb);
+ }
+
+(udp_dissect_pdus has an option of a heuristic check function within it while
+tcp_dissect_pdus does not, so it's done outside)
+
+The arguments to udp_dissect_pdus are:
+
+ the tvbuff pointer, packet_info pointer, and proto_tree pointer
+ passed to the dissector;
+
+ the number of bytes of PDU data required to determine the length
+ of the PDU;
+
+ an optional routine (passing NULL is okay) that takes as arguments a
+ packet_info pointer, a tvbuff pointer and an offset value representing the
+ offset into the tvbuff at which a PDU begins, and a void pointer for user
+ data, and should return TRUE if the packet belongs to the dissector.
+ The routine must not throw exceptions (it is guaranteed that the
+ number of bytes specified by the previous argument to
+ udp_dissect_pdus is available, but more data might not be available,
+ so don't refer to any data past that);
+
+ a routine that takes as arguments a packet_info pointer, a tvbuff
+ pointer and an offset value representing the offset into the tvbuff
+ at which a PDU begins, and a void pointer for user data, and should
+ return the total length of the PDU in bytes. If return value is 0,
+ it's treated the same as a failed heuristic.
+ The routine must not throw exceptions (it is guaranteed that the
+ number of bytes specified by the previous argument to
+ tcp_dissect_pdus is available, but more data might not be available,
+ so don't refer to any data past that);
+
+ a new_dissector_t routine to dissect the pdu that's passed a tvbuff
+ pointer, packet_info pointer, proto_tree pointer and a void pointer for
+ user data, with the tvbuff containing a possibly-reassembled PDU. (The
+ "reported_length" of the tvbuff will be the length of the PDU);
+
+ a void pointer to user data that is passed to the length-determining
+ routine, and the dissector routine referenced in the previous parameter.
+
+2.9 ptvcursors.
The ptvcursor API allows a simpler approach to writing dissectors for
simple protocols. The ptvcursor API works best for protocols whose fields
@@ -3180,7 +3265,7 @@ To use the ptvcursor API, include the "ptvcursor.h" file. The PGM dissector
is an example of how to use it. You don't need to look at it as a guide;
instead, the API description here should be good enough.
-2.8.1 ptvcursor API.
+2.9.1 ptvcursor API.
ptvcursor_t*
ptvcursor_new(proto_tree* tree, tvbuff_t* tvb, gint offset)
@@ -3236,7 +3321,7 @@ If the length is unknown, length may be defined as SUBTREE_UNDEFINED_LENGTH.
In this case, at the next pop, the item length will be equal to the advancement
of the cursor since the creation of the subtree.
-2.8.2 Miscellaneous functions.
+2.9.2 Miscellaneous functions.
tvbuff_t*
ptvcursor_tvbuff(ptvcursor_t* ptvc)
@@ -3259,7 +3344,7 @@ ptvcursor_set_subtree(ptvcursor_t* ptvc, proto_item* it, gint ett_subtree);
Creates a subtree and adds it to the cursor as the working tree but does
not save the old working tree.
-2.9 Optimizations
+2.10 Optimizations
A protocol dissector may be called in 2 different ways - with, or
without a non-null "tree" argument.
diff --git a/doc/README.heuristic b/doc/README.heuristic
index 2c4c8db56d..bac71b5677 100644
--- a/doc/README.heuristic
+++ b/doc/README.heuristic
@@ -103,7 +103,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 163 files (November 2014).
+returns 177 files (October 2015).
For the above example criteria, the following code example might do the work
(combine this with the dissector skeleton in README.developer):
@@ -118,7 +118,7 @@ static dissector_handle_t PROTOABBREV_pdu_handle;
/* Heuristics test */
static gboolean
-test_PROTOABBREV(tvbuff_t *tvb)
+test_PROTOABBREV(packet_info *pinfo _U_, tvbuff_t *tvb, int offset _U_, void *data _U_)
{
/* 0) Verify needed bytes available in tvb so tvb_get...() doesn't cause exception.
if (tvb_captured_length(tvb) < 5)
@@ -172,7 +172,7 @@ dissect_PROTOABBREV_tcp(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, voi
static gboolean
dissect_PROTOABBREV_heur_tcp(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void *data)
{
- if (!test_PROTOABBREV(tvb))
+ if (!test_PROTOABBREV(pinfo, tvb, 0, data))
return FALSE;
/* specify that dissect_PROTOABBREV is to be called directly from now on for
@@ -190,26 +190,21 @@ dissect_PROTOABBREV_heur_tcp(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree
return (TRUE);
}
+static int
+dissect_PROTOABBREV_udp(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void *data)
+{
+ udp_dissect_pdus(tvb, pinfo, tree, TRUE, 5, NULL,
+ get_PROTOABBREV_len, dissect_PROTOABBREV_pdu, data);
+ return tvb_reported_length(tvb);
+}
+
static gboolean
dissect_PROTOABBREV_heur_udp(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void *data)
{
...
- If (!test_PROTOABBREV(tvb))
- return FALSE;
-
- /* specify that dissect_PROTOABBREV is to be called directly from now on for
- * packets for this "connection" ... but only do this if your heuristic sits directly
- * on top of (was called by) a dissector which established a conversation for the
- * protocol "port type". In other words: only directly over TCP, UDP, DCCP, ...
- * otherwise you'll be overriding the dissector that called your heuristic dissector.
- */
- conversation = find_or_create_conversation(pinfo);
- conversation_set_dissector(conversation, PROTOABBREV_pdu_handle);
-
/* and do the dissection */
- dissect_PROTOABBREV_pdu(tvb, pinfo, tree, data);
-
- return (TRUE);
+ return (udp_dissect_pdus(tvb, pinfo, tree, TRUE, 5, test_PROTOABBREV,
+ get_PROTOABBREV_len, dissect_PROTOABBREV_pdu, data) != 0);
}
void
@@ -221,9 +216,9 @@ proto_reg_handoff_PROTOABBREV(void)
proto_PROTOABBREV);
/* register as heuristic dissector for both TCP and UDP */
- heur_dissector_add("tcp", dissect_PROTOABBREV_tcp_heur, "PROTOABBREV over TCP",
+ heur_dissector_add("tcp", dissect_PROTOABBREV_heur_tcp, "PROTOABBREV over TCP",
"PROTOABBREV_tcp", proto_PROTOABBREV, HEURISTIC_ENABLE);
- heur_dissector_add("udp", dissect_PROTOABBREV_udp_heur, "PROTOABBREV over UDP",
+ heur_dissector_add("udp", dissect_PROTOABBREV_heur_udp, "PROTOABBREV over UDP",
"PROTOABBREV_udp", proto_PROTOABBREV, HEURISTIC_ENABLE);
#ifdef OPTIONAL