From Graham Bloice:
[obnox/wireshark/wip.git] / docbook / wsdg_src / WSDG_chapter_dissection.xml
index d22f04863a8cea87da9a0a66a00154cb3b3a04e9..69d229a0d00ff1bcac11c629147d7e7d4c32bf3d 100644 (file)
@@ -536,9 +536,10 @@ static const value_string packettypenames[] = {
    <programlisting>
    <![CDATA[
        { &hf_foo_pdu_type,
-       { "FOO PDU Type",           "foo.type",
-       FT_UINT8, BASE_DEC, VALS(packettypenames), 0x0,
-       "", HFILL }
+               { "FOO PDU Type", "foo.type",
+               FT_UINT8, BASE_DEC,
+               VALS(packettypenames), 0x0,
+               NULL, HFILL }
        },
 ]]>    
    </programlisting></example>
@@ -558,19 +559,22 @@ static int hf_foo_endflag = -1;
 static int hf_foo_priorityflag = -1;
 ...
        { &hf_foo_startflag,
-       { "FOO PDU Start Flags",           "foo.flags.start",
-       FT_BOOLEAN, 8, NULL, FOO_START_FLAG,
-       "", HFILL }
+               { "FOO PDU Start Flags", "foo.flags.start",
+               FT_BOOLEAN, 8, 
+               NULL, FOO_START_FLAG,
+               NULL, HFILL }
        },
        { &hf_foo_endflag,
-       { "FOO PDU End Flags",           "foo.flags.end",
-       FT_BOOLEAN, 8, NULL, FOO_END_FLAG,
-       "", HFILL }
+               { "FOO PDU End Flags", "foo.flags.end",
+               FT_BOOLEAN, 8,
+               NULL, FOO_END_FLAG,
+               NULL, HFILL }
        },
        { &hf_foo_priorityflag,
-       { "FOO PDU Priority Flags",           "foo.flags.priority",
-       FT_BOOLEAN, 8, NULL, FOO_PRIORITY_FLAG,
-       "", HFILL }
+               { "FOO PDU Priority Flags", "foo.flags.priority",
+               FT_BOOLEAN, 8, 
+               NULL, FOO_PRIORITY_FLAG,
+               NULL, HFILL }
        },
 ...
        proto_tree_add_item(foo_tree, hf_foo_flags, tvb, offset, 1, FALSE);
@@ -678,7 +682,6 @@ dissect_foo(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
                next_tvb = tvb_new_real_data(decompressed_buffer, orig_size, orig_size);
                tvb_set_child_real_data_tvbuff(tvb, next_tvb);
                add_new_data_source(pinfo, next_tvb, "Decompressed Data");
-               tvb_set_free_cb(next_tvb, g_free);
        } else {
                next_tvb = tvb_new_subset(tvb, offset, -1, -1);
        }
@@ -982,12 +985,95 @@ static gint *ett[] =
    The other variables are used for flagging up errors.
    </para>
        </section>
+       <section id="TcpDissectPdus">
+               <title>How to reassemble split TCP Packets</title>
+               <para>  
+                       A dissector gets a tvbuff_t pointer which holds the payload
+                       of a TCP packet. This payload contains the header and data
+                       of your application layer protocol.
+               </para>
+               <para>
+                       When dissecting an application layer protocol you cannot assume
+                       that each TCP packet contains exactly one application layer message.
+                       One application layer message can be split into several TCP packets.
+               </para>
+               <para>
+                       You also cannot assume the a TCP packet contains only one application layer message
+                       and that the message header is at the start of your TCP payload.
+                       More than one messages can be transmitted in one TCP packet,
+                       so that a message can start at an abitrary position.
+                       
+               </para>
+               <para>
+                       This sounds complicated, but there is a simple solution.
+                       <methodname>tcp_dissect_pdus()</methodname> does all this tcp packet reassembling for you.
+                       This function is implemented in <filename>epan/dissectors/packet-tcp.h</filename>.
+               </para>
+               <example>
+                       <title>Reassembling TCP fragments</title>
+                       <programlisting>
+<![CDATA[
+#ifdef HAVE_CONFIG_H
+# include "config.h"
+#endif
+
+#include <gmodule.h>
+#include <epan/packet.h>
+#include <epan/emem.h>
+#include <epan/dissectors/packet-tcp.h>
+#include <epan/prefs.h>
+
+...
+
+#define FRAME_HEADER_LEN 8
+
+/* The main dissecting routine */
+static void dissect_foo(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
+{
+    tcp_dissect_pdus(tvb, pinfo, tree, TRUE, FRAME_HEADER_LEN,
+                     get_foo_message_len, dissect_foo_message);
+}
+
+/* This method dissects fully reassembled messages */
+static void dissect_foo_message(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
+{
+    /* TODO: implement your dissecting code */
+}
+
+/* determine PDU length of protocol foo */
+static guint get_foo_message_len(packet_info *pinfo, tvbuff_t *tvb, int offset)
+{
+    /* TODO: change this to your needs */
+    return (guint)tvb_get_ntohl(tvb, offset+4); /* e.g. length is at offset 4 */
+}
+
+...
+]]>
+                       </programlisting>
+               </example>
+               <para>
+                       As you can see this is really simple. Just call <function>tcp_dissect_pdus()</function> in
+                       your main dissection routine and move you message parsing code into another function.
+                       This function gets called whenever a message has been reassembled.
+               </para>
+               <para>
+                       The parameters <parameter>tvb</parameter>, <parameter>pinfo</parameter> and <parameter>tree</parameter> 
+                       are just handed over to <function>tcp_dissect_pdus()</function>.
+                       The 4th parameter is a flag to indicate if the data should be reassebled or not. This could be set 
+                       according to a dissector preference as well.
+                       Parameter 5 indicates how much data has at least to be available to be able to determine the length 
+                       of the foo message.
+                       Parameter 6 is a function pointer to a method that returns this length. It gets called when at least 
+                       the number of bytes given in the previous parameter is available.
+                       Parameter 7 is a function pointer to your real message dissector.
+               </para>
+       </section>
   </section>
   <section id="ChDissectTap">
        <title>How to tap protocols</title>
        <para>
        Adding a Tap interface to a protocol allows it to do some useful things.
-       In particular you can produce protocol statistics from teh tap interface.
+       In particular you can produce protocol statistics from the tap interface.
        </para>
        <para>
        A tap is basically a way of allowing other items to see whats happening as