Convert the dissection chapter to AsciiDoc.
authorGerald Combs <gerald@zing.org>
Mon, 3 Feb 2014 18:28:37 +0000 (10:28 -0800)
committerGerald Combs <gerald@wireshark.org>
Mon, 3 Feb 2014 18:32:32 +0000 (18:32 +0000)
Change-Id: Ieccd2ad235576b9ec6013ddb23a8373ccf2f8cdf
Reviewed-on: https://code.wireshark.org/review/92
Reviewed-by: Gerald Combs <gerald@wireshark.org>
Tested-by: Gerald Combs <gerald@wireshark.org>
docbook/CMakeLists.txt
docbook/Makefile.common
docbook/wsdg_src/WSDG_chapter_dissection.asciidoc [new file with mode: 0644]
docbook/wsdg_src/WSDG_chapter_dissection.xml [deleted file]

index 0e3f5456efb132bf4126ff4bc11c3d960552b4b8..8faee7c266f4190ad5df2f4389e61f5ec2821c56 100644 (file)
@@ -184,7 +184,7 @@ set(WSUG_GRAPHICS
 set(WSDG_FILES
        wsdg_generated_src/WSDG_chapter_build_intro.xml
        wsdg_generated_src/WSDG_chapter_capture.xml
-       wsdg_src/WSDG_chapter_dissection.xml
+       wsdg_generated_src/WSDG_chapter_dissection.xml
        wsdg_generated_src/WSDG_chapter_env_intro.xml
        wsdg_generated_src/WSDG_chapter_libraries.xml
        wsdg_generated_src/WSDG_chapter_quick_setup.xml
@@ -200,6 +200,7 @@ set(WSDG_FILES
 set(WSDG_ASCIIDOC_FILES
        wsdg_src/WSDG_chapter_build_intro.asciidoc
        wsdg_src/WSDG_chapter_capture.asciidoc
+       wsdg_src/WSDG_chapter_dissection.asciidoc
        wsdg_src/WSDG_chapter_env_intro.asciidoc
        wsdg_src/WSDG_chapter_libraries.asciidoc
        wsdg_src/WSDG_chapter_quick_setup.asciidoc
index 524367234745bd8a7ec484ef3700f55236b41326..88e6635d03c8ef1fcc17a2e4327ff7754a6a9e5e 100644 (file)
@@ -161,7 +161,7 @@ WSUG_GRAPHICS =     \
 WSDG_FILES =   \
        wsdg_src/WSDG_chapter_build_intro.asciidoc      \
        wsdg_src/WSDG_chapter_capture.asciidoc          \
-       wsdg_src/WSDG_chapter_dissection.xml    \
+       wsdg_src/WSDG_chapter_dissection.asciidoc       \
        wsdg_src/WSDG_chapter_env_intro.asciidoc        \
        wsdg_src/WSDG_chapter_libraries.asciidoc        \
        wsdg_src/WSDG_chapter_quick_setup.asciidoc      \
@@ -176,6 +176,7 @@ WSDG_FILES =        \
 WSDG_GENERATED_SOURCE = \
        wsdg_src/WSDG_chapter_build_intro.xml   \
        wsdg_src/WSDG_chapter_capture.xml       \
+       wsdg_src/WSDG_chapter_dissection.xml    \
        wsdg_src/WSDG_chapter_env_intro.xml     \
        wsdg_src/WSDG_chapter_libraries.xml     \
        wsdg_src/WSDG_chapter_quick_setup.xml   \
diff --git a/docbook/wsdg_src/WSDG_chapter_dissection.asciidoc b/docbook/wsdg_src/WSDG_chapter_dissection.asciidoc
new file mode 100644 (file)
index 0000000..13b8287
--- /dev/null
@@ -0,0 +1,1138 @@
+++++++++++++++++++++++++++++++++++++++
+<!-- WSDG Chapter Dissection -->
+++++++++++++++++++++++++++++++++++++++
+    
+[[ChapterDissection]]
+
+== Packet dissection
+
+[[ChDissectWorks]]
+
+=== How it works
+
+Each dissector decodes its part of the protocol, and then hands off
+decoding to subsequent dissectors for an encapsulated protocol.
+
+Every dissection starts with the Frame dissector which dissects the packet
+details of the capture file itself (e.g. timestamps). From there it passes the
+data on to the the lowest-level data dissector, e.g. the Ethernet dissector for
+the Ethernet header. The payload is then passed on to the next dissector (e.g.
+IP) and so on. At each stage, details of the packet will be decoded and
+displayed.
+
+Dissection can be implemented in two possible ways. One is to have a dissector
+module compiled into the main program, which means it's always available.
+Another way is to make a plugin (a shared library or DLL) that registers itself
+to handle dissection.
+
+There is little difference in having your dissector as either a plugin or
+built-in. On the Windows platform you have limited function access through the
+ABI exposed in 'libwireshark.def', but that is mostly complete.
+
+The big plus is that your rebuild cycle for a plugin is much shorter than for a
+built-in one. So starting with a plugin makes initial development simpler, while
+the finished code may make more sense as a built-in dissector.
+
+[NOTE]
+.Read README.developer
+====
+The file 'doc/README.developer' contains detailed information about implementing
+a dissector. In many cases it is more up to date than this document.
+====
+
+[[ChDissectAdd]]
+
+=== Adding a basic dissector
+
+Let's step through adding a basic dissector. We'll start with the made up "foo"
+protocol. It consists of the following basic items.
+
+* A packet type - 8 bits, possible values: 1 - initialisation, 2 - terminate, 3 - data.
+
+* A set of flags stored in 8 bits, 0x01 - start packet, 0x02 - end packet, 0x04 - priority packet.
+
+* A sequence number - 16 bits.
+
+* An IPv4 address.
+
+[[ChDissectSetup]]
+
+==== Setting up the dissector
+
+The first decision you need to make is if this dissector will be a
+built-in dissector, included in the main program, or a plugin.
+
+Plugins are the easiest to write initially, so let's start with that.
+With a little care, the plugin can be made to run as a built-in
+easily too so we haven't lost anything.
+
+.Dissector Initialisation.
+====
+----
+#include "config.h"
+
+#include <epan/packet.h>
+
+#define FOO_PORT 1234
+
+static int proto_foo = -1;
+
+
+void
+proto_register_foo(void)
+{
+    proto_foo = proto_register_protocol (
+        "FOO Protocol", /* name       */
+        "FOO",      /* short name */
+        "foo"       /* abbrev     */
+        );
+}
+----
+====
+
+Let's go through this a bit at a time. First we have some boilerplate
+include files. These will be pretty constant to start with.
+
+Next we have an int that is initialised to +$$-1$$+ that records our protocol.
+This will get updated when we register this dissector with the main program.
+It's good practice to make all variables and functions that aren't exported
+static to keep name space pollution down. Normally this isn't a problem unless your
+dissector gets so big it has to span multiple files.
+
+Then a +#define+ for the UDP port that carries _foo_ traffic.
+
+Now that we have the basics in place to interact with the main program, we'll
+start with two protocol dissector setup functions.
+
+First we'll call +proto_register_protocol()+ which registers the protocol. We
+can give it three names that will be used for display in various places. The
+full and short name are used in e.g. the "Preferences" and "Enabled protocols"
+dialogs as well as the generated field name list in the documentation. The
+abbreviation is used as the display filter name.
+
+Next we need a handoff routine.
+
+.Dissector Handoff.
+====
+----
+void
+proto_reg_handoff_foo(void)
+{
+    static dissector_handle_t foo_handle;
+
+    foo_handle = create_dissector_handle(dissect_foo, proto_foo);
+    dissector_add_uint("udp.port", FOO_PORT, foo_handle);
+}
+----
+====
+
+What's happening here? We are initialising the dissector. First we create a
+dissector handle; It is associated with the foo protocol and with a routine to
+be called to do the actual dissecting. Then we associate the handle with a UDP
+port number so that the main program will know to call us when it gets UDP
+traffic on that port.
+
+The stardard Wireshark dissector convention is to put +proto_register_foo()+ and
++proto_reg_handoff_foo()+ as the last two functions in the dissector source.
+
+Now at last we get to write some dissecting code. For the moment we'll
+leave it as a basic placeholder.
+
+.Dissection.
+====
+----
+static void
+dissect_foo(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
+{
+    col_set_str(pinfo->cinfo, COL_PROTOCOL, "FOO");
+    /* Clear out stuff in the info column */
+    col_clear(pinfo->cinfo,COL_INFO);
+}
+----
+====
+
+This function is called to dissect the packets presented to it. The packet data
+is held in a special buffer referenced here as tvb. We shall become fairly
+familiar with this as we get deeper into the details of the protocol. The packet
+info structure contains general data about the protocol, and we can update
+information here. The tree parameter is where the detail dissection takes place.
+
+For now we'll do the minimum we can get away with. In the first line we set the
+text of this to our protocol, so everyone can see it's being recognised. The
+only other thing we do is to clear out any data in the INFO column if it's being
+displayed.
+
+At this point we should have a basic dissector ready to compile and install.
+It doesn't do much at present, other than identify the protocol and label it.
+
+In order to compile this dissector and create a plugin a couple of support files
+are required, besides the dissector source in 'packet-foo.c':
+
+* 'Makefile.am' - The UNIX/Linux makefile template.
+
+* 'Makefile.common' - Contains the file names of this plugin.
+
+* 'Makefile.nmake' - Contains the Wireshark plugin makefile for Windows.
+
+* 'moduleinfo.h' - Contains plugin version information.
+
+* 'moduleinfo.nmake' - Contains DLL version info for Windows.
+
+* 'packet-foo.c' - Your dissector source.
+
+* 'plugin.rc.in' - Contains the DLL resource template for Windows.
+
+You can find a good example for these files in the interlink plugin directory.
+'Makefile.common' and 'Makefile.am' have to be modified to reflect the relevant
+files and dissector name. 'moduleinfo.h' and 'moduleinfo.nmake' have to be
+filled in with the version information. Compile the dissector to a DLL or shared
+library and copy it into the plugin directory of the installation.
+
+[[ChDissectDetails]]
+
+==== Dissecting the details of the protocol
+
+Now that we have our basic dissector up and running, let's do something with it.
+The simplest thing to do to start with is to just label the payload.
+This will allow us to set up some of the parts we will need.
+
+The first thing we will do is to build a subtree to decode our results into.
+This helps to keep things looking nice in the detailed display. Now the
+dissector is called in two different cases. In one case it is called to get a
+summary of the packet, in the other case it is called to look into details of
+the packet. These two cases can be distinguished by the tree pointer. If the
+tree pointer is NULL, then we are being asked for a summary. If it is non NULL,
+we can pick apart the protocol for display. So with that in mind, let's enhance
+our dissector.
+
+.Plugin Packet Dissection.
+====
+----
+static void
+dissect_foo(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
+{
+
+    col_set_str(pinfo->cinfo, COL_PROTOCOL, "FOO");
+    /* Clear out stuff in the info column */
+    col_clear(pinfo->cinfo,COL_INFO);
+
+    if (tree) { /* we are being asked for details */
+        proto_item *ti = NULL;
+        ti = proto_tree_add_item(tree, proto_foo, tvb, 0, -1, ENC_NA);
+    }
+}
+----
+====
+
+What we're doing here is adding a subtree to the dissection.
+This subtree will hold all the details of this protocol and so not clutter
+up the display when not required.
+
+We are also marking the area of data that is being consumed by this
+protocol. In our case it's all that has been passed to us, as we're assuming
+this protocol does not encapsulate another.
+Therefore, we add the new tree node with +proto_tree_add_item()+,
+adding it to the passed in tree, label it with the protocol, use the passed in
+tvb buffer as the data, and consume from 0 to the end (-1) of this data.
+ENC_NA ("not applicable") is specified as the "encoding" parameter.
+
+After this change, there should be a label in the detailed display for the protocol,
+and selecting this will highlight the remaining contents of the packet.
+
+Now let's go to the next step and add some protocol dissection. For this step
+we'll need to construct a couple of tables that help with dissection. This needs
+some additions to the +proto_register_foo()+ function shown previously.
+
+Two statically allocated arrays are added at the beginning of
++proto_register_foo()+. The arrays are then registered after the call to
++proto_register_protocol()+.
+
+.Registering data structures.
+====
+----
+void
+proto_register_foo(void)
+{
+    static hf_register_info hf[] = {
+        { &hf_foo_pdu_type,
+            { "FOO PDU Type", "foo.type",
+            FT_UINT8, BASE_DEC,
+            NULL, 0x0,
+            NULL, HFILL }
+        }
+    };
+
+    /* Setup protocol subtree array */
+    static gint *ett[] = {
+        &ett_foo
+    };
+
+    proto_foo = proto_register_protocol (
+        "FOO Protocol", /* name       */
+        "FOO",      /* short name */
+        "foo"       /* abbrev     */
+        );
+
+    proto_register_field_array(proto_foo, hf, array_length(hf));
+    proto_register_subtree_array(ett, array_length(ett));
+}
+----
+====
+
+The variables +hf_foo_pdu_type+ and +ett_foo+ also need to be declared somewhere near the top of the file.
+
+.Dissector data structure globals.
+====
+----
+static int hf_foo_pdu_type = -1;
+
+static gint ett_foo = -1;
+----
+====
+
+Now we can enhance the protocol display with some detail.
+
+.Dissector starting to dissect the packets.
+====
+----
+   if (tree) { /* we are being asked for details */
+        proto_item *ti = NULL;
+        proto_tree *foo_tree = NULL;
+
+        ti = proto_tree_add_item(tree, proto_foo, tvb, 0, -1, ENC_NA);
+        foo_tree = proto_item_add_subtree(ti, ett_foo);
+        proto_tree_add_item(foo_tree, hf_foo_pdu_type, tvb, 0, 1, ENC_BIG_ENDIAN);
+    }   
+----
+====
+
+Now the dissection is starting to look more interesting. We have picked apart
+our first bit of the protocol. One byte of data at the start of the packet
+that defines the packet type for foo protocol.
+
+The +proto_item_add_subtree()+ call has added a child node
+to the protocol tree which is where we will do our detail dissection.
+The expansion of this node is controlled by the +ett_foo+
+variable. This remembers if the node should be expanded or not as you move
+between packets. All subsequent dissection will be added to this tree,
+as you can see from the next call.
+A call to +proto_tree_add_item()+ in the foo_tree,
+this time using the +hf_foo_pdu_type+ to control the formatting
+of the item. The pdu type is one byte of data, starting at 0. We assume it is
+in network order (also called big endian), so that is why we use +ENC_BIG_ENDIAN+.
+For a 1-byte quantity, there is no order issue, but it is good practice to
+make this the same as any multibyte fields that may be present, and as we will
+see in the next section, this particular protocol uses network order.
+
+If we look in detail at the +hf_foo_pdu_type+ declaration in
+the static array we can see the details of the definition.
+
+* 'hf_foo_pdu_type' - The index for this node.
+
+* 'FOO PDU Type' - The label for this item.
+
+* 'foo.type' - This is the filter string. It enables us to type constructs such
+as +foo.type=1+ into the filter box.
+
+* 'FT_UINT8' - This specifies this item is an 8bit unsigned integer.
+This tallies with our call above where we tell it to only look at one byte.
+
+* 'BASE_DEC' - Tor an integer type, this tells it to be printed as a decimal
+number. It could be hexdecimal (BASE_HEX) or octal (BASE_OCT) if that made more sense.
+
+We'll ignore the rest of the structure for now.
+
+If you install this plugin and try it out, you'll see something that begins to look
+useful.
+
+Now let's finish off dissecting the simple protocol. We need to add a few
+more variables to the hfarray, and a couple more procedure calls.
+
+.Wrapping up the packet dissection.
+====
+----
+...
+static int hf_foo_flags = -1;
+static int hf_foo_sequenceno = -1;
+static int hf_foo_initialip = -1;
+...
+
+static void
+dissect_foo(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
+{
+    gint offset = 0;
+
+    ...
+
+    if (tree) { /* we are being asked for details */
+        proto_item *ti = NULL;
+        proto_tree *foo_tree = NULL;
+
+        ti = proto_tree_add_item(tree, proto_foo, tvb, 0, -1, ENC_NA);
+        foo_tree = proto_item_add_subtree(ti, ett_foo);
+        proto_tree_add_item(foo_tree, hf_foo_pdu_type, tvb, offset, 1, ENC_BIG_ENDIAN);
+        offset += 1;
+        proto_tree_add_item(foo_tree, hf_foo_flags, tvb, offset, 1, ENC_BIG_ENDIAN);
+        offset += 1;
+        proto_tree_add_item(foo_tree, hf_foo_sequenceno, tvb, offset, 2, ENC_BIG_ENDIAN);
+        offset += 2;
+        proto_tree_add_item(foo_tree, hf_foo_initialip, tvb, offset, 4, ENC_BIG_ENDIAN);
+        offset += 4;
+    }
+    ...
+}
+
+void
+proto_register_foo(void) {
+    ...
+        ...
+        { &hf_foo_flags,
+            { "FOO PDU Flags", "foo.flags",
+            FT_UINT8, BASE_HEX,
+            NULL, 0x0,
+            NULL, HFILL }
+        },
+        { &hf_foo_sequenceno,
+            { "FOO PDU Sequence Number", "foo.seqn",
+            FT_UINT16, BASE_DEC,
+            NULL, 0x0,
+            NULL, HFILL }
+        },
+        { &hf_foo_initialip,
+            { "FOO PDU Initial IP", "foo.initialip",
+            FT_IPv4, BASE_NONE,
+            NULL, 0x0,
+            NULL, HFILL }
+        },
+        ...
+    ...
+}
+...
+----
+====
+
+This dissects all the bits of this simple hypothetical protocol. We've
+introduced a new variable offsetinto the mix to help keep track of where we are
+in the packet dissection. With these extra bits in place, the whole protocol is
+now dissected.
+
+==== Improving the dissection information
+
+We can certainly improve the display of the protocol with a bit of extra data.
+The first step is to add some text labels. Let's start by labeling the packet
+types. There is some useful support for this sort of thing by adding a couple of
+extra things. First we add a simple table of type to name.
+
+
+.Naming the packet types.
+====
+----
+static const value_string packettypenames[] = {
+    { 1, "Initialise" },
+    { 2, "Terminate" },
+    { 3, "Data" },
+    { 0, NULL }
+};   
+----
+====
+
+This is a handy data structure that can be used to look up a name for a value.
+There are routines to directly access this lookup table, but we don't need to
+do that, as the support code already has that added in. We just have to give
+these details to the appropriate part of the data, using the +VALS+ macro.
+
+.Adding Names to the protocol.
+====
+----
+   { &hf_foo_pdu_type,
+        { "FOO PDU Type", "foo.type",
+        FT_UINT8, BASE_DEC,
+        VALS(packettypenames), 0x0,
+        NULL, HFILL }
+    }
+----
+====
+
+This helps in deciphering the packets, and we can do a similar thing for the
+flags structure. For this we need to add some more data to the table though.
+
+.Adding Flags to the protocol.
+====
+----
+#define FOO_START_FLAG 0x01
+#define FOO_END_FLAG        0x02
+#define FOO_PRIORITY_FLAG   0x04
+
+static int hf_foo_startflag = -1;
+static int hf_foo_endflag = -1;
+static int hf_foo_priorityflag = -1;
+
+static void
+dissect_foo(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
+{
+    ...
+        ...
+        proto_tree_add_item(foo_tree, hf_foo_flags, tvb, offset, 1, ENC_BIG_ENDIAN);
+        proto_tree_add_item(foo_tree, hf_foo_startflag, tvb, offset, 1, ENC_BIG_ENDIAN);
+        proto_tree_add_item(foo_tree, hf_foo_endflag, tvb, offset, 1, ENC_BIG_ENDIAN);
+        proto_tree_add_item(foo_tree, hf_foo_priorityflag, tvb, offset, 1, ENC_BIG_ENDIAN);
+        offset += 1;
+        ...
+    ...
+}
+
+void
+proto_register_foo(void) {
+    ...
+        ...
+        { &hf_foo_startflag,
+            { "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,
+            NULL, HFILL }
+        },
+        { &hf_foo_priorityflag,
+            { "FOO PDU Priority Flags", "foo.flags.priority",
+            FT_BOOLEAN, 8,
+            NULL, FOO_PRIORITY_FLAG,
+            NULL, HFILL }
+        },
+        ...
+    ...
+}
+...
+----
+====
+
+Some things to note here. For the flags, as each bit is a different flag, we use
+the type +FT_BOOLEAN+, as the flag is either on or off. Second, we include the flag
+mask in the 7th field of the data, which allows the system to mask the relevant bit.
+We've also changed the 5th field to 8, to indicate that we are looking at an 8 bit
+quantity when the flags are extracted. Then finally we add the extra constructs
+to the dissection routine. Note we keep the same offset for each of the flags.
+
+This is starting to look fairly full featured now, but there are a couple of
+other things we can do to make things look even more pretty. At the moment our
+dissection shows the packets as "Foo Protocol" which whilst correct is a little
+uninformative. We can enhance this by adding a little more detail. First, let's
+get hold of the actual value of the protocol type. We can use the handy function
++tvb_get_guint8()+ to do this. With this value in hand, there are a couple of
+things we can do. First we can set the INFO column of the non-detailed view to
+show what sort of PDU it is - which is extremely helpful when looking at
+protocol traces. Second, we can also display this information in the dissection
+window.
+
+.Enhancing the display.
+====
+----
+static void
+dissect_foo(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
+{
+    guint8 packet_type = tvb_get_guint8(tvb, 0);
+
+    col_set_str(pinfo->cinfo, COL_PROTOCOL, "FOO");
+    /* Clear out stuff in the info column */
+    col_clear(pinfo->cinfo,COL_INFO);
+    col_add_fstr(pinfo->cinfo, COL_INFO, "Type %s",
+             val_to_str(packet_type, packettypenames, "Unknown (0x%02x)"));
+
+    if (tree) { /* we are being asked for details */
+        proto_item *ti = NULL;
+        proto_tree *foo_tree = NULL;
+        gint offset = 0;
+
+        ti = proto_tree_add_item(tree, proto_foo, tvb, 0, -1, ENC_NA);
+        proto_item_append_text(ti, ", Type %s",
+            val_to_str(packet_type, packettypenames, "Unknown (0x%02x)"));
+        foo_tree = proto_item_add_subtree(ti, ett_foo);
+        proto_tree_add_item(foo_tree, hf_foo_pdu_type, tvb, offset, 1, ENC_BIG_ENDIAN);
+        offset += 1;
+    }
+}
+----
+====
+
+So here, after grabbing the value of the first 8 bits, we use it with one of the
+built-in utility routines +val_to_str()+, to lookup the value. If the value
+isn't found we provide a fallback which just prints the value in hex. We use
+this twice, once in the INFO field of the columns -- if it's displayed, and
+similarly we append this data to the base of our dissecting tree.
+
+[[ChDissectTransformed]]
+
+=== How to handle transformed data
+
+Some protocols do clever things with data. They might possibly
+encrypt the data, or compress data, or part of it. If you know
+how these steps are taken it is possible to reverse them within the
+dissector.
+
+As encryption can be tricky, let's consider the case of compression.
+These techniques can also work for other transformations of data,
+where some step is required before the data can be examined.
+
+What basically needs to happen here, is to identify the data that needs
+conversion, take that data and transform it into a new stream, and then call a
+dissector on it. Often this needs to be done "on-the-fly" based on clues in the
+packet. Sometimes this needs to be used in conjunction with other techniques,
+such as packet reassembly. The following shows a technique to achieve this
+effect.
+
+.Decompressing data packets for dissection.
+====
+----
+    guint8 flags = tvb_get_guint8(tvb, offset);
+    offset ++;
+    if (flags & FLAG_COMPRESSED) { /* the remainder of the packet is compressed */
+        guint16 orig_size = tvb_get_ntohs(tvb, offset);
+        guchar *decompressed_buffer = (guchar*)g_malloc(orig_size);
+        offset += 2;
+        decompress_packet(tvb_get_ptr(tvb, offset, -1),
+                tvb_length_remaining(tvb, offset),
+                decompressed_buffer, orig_size);
+        /* Now re-setup the tvb buffer to have the new data */
+        next_tvb = tvb_new_child_real_data(tvb, decompressed_buffer, orig_size, orig_size);
+        tvb_set_free_cb(next_tvb, g_free);
+        add_new_data_source(pinfo, next_tvb, "Decompressed Data");
+    } else {
+        next_tvb = tvb_new_subset_remaining(tvb, offset);
+    }
+    offset = 0;
+    /* process next_tvb from here on */
+----
+====
+
+The first steps here are to recognise the compression. In this case a flag byte
+alerts us to the fact the remainder of the packet is compressed. Next we
+retrieve the original size of the packet, which in this case is conveniently
+within the protocol. If it's not, it may be part of the compression routine to
+work it out for you, in which case the logic would be different.
+
+So armed with the size, a buffer is allocated to receive the uncompressed data
+using +g_malloc()+, and the packet is decompressed into it. The +tvb_get_ptr()+
+function is useful to get a pointer to the raw data of the packet from the
+offset onwards. In this case the decompression routine also needs to know the
+length, which is given by the +tvb_length_remaining()+ function.
+
+Next we build a new tvb buffer from this data, using the
++tvb_new_child_real_data()+ call. This data is a child of our original data, so
+calling this function also acknowledges that. One procedural step is to add a
+callback handler to free the data when it's no longer needed via a call to
++tvb_set_free_cb()+. In this case +g_malloc()+ was used to allocate the memory,
+so +g_free()+ is the appropriate callback function. Finally we add this tvb as a
+new data source, so that the detailed display can show the decompressed bytes as
+well as the original.
+
+After this has been set up the remainder of the dissector can dissect the buffer
+next_tvb, as it's a new buffer the offset needs to be 0 as we start again from
+the beginning of this buffer. To make the rest of the dissector work regardless
+of whether compression was involved or not, in the case that compression was not
+signaled, we use +tvb_new_subset_remaining()+ to deliver us a new buffer based
+on the old one but starting at the current offset, and extending to the end.
+This makes dissecting the packet from this point on exactly the same regardless
+of compression.
+
+[[ChDissectReassemble]]
+
+=== How to reassemble split packets
+
+Some protocols have times when they have to split a large packet across
+multiple other packets. In this case the dissection can't be carried out correctly
+until you have all the data. The first packet doesn't have enough data,
+and the subsequent packets don't have the expect format.
+To dissect these packets you need to wait until all the parts have
+arrived and then start the dissection.
+
+[[ChDissectReassembleUdp]]
+
+==== How to reassemble split UDP packets
+
+As an example, let's examine a protocol that is layered on top of UDP that
+splits up its own data stream. If a packet is bigger than some given size, it
+will be split into chunks, and somehow signaled within its protocol.
+
+To deal with such streams, we need several things to trigger from. We need to
+know that this packet is part of a multi-packet sequence. We need to know how
+many packets are in the sequence. We also need to know when we have all the
+packets.
+
+For this example we'll assume there is a simple in-protocol signaling mechanism
+to give details. A flag byte that signals the presence of a multi-packet
+sequence and also the last packet, followed by an ID of the sequence and a
+packet sequence number.
+
+----
+msg_pkt ::= SEQUENCE {
+    .....
+    flags ::= SEQUENCE {
+        fragment    BOOLEAN,
+        last_fragment   BOOLEAN,
+    .....
+    }
+    msg_id  INTEGER(0..65535),
+    frag_id INTEGER(0..65535),
+    .....
+}
+----
+
+.Reassembling fragments - Part 1
+====
+----
+#include <epan/reassemble.h>
+   ...
+save_fragmented = pinfo->fragmented;
+flags = tvb_get_guint8(tvb, offset); offset++;
+if (flags & FL_FRAGMENT) { /* fragmented */
+    tvbuff_t* new_tvb = NULL;
+    fragment_data *frag_msg = NULL;
+    guint16 msg_seqid = tvb_get_ntohs(tvb, offset); offset += 2;
+    guint16 msg_num = tvb_get_ntohs(tvb, offset); offset += 2;
+
+    pinfo->fragmented = TRUE;
+    frag_msg = fragment_add_seq_check(tvb, offset, pinfo,
+        msg_seqid, /* ID for fragments belonging together */
+        msg_fragment_table, /* list of message fragments */
+        msg_reassembled_table, /* list of reassembled messages */
+        msg_num, /* fragment sequence number */
+        tvb_length_remaining(tvb, offset), /* fragment length - to the end */
+        flags & FL_FRAG_LAST); /* More fragments? */
+----
+====
+
+We start by saving the fragmented state of this packet, so we can restore it
+later. Next comes some protocol specific stuff, to dig the fragment data out of
+the stream if it's present. Having decided it is present, we let the function
++fragment_add_seq_check()+ do its work. We need to provide this with a certain
+amount of data.
+
+* The tvb buffer we are dissecting.
+
+* The offset where the partial packet starts.
+
+* The provided packet info.
+
+* The sequence number of the fragment stream. There may be several streams of
+  fragments in flight, and this is used to key the relevant one to be used for
+  reassembly.
+
+* The +msg_fragment_table+ and the +msg_reassembled_table+ are variables we need
+  to declare. We'll consider these in detail later.
+
+* msg_num is the packet number within the sequence.
+
+* The length here is specified as the rest of the tvb as we want the rest of the packet data.
+
+* Finally a parameter that signals if this is the last fragment or not. This
+  might be a flag as in this case, or there may be a counter in the protocol.
+
+.Reassembling fragments part 2
+====
+----
+    new_tvb = process_reassembled_data(tvb, offset, pinfo,
+        "Reassembled Message", frag_msg, &msg_frag_items,
+        NULL, msg_tree);
+
+    if (frag_msg) { /* Reassembled */
+        col_append_str(pinfo->cinfo, COL_INFO,
+                " (Message Reassembled)");
+    } else { /* Not last packet of reassembled Short Message */
+        col_append_fstr(pinfo->cinfo, COL_INFO,
+                " (Message fragment %u)", msg_num);
+    }
+
+    if (new_tvb) { /* take it all */
+        next_tvb = new_tvb;
+    } else { /* make a new subset */
+        next_tvb = tvb_new_subset(tvb, offset, -1, -1);
+    }
+}
+else { /* Not fragmented */
+    next_tvb = tvb_new_subset(tvb, offset, -1, -1);
+}
+
+.....
+pinfo->fragmented = save_fragmented;
+----
+====
+
+Having passed the fragment data to the reassembly handler, we can now check if
+we have the whole message. If there is enough information, this routine will
+return the newly reassembled data buffer.
+
+After that, we add a couple of informative messages to the display to show that
+this is part of a sequence. Then a bit of manipulation of the buffers and the
+dissection can proceed. Normally you will probably not bother dissecting further
+unless the fragments have been reassembled as there won't be much to find.
+Sometimes the first packet in the sequence can be partially decoded though if
+you wish.
+
+Now the mysterious data we passed into the +fragment_add_seq_check()+.
+
+.Reassembling fragments - Initialisation
+====
+----
+static GHashTable *msg_fragment_table = NULL;
+static GHashTable *msg_reassembled_table = NULL;
+
+static void
+msg_init_protocol(void)
+{
+    fragment_table_init(&msg_fragment_table);
+    reassembled_table_init(&msg_reassembled_table);
+}   
+----
+====
+
+First a couple of hash tables are declared, and these are initialised in the
+protocol initialisation routine. Following that, a +fragment_items+ structure is
+allocated and filled in with a series of ett items, hf data items, and a string
+tag. The ett and hf values should be included in the relevant tables like all
+the other variables your protocol may use. The hf variables need to be placed in
+the structure something like the following. Of course the names may need to be
+adjusted.
+
+.Reassembling fragments - Data
+====
+----
+...
+static int hf_msg_fragments = -1;
+static int hf_msg_fragment = -1;
+static int hf_msg_fragment_overlap = -1;
+static int hf_msg_fragment_overlap_conflicts = -1;
+static int hf_msg_fragment_multiple_tails = -1;
+static int hf_msg_fragment_too_long_fragment = -1;
+static int hf_msg_fragment_error = -1;
+static int hf_msg_fragment_count = -1;
+static int hf_msg_reassembled_in = -1;
+static int hf_msg_reassembled_length = -1;
+...
+static gint ett_msg_fragment = -1;
+static gint ett_msg_fragments = -1;
+...
+static const fragment_items msg_frag_items = {
+    /* Fragment subtrees */
+    &ett_msg_fragment,
+    &ett_msg_fragments,
+    /* Fragment fields */
+    &hf_msg_fragments,
+    &hf_msg_fragment,
+    &hf_msg_fragment_overlap,
+    &hf_msg_fragment_overlap_conflicts,
+    &hf_msg_fragment_multiple_tails,
+    &hf_msg_fragment_too_long_fragment,
+    &hf_msg_fragment_error,
+    &hf_msg_fragment_count,
+    /* Reassembled in field */
+    &hf_msg_reassembled_in,
+    /* Reassembled length field */
+    &hf_msg_reassembled_length,
+    /* Tag */
+    "Message fragments"
+};
+...
+static hf_register_info hf[] =
+{
+...
+{&hf_msg_fragments,
+    {"Message fragments", "msg.fragments",
+    FT_NONE, BASE_NONE, NULL, 0x00, NULL, HFILL } },
+{&hf_msg_fragment,
+    {"Message fragment", "msg.fragment",
+    FT_FRAMENUM, BASE_NONE, NULL, 0x00, NULL, HFILL } },
+{&hf_msg_fragment_overlap,
+    {"Message fragment overlap", "msg.fragment.overlap",
+    FT_BOOLEAN, 0, NULL, 0x00, NULL, HFILL } },
+{&hf_msg_fragment_overlap_conflicts,
+    {"Message fragment overlapping with conflicting data",
+    "msg.fragment.overlap.conflicts",
+    FT_BOOLEAN, 0, NULL, 0x00, NULL, HFILL } },
+{&hf_msg_fragment_multiple_tails,
+    {"Message has multiple tail fragments",
+    "msg.fragment.multiple_tails",
+    FT_BOOLEAN, 0, NULL, 0x00, NULL, HFILL } },
+{&hf_msg_fragment_too_long_fragment,
+    {"Message fragment too long", "msg.fragment.too_long_fragment",
+    FT_BOOLEAN, 0, NULL, 0x00, NULL, HFILL } },
+{&hf_msg_fragment_error,
+    {"Message defragmentation error", "msg.fragment.error",
+    FT_FRAMENUM, BASE_NONE, NULL, 0x00, NULL, HFILL } },
+{&hf_msg_fragment_count,
+    {"Message fragment count", "msg.fragment.count",
+    FT_UINT32, BASE_DEC, NULL, 0x00, NULL, HFILL } },
+{&hf_msg_reassembled_in,
+    {"Reassembled in", "msg.reassembled.in",
+    FT_FRAMENUM, BASE_NONE, NULL, 0x00, NULL, HFILL } },
+{&hf_msg_reassembled_length,
+    {"Reassembled length", "msg.reassembled.length",
+    FT_UINT32, BASE_DEC, NULL, 0x00, NULL, HFILL } },
+...
+static gint *ett[] =
+{
+...
+&ett_msg_fragment,
+&ett_msg_fragments
+...
+----
+====
+
+These hf variables are used internally within the reassembly routines to make
+useful links, and to add data to the dissection. It produces links from one
+packet to another, such as a partial packet having a link to the fully
+reassembled packet. Likewise there are back pointers to the individual packets
+from the reassembled one. The other variables are used for flagging up errors.
+
+[[TcpDissectPdus]]
+
+==== How to reassemble split TCP Packets
+
+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.
+
+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.
+
+You also cannot assume that 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 arbitrary position.
+
+This sounds complicated, but there is a simple solution.
++tcp_dissect_pdus()+ does all this tcp packet reassembling for you.
+This function is implemented in 'epan/dissectors/packet-tcp.h'.
+
+.Reassembling TCP fragments
+====
+----
+#include "config.h"
+
+#include <epan/packet.h>
+#include <epan/prefs.h>
+#include "packet-tcp.h"
+
+...
+
+#define FRAME_HEADER_LEN 8
+
+/* This method dissects fully reassembled messages */
+static int dissect_foo_message(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void* data _U_)
+{
+    /* TODO: implement your dissecting code */
+    return tvb_length(tvb);
+}
+
+/* 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 */
+}
+
+/* The main dissecting routine */
+static int dissect_foo(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void* data)
+{
+    tcp_dissect_pdus(tvb, pinfo, tree, TRUE, FRAME_HEADER_LEN,
+                     get_foo_message_len, dissect_foo_message, data);
+    return tvb_length(tvb);
+}
+
+...
+----
+====
+
+As you can see this is really simple. Just call +tcp_dissect_pdus()+ in your
+main dissection routine and move you message parsing code into another function.
+This function gets called whenever a message has been reassembled.
+
+The parameters tvb, pinfo, treeand dataare just handed over to
++tcp_dissect_pdus()+. The 4th parameter is a flag to indicate if the data should
+be reassembled 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. Parameter 8 is a the data
+passed in from parent dissector.
+
+[[ChDissectTap]]
+
+=== How to tap protocols
+
+Adding a Tap interface to a protocol allows it to do some useful things.
+In particular you can produce protocol statistics from the tap interface.
+
+A tap is basically a way of allowing other items to see whats happening as
+a protocol is dissected. A tap is registered with the main program, and
+then called on each dissection. Some arbitrary protocol specific data
+is provided with the routine that can be used.
+
+To create a tap, you first need to register a tap. A tap is registered with an
+integer handle, and registered with the routine +register_tap()+. This takes a
+string name with which to find it again.
+
+.Initialising a tap
+====
+----
+#include <epan/packet.h>
+#include <epan/tap.h>
+
+static int foo_tap = -1;
+
+struct FooTap {
+    gint packet_type;
+    gint priority;
+       ...
+};
+
+void proto_register_foo(void)
+{
+       ...
+    foo_tap = register_tap("foo");
+----
+====
+
+Whilst you can program a tap without protocol specific data, it is generally not
+very useful. Therefore it's a good idea to declare a structure that can be
+passed through the tap. This needs to be a static structure as it will be used
+after the dissection routine has returned. It's generally best to pick out some
+generic parts of the protocol you are dissecting into the tap data. A packet
+type, a priority or a status code maybe. The structure really needs to be
+included in a header file so that it can be included by other components that
+want to listen in to the tap.
+
+Once you have these defined, it's simply a case of populating the protocol
+specific structure and then calling +tap_queue_packet+, probably as the last part
+of the dissector.
+
+.Calling a protocol tap
+====
+----
+void dissect_foo(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
+{
+       ...
+    fooinfo = ep_alloc(sizeof(struct FooTap));
+    fooinfo->packet_type = tvb_get_guint8(tvb, 0);
+    fooinfo->priority = tvb_get_ntohs(tvb, 8);
+       ...
+    tap_queue_packet(foo_tap, pinfo, fooinfo);
+}
+----
+====
+
+This now enables those interested parties to listen in on the details
+of this protocol conversation.
+
+[[ChDissectStats]]
+
+=== How to produce protocol stats
+
+Given that you have a tap interface for the protocol, you can use this
+to produce some interesting statistics (well presumably interesting!) from
+protocol traces.
+
+This can be done in a separate plugin, or in the same plugin that is
+doing the dissection. The latter scheme is better, as the tap and stats
+module typically rely on sharing protocol specific data, which might get out
+of step between two different plugins.
+
+Here is a mechanism to produce statistics from the above TAP interface.
+
+.Initialising a stats interface
+====
+----
+/* register all http trees */
+static void register_foo_stat_trees(void) {
+    stats_tree_register("foo", "foo", "Foo/Packet Types",
+        foo_stats_tree_packet, foo_stats_tree_init, NULL);
+}
+
+WS_DLL_PUBLIC_DEF const gchar version[] = "0.0";
+
+WS_DLL_PUBLIC_DEF void plugin_register_tap_listener(void)
+{
+    register_foo_stat_trees();
+}
+
+#endif   
+----
+====
+
+Working from the bottom up, first the plugin interface entry point is defined,
++plugin_register_tap_listener()+. This simply calls the initialisation function
++register_foo_stat_trees()+.
+
+This in turn calls the +stats_tree_register()+ function, which takes three
+strings, and three functions.
+
+. This is the tap name that is registered.
+
+. An abbreviation of the stats name.
+
+. The name of the stats module. A $$'/'$$ character can be used to make sub menus.
+
+. The function that will called to generate the stats.
+
+. A function that can be called to initialise the stats data.
+
+. A function that will be called to clean up the stats data.
+
+In this case we only need the first two functions, as there is nothing specific to clean up.
+
+.Initialising a stats session
+====
+----
+static const guint8* st_str_packets = "Total Packets";
+static const guint8* st_str_packet_types = "FOO Packet Types";
+static int st_node_packets = -1;
+static int st_node_packet_types = -1;
+
+static void foo_stats_tree_init(stats_tree* st)
+{
+    st_node_packets = stats_tree_create_node(st, st_str_packets, 0, TRUE);
+    st_node_packet_types = stats_tree_create_pivot(st, st_str_packet_types, st_node_packets);
+}   
+----
+====
+
+In this case we create a new tree node, to handle the total packets,
+and as a child of that we create a pivot table to handle the stats about
+different packet types.
+
+
+.Generating the stats
+====
+----
+static int foo_stats_tree_packet(stats_tree* st, packet_info* pinfo, epan_dissect_t* edt, const void* p)
+{
+    struct FooTap *pi = (struct FooTap *)p;
+    tick_stat_node(st, st_str_packets, 0, FALSE);
+    stats_tree_tick_pivot(st, st_node_packet_types,
+            val_to_str(pi->packet_type, msgtypevalues, "Unknown packet type (%d)"));
+    return 1;
+}   
+----
+====
+
+In this case the processing of the stats is quite simple. First we call the
++tick_stat_node+ for the +st_str_packets+ packet node, to count packets. Then a
+call to +stats_tree_tick_pivot()+ on the +st_node_packet_types+ subtree allows
+us to record statistics by packet type.
+
+[[ChDissectConversation]]
+
+=== How to use conversations
+
+Some info about how to use conversations in a dissector can be found in the file
+'doc/README.developer', chapter 2.2.
+
+++++++++++++++++++++++++++++++++++++++
+<!-- End of WSDG Chapter Dissection -->
+++++++++++++++++++++++++++++++++++++++
+    
diff --git a/docbook/wsdg_src/WSDG_chapter_dissection.xml b/docbook/wsdg_src/WSDG_chapter_dissection.xml
deleted file mode 100644 (file)
index 58ee50c..0000000
+++ /dev/null
@@ -1,1209 +0,0 @@
-<!-- WSDG Chapter Dissection -->
-<!-- $Id$ -->
-
-<chapter id="ChapterDissection">
-  <title>Packet dissection</title>
-  <!-- Julian Onions additions -->
-  <section id="ChDissectWorks">
-       <title>How it works</title>
-       <para>
-       Each dissector decodes its part of the protocol, and then hands off
-       decoding to subsequent dissectors for an encapsulated protocol.
-       </para>
-       <para>
-       So it might all start with a Frame dissector which dissects the packet details
-       of the capture file itself (e.g. timestamps), passes the data on to an
-       Ethernet frame dissector that decodes the Ethernet header,
-       and then passes the payload to the next dissector (e.g. IP) and so on.
-       At each stage, details of the packet will be decoded and displayed.
-       </para>
-       <para>
-       Dissection can be implemented in two possible ways. One is to have a dissector
-       module compiled into the main program, which means it's always available.
-       Another way is to make a plugin (a shared library/DLL) that registers itself
-       to handle dissection.
-       </para>
-       <para>
-       There is little difference in having your dissector as either a plugin
-       or built-in. On the Windows platform you have limited function access
-       through what's listed in <filename>libwireshark.def</filename>,
-       but that is mostly complete.
-       </para>
-       <para>
-       The big plus is that your rebuild cycle for a plugin is much shorter
-       than for a built-in one. So starting with a plugin makes initial development
-       simpler, while deployment of the finished code may well be done as built-in
-       dissector.
-       </para>
-       <note><title>See also README.developer</title>
-       <para>
-       The file <filename>doc/README.developer</filename> contains much detailed information about
-       implementing a dissector (and may, in some cases, be more up-to-date than this document).
-       </para>
-       </note>
-  </section>
-
-  <section id="ChDissectAdd">
-       <title>Adding a basic dissector</title>
-       <para>
-       Let's step through adding a basic dissector. We'll start with the made up
-       "foo" protocol. It consists of the following basic items.
-       </para>
-       <itemizedlist>
-       <listitem><para>
-       A packet type - 8 bits, possible values: 1 - initialisation, 2 - terminate, 3 - data.
-       </para></listitem>
-       <listitem><para>
-       A set of flags stored in 8 bits, 0x01 - start packet, 0x02 - end packet, 0x04 - priority packet.
-       </para></listitem>
-       <listitem><para>
-       A sequence number - 16 bits.
-       </para></listitem>
-       <listitem><para>
-       An IP address.
-       </para></listitem>
-       </itemizedlist>
-       <section id="ChDissectSetup">
-       <title>Setting up the dissector</title>
-          <para>
-               The first decision you need to make is if this dissector will be a
-               built-in dissector, included in the main program, or a plugin.
-          </para>
-          <para>
-               Plugins are the easiest to write initially, so let's start with that.
-               With a little care, the plugin can be made to run as a built-in
-               easily too - so we haven't lost anything.
-          </para>
-          <example><title>Dissector Initialisation.</title>
-   <programlisting>
-<![CDATA[#include "config.h"
-
-#include <epan/packet.h>
-
-#define FOO_PORT 1234
-
-static int proto_foo = -1;
-
-
-void
-proto_register_foo(void)
-{
-    proto_foo = proto_register_protocol (
-        "FOO Protocol", /* name       */
-        "FOO",      /* short name */
-        "foo"       /* abbrev     */
-        );
-}]]>
-   </programlisting></example>
-       <para>
-       Let's go through this a bit at a time. First we have some boilerplate
-       include files. These will be pretty constant to start with.
-       </para>
-       <para>
-       Next we have an int that is initialised to -1 that records our protocol.
-       This will get updated when we register this dissector with the main program.
-       It's good practice to make all variables and functions that aren't exported
-       static to keep name space pollution down. Normally this isn't a problem unless your
-       dissector gets so big it has to span multiple files.
-       </para>
-       <para>
-       Then a #define for the UDP port that we'll assume we are dissecting traffic for.
-       </para>
-       <para>
-       Now that we have the basics in place to interact with the main program, we'll
-       start with two protocol dissector setup functions.
-
-       </para>
-       <para>
-       First we'll call the <function>proto_register_protocol()</function> function
-       which registers the protocol.
-       We can give it three names that will be used for display in various places.
-       The full and short name are used in e.g. the "Preferences" and "Enabled protocols"
-       dialogs as well as the generated field name list in the documentation.
-       The abbreviation is used as the display filter name.
-       </para>
-       <para>
-       Next we need a handoff routine.
-       </para>
-          <example><title>Dissector Handoff.</title>
-   <programlisting>
-<![CDATA[void
-proto_reg_handoff_foo(void)
-{
-    static dissector_handle_t foo_handle;
-
-    foo_handle = create_dissector_handle(dissect_foo, proto_foo);
-    dissector_add_uint("udp.port", FOO_PORT, foo_handle);
-}]]>
-   </programlisting></example>
-       <para>
-       What's happening here? We are initialising the dissector.
-       First we create a dissector handle; It is associated with the foo protocol and
-       with a routine to be called to do the actual dissecting.
-       Then we associate the handle with a UDP port number
-       so that the main program will know to call us when it gets UDP traffic on that port.
-       </para>
-       <para>
-       The stardard Wireshark dissector convention is to put
-       <function>proto_register_foo()</function> and <function>proto_reg_handoff_foo()</function>
-       as the last two functions in the dissector source.
-       </para>
-       <para>
-       Now at last we get to write some dissecting code. For the moment we'll
-       leave it as a basic placeholder.
-       </para>
-          <example><title>Dissection.</title>
-   <programlisting>
-<![CDATA[static void
-dissect_foo(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
-{
-    col_set_str(pinfo->cinfo, COL_PROTOCOL, "FOO");
-    /* Clear out stuff in the info column */
-    col_clear(pinfo->cinfo,COL_INFO);
-}]]>
-   </programlisting></example>
-       <para>
-       This function is called to dissect the packets presented to it.
-       The packet data is held in a special buffer referenced here as tvb.
-       We shall become fairly familiar with this as we get deeper into the details
-       of the protocol.
-       The packet info structure contains general data about the protocol, and we
-       can update information here.
-       The tree parameter is where the detail dissection takes place.
-       </para>
-       <para>
-       For now we'll do the minimum we can get away with.
-       In the first line we set the text of this to our protocol, so everyone
-       can see it's being recognised.
-       The only other thing we do is to clear out any data in the INFO column
-       if it's being displayed.
-       </para>
-       <para>
-       At this point we should have a basic dissector ready to compile and install.
-       It doesn't do much at present, other than identify the protocol and label it.
-       </para>
-       <para>
-       In order to compile this dissector and create a plugin a couple of support files
-       are required, besides the dissector source in <filename>packet-foo.c</filename>:
-       <itemizedlist>
-       <listitem><para>
-       Makefile.am - This is the UNIX/Linux makefile template
-       </para></listitem>
-       <listitem><para>
-       Makefile.common - This contains the file names of this plugin
-       </para></listitem>
-       <listitem><para>
-       Makefile.nmake - This contains the Wireshark plugin makefile for Windows
-       </para></listitem>
-       <listitem><para>
-       moduleinfo.h - This contains plugin version info
-       </para></listitem>
-       <listitem><para>
-       moduleinfo.nmake - This contains DLL version info for Windows
-       </para></listitem>
-       <listitem><para>
-       packet-foo.c - This is your dissector source
-       </para></listitem>
-       <listitem><para>
-       plugin.rc.in - This contains the DLL resource template for Windows
-       </para></listitem>
-       </itemizedlist>
-       You can find a good example for these files in the interlink plugin directory.
-       <filename>Makefile.common</filename> and <filename>Makefile.am</filename> have to
-       be modified to reflect the relevant files and dissector name.
-       <filename>moduleinfo.h</filename> and <filename>moduleinfo.nmake</filename> have
-       to be filled in with the version information.
-       Compile the dissector to a DLL or shared library and copy it into the plugin
-       directory of the installation.
-       </para>
-   </section>
-
-       <section id="ChDissectDetails">
-       <title>Dissecting the details of the protocol</title>
-          <para>
-          Now that we have our basic dissector up and running, let's do something with it.
-          The simplest thing to do to start with is to just label the payload.
-          This will allow us to set up some of the parts we will need.
-          </para>
-          <para>
-          The first thing we will do is to build a subtree to decode our results into.
-          This helps to keep things looking nice in the detailed display.
-          Now the dissector is called in two different cases. In one case
-          it is called to get a summary of the packet, in the other case it is
-          called to look into details of the packet. These two cases can be
-          distinguished by the tree pointer. If the tree pointer is NULL, then
-          we are being asked for a summary. If it is non NULL, we can pick apart
-          the protocol for display. So with that in mind, let's enhance our dissector.
-          </para>
-          <example><title>Plugin Packet Dissection.</title>
-   <programlisting>
-<![CDATA[static void
-dissect_foo(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
-{
-
-    col_set_str(pinfo->cinfo, COL_PROTOCOL, "FOO");
-    /* Clear out stuff in the info column */
-    col_clear(pinfo->cinfo,COL_INFO);
-
-    if (tree) { /* we are being asked for details */
-        proto_item *ti = NULL;
-        ti = proto_tree_add_item(tree, proto_foo, tvb, 0, -1, ENC_NA);
-    }
-}]]>
-   </programlisting></example>
-       <para>
-       What we're doing here is adding a subtree to the dissection.
-       This subtree will hold all the details of this protocol and so not clutter
-       up the display when not required.
-       </para>
-       <para>
-       We are also marking the area of data that is being consumed by this
-       protocol. In our case it's all that has been passed to us, as we're assuming
-       this protocol does not encapsulate another.
-       Therefore, we add the new tree node with <function>proto_tree_add_item()</function>,
-       adding it to the passed in tree, label it with the protocol, use the passed in
-       tvb buffer as the data, and consume from 0 to the end (-1) of this data.
-       ENC_NA ("not applicable") is specified as the "encoding" parameter.
-
-       </para>
-       <para>
-       After this change, there should be a label in the detailed display for the protocol,
-       and selecting this will highlight the remaining contents of the packet.
-       </para>
-       <para>
-       Now let's go to the next step and add some protocol dissection.
-       For this step we'll need to construct a couple of tables that help with dissection.
-       This needs some additions to the <function>proto_register_foo()</function>
-       function shown previously.
-       </para>
-       <para>
-       Two statically allocated arrays are added at the beginning of
-       <function>proto_register_foo()</function>. The arrays are then registered after
-       the call to <function>proto_register_protocol()</function>.
-       </para>
-          <example><title>Registering data structures.</title>
-   <programlisting>
-<![CDATA[void
-proto_register_foo(void)
-{
-    static hf_register_info hf[] = {
-        { &hf_foo_pdu_type,
-            { "FOO PDU Type", "foo.type",
-            FT_UINT8, BASE_DEC,
-            NULL, 0x0,
-            NULL, HFILL }
-        }
-    };
-
-    /* Setup protocol subtree array */
-    static gint *ett[] = {
-        &ett_foo
-    };
-
-    proto_foo = proto_register_protocol (
-        "FOO Protocol", /* name       */
-        "FOO",      /* short name */
-        "foo"       /* abbrev     */
-        );
-
-    proto_register_field_array(proto_foo, hf, array_length(hf));
-    proto_register_subtree_array(ett, array_length(ett));
-}]]>
-   </programlisting></example>
-       <para>
-       The variables <varname>hf_foo_pdu_type</varname> and <varname>ett_foo</varname>
-       also need to be declared somewhere near the top of the file.
-       </para>
-          <example><title>Dissector data structure globals.</title>
-   <programlisting>
-<![CDATA[static int hf_foo_pdu_type = -1;
-
-static gint ett_foo = -1;]]>
-   </programlisting></example>
-       <para>
-       Now we can enhance the protocol display with some detail.
-       </para>
-          <example><title>Dissector starting to dissect the packets.</title>
-   <programlisting>
-<![CDATA[   if (tree) { /* we are being asked for details */
-        proto_item *ti = NULL;
-        proto_tree *foo_tree = NULL;
-
-        ti = proto_tree_add_item(tree, proto_foo, tvb, 0, -1, ENC_NA);
-        foo_tree = proto_item_add_subtree(ti, ett_foo);
-        proto_tree_add_item(foo_tree, hf_foo_pdu_type, tvb, 0, 1, ENC_BIG_ENDIAN);
-    }]]>
-   </programlisting></example>
-       <para>
-       Now the dissection is starting to look more interesting. We have picked apart
-       our first bit of the protocol. One byte of data at the start of the packet
-       that defines the packet type for foo protocol.
-       </para>
-       <para>
-       The <function>proto_item_add_subtree()</function> call has added a child node
-       to the protocol tree which is where we will do our detail dissection.
-       The expansion of this node is controlled by the <varname>ett_foo</varname>
-       variable. This remembers if the node should be expanded or not as you move
-       between packets. All subsequent dissection will be added to this tree,
-       as you can see from the next call.
-       A call to <function>proto_tree_add_item()</function> in the <varname>foo_tree</varname>,
-       this time using the <varname>hf_foo_pdu_type</varname> to control the formatting
-       of the item. The pdu type is one byte of data, starting at 0. We assume it is
-       in network order (also called big endian), so that is why we use ENC_BIG_ENDIAN.
-       For a 1-byte quantity, there is no order issue, but it is good practice to
-       make this the same as any multibyte fields that may be present, and as we will
-       see in the next section, this particular protocol uses network order.
-       </para>
-       <para>
-       If we look in detail at the <varname>hf_foo_pdu_type</varname> declaration in
-       the static array we can see the details of the definition.
-       </para>
-       <itemizedlist>
-       <listitem><para>
-       hf_foo_pdu_type - the index for this node.
-       </para></listitem>
-       <listitem><para>
-       FOO PDU Type - the label for this item.
-       </para></listitem>
-       <listitem><para>
-       foo.type - this is the filter string. It enables us to type constructs such
-       as foo.type=1 into the filter box.
-       </para></listitem>
-       <listitem><para>
-       FT_UINT8 - this specifies this item is an 8bit unsigned integer.
-       This tallies with our call above where we tell it to only look at one byte.
-       </para></listitem>
-       <listitem><para>
-       BASE_DEC - for an integer type, this tells it to be printed as a decimal
-       number. It could be hexdecimal (BASE_HEX) or octal (BASE_OCT) if that made more sense.
-       </para></listitem>
-       </itemizedlist>
-       <para>
-       We'll ignore the rest of the structure for now.
-       </para>
-       <para>
-       If you install this plugin and try it out, you'll see something that begins to look
-       useful.
-       </para>
-       <para>
-       Now let's finish off dissecting the simple protocol. We need to add a few
-       more variables to the <varname>hf</varname> array, and a couple more procedure calls.
-       </para>
-          <example><title>Wrapping up the packet dissection.</title>
-   <programlisting>
-<![CDATA[...
-static int hf_foo_flags = -1;
-static int hf_foo_sequenceno = -1;
-static int hf_foo_initialip = -1;
-...
-
-static void
-dissect_foo(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
-{
-    gint offset = 0;
-
-    ...
-
-    if (tree) { /* we are being asked for details */
-        proto_item *ti = NULL;
-        proto_tree *foo_tree = NULL;
-
-        ti = proto_tree_add_item(tree, proto_foo, tvb, 0, -1, ENC_NA);
-        foo_tree = proto_item_add_subtree(ti, ett_foo);
-        proto_tree_add_item(foo_tree, hf_foo_pdu_type, tvb, offset, 1, ENC_BIG_ENDIAN);
-        offset += 1;
-        proto_tree_add_item(foo_tree, hf_foo_flags, tvb, offset, 1, ENC_BIG_ENDIAN);
-        offset += 1;
-        proto_tree_add_item(foo_tree, hf_foo_sequenceno, tvb, offset, 2, ENC_BIG_ENDIAN);
-        offset += 2;
-        proto_tree_add_item(foo_tree, hf_foo_initialip, tvb, offset, 4, ENC_BIG_ENDIAN);
-        offset += 4;
-    }
-    ...
-}
-
-void
-proto_register_foo(void) {
-    ...
-        ...
-        { &hf_foo_flags,
-            { "FOO PDU Flags", "foo.flags",
-            FT_UINT8, BASE_HEX,
-            NULL, 0x0,
-            NULL, HFILL }
-        },
-        { &hf_foo_sequenceno,
-            { "FOO PDU Sequence Number", "foo.seqn",
-            FT_UINT16, BASE_DEC,
-            NULL, 0x0,
-            NULL, HFILL }
-        },
-        { &hf_foo_initialip,
-            { "FOO PDU Initial IP", "foo.initialip",
-            FT_IPv4, BASE_NONE,
-            NULL, 0x0,
-            NULL, HFILL }
-        },
-        ...
-    ...
-}
-...]]>
-   </programlisting></example>
-   <para>
-   This dissects all the bits of this simple hypothetical protocol. We've introduced a new
-   variable <varname>offset</varname> into the mix to help keep track of where we are in
-   the packet dissection. With these extra bits in place, the whole protocol is now dissected.
-   </para>
-   </section>
-   <section><title>Improving the dissection information</title>
-   <para>
-   We can certainly improve the display of the protocol with a bit of extra data.
-   The first step is to add some text labels. Let's start by labeling the packet types.
-   There is some useful support for this sort of thing by adding a couple of extra things.
-   First we add a simple table of type to name.
-   </para>
-   <example><title>Naming the packet types.</title>
-   <programlisting>
-<![CDATA[static const value_string packettypenames[] = {
-    { 1, "Initialise" },
-    { 2, "Terminate" },
-    { 3, "Data" },
-    { 0, NULL }
-};]]>
-   </programlisting></example>
-   <para>
-   This is a handy data structure that can be used to look up a name for a value.
-   There are routines to directly access this lookup table, but we don't need to
-   do that, as the support code already has that added in. We just have to give
-   these details to the appropriate part of the data, using the VALS macro.
-   </para>
-   <example><title>Adding Names to the protocol.</title>
-   <programlisting>
-<![CDATA[   { &hf_foo_pdu_type,
-        { "FOO PDU Type", "foo.type",
-        FT_UINT8, BASE_DEC,
-        VALS(packettypenames), 0x0,
-        NULL, HFILL }
-    }]]>
-   </programlisting></example>
-    <para>
-    This helps in deciphering the packets, and we can do a similar thing for the
-    flags structure. For this we need to add some more data to the table though.
-    </para>
-   <example><title>Adding Flags to the protocol.</title>
-   <programlisting>
-<![CDATA[#define FOO_START_FLAG 0x01
-#define FOO_END_FLAG        0x02
-#define FOO_PRIORITY_FLAG   0x04
-
-static int hf_foo_startflag = -1;
-static int hf_foo_endflag = -1;
-static int hf_foo_priorityflag = -1;
-
-static void
-dissect_foo(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
-{
-    ...
-        ...
-        proto_tree_add_item(foo_tree, hf_foo_flags, tvb, offset, 1, ENC_BIG_ENDIAN);
-        proto_tree_add_item(foo_tree, hf_foo_startflag, tvb, offset, 1, ENC_BIG_ENDIAN);
-        proto_tree_add_item(foo_tree, hf_foo_endflag, tvb, offset, 1, ENC_BIG_ENDIAN);
-        proto_tree_add_item(foo_tree, hf_foo_priorityflag, tvb, offset, 1, ENC_BIG_ENDIAN);
-        offset += 1;
-        ...
-    ...
-}
-
-void
-proto_register_foo(void) {
-    ...
-        ...
-        { &hf_foo_startflag,
-            { "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,
-            NULL, HFILL }
-        },
-        { &hf_foo_priorityflag,
-            { "FOO PDU Priority Flags", "foo.flags.priority",
-            FT_BOOLEAN, 8,
-            NULL, FOO_PRIORITY_FLAG,
-            NULL, HFILL }
-        },
-        ...
-    ...
-}
-...]]>
-   </programlisting></example>
-   <para>
-   Some things to note here. For the flags, as each bit is a different flag, we use
-   the type FT_BOOLEAN, as the flag is either on or off. Second, we include the flag
-   mask in the 7th field of the data, which allows the system to mask the relevant bit.
-   We've also changed the 5th field to 8, to indicate that we are looking at an 8 bit
-   quantity when the flags are extracted. Then finally we add the extra constructs
-   to the dissection routine. Note we keep the same offset for each of the flags.
-   </para>
-   <para>
-   This is starting to look fairly full featured now, but there are a couple of other
-   things we can do to make things look even more pretty. At the moment our dissection
-   shows the packets as "Foo Protocol" which whilst correct is a little uninformative.
-   We can enhance this by adding a little more detail.
-   First, let's get hold of the actual value of the protocol type. We can use the handy
-   function <function>tvb_get_guint8()</function> to do this.
-   With this value in hand, there are a couple of things we can do.
-   First we can set the INFO column of the non-detailed view to show what sort of
-   PDU it is - which is extremely helpful when looking at protocol traces.
-   Second, we can also display this information in the dissection window.
-   </para>
-   <example><title>Enhancing the display.</title>
-   <programlisting>
-<![CDATA[static void
-dissect_foo(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
-{
-    guint8 packet_type = tvb_get_guint8(tvb, 0);
-
-    col_set_str(pinfo->cinfo, COL_PROTOCOL, "FOO");
-    /* Clear out stuff in the info column */
-    col_clear(pinfo->cinfo,COL_INFO);
-    col_add_fstr(pinfo->cinfo, COL_INFO, "Type %s",
-             val_to_str(packet_type, packettypenames, "Unknown (0x%02x)"));
-
-    if (tree) { /* we are being asked for details */
-        proto_item *ti = NULL;
-        proto_tree *foo_tree = NULL;
-        gint offset = 0;
-
-        ti = proto_tree_add_item(tree, proto_foo, tvb, 0, -1, ENC_NA);
-        proto_item_append_text(ti, ", Type %s",
-            val_to_str(packet_type, packettypenames, "Unknown (0x%02x)"));
-        foo_tree = proto_item_add_subtree(ti, ett_foo);
-        proto_tree_add_item(foo_tree, hf_foo_pdu_type, tvb, offset, 1, ENC_BIG_ENDIAN);
-        offset += 1;
-    }
-}]]>
-   </programlisting></example>
-   <para>
-   So here, after grabbing the value of the first 8 bits, we use it with one of the
-   built-in utility routines <function>val_to_str()</function>, to lookup the value.
-   If the value isn't found we provide a fallback which just prints the value in hex.
-   We use this twice, once in the INFO field of the columns - if it's displayed, and
-   similarly we append this data to the base of our dissecting tree.
-   </para>
-
-   </section>
-  </section>
-
-  <section id="ChDissectTransformed">
-       <title>How to handle transformed data</title>
-       <para>
-       Some protocols do clever things with data. They might possibly
-       encrypt the data, or compress data, or part of it. If you know
-       how these steps are taken it is possible to reverse them within the
-       dissector.
-       </para>
-       <para>
-       As encryption can be tricky, let's consider the case of compression.
-       These techniques can also work for other transformations of data,
-       where some step is required before the data can be examined.
-       </para>
-       <para>
-       What basically needs to happen here, is to identify the data that
-       needs conversion, take that data and transform it into a new stream,
-       and then call a dissector on it.
-       Often this needs to be done "on-the-fly" based on clues in the packet.
-       Sometimes this needs to be used in conjunction with other techniques,
-       such as packet reassembly. The following shows a technique to
-       achieve this effect.
-       </para>
-          <example><title>Decompressing data packets for dissection.</title>
-   <programlisting>
-   <![CDATA[
-    guint8 flags = tvb_get_guint8(tvb, offset);
-    offset ++;
-    if (flags & FLAG_COMPRESSED) { /* the remainder of the packet is compressed */
-        guint16 orig_size = tvb_get_ntohs(tvb, offset);
-        guchar *decompressed_buffer = (guchar*)g_malloc(orig_size);
-        offset += 2;
-        decompress_packet(tvb_get_ptr(tvb, offset, -1),
-                tvb_length_remaining(tvb, offset),
-                decompressed_buffer, orig_size);
-        /* Now re-setup the tvb buffer to have the new data */
-        next_tvb = tvb_new_child_real_data(tvb, decompressed_buffer, orig_size, orig_size);
-        tvb_set_free_cb(next_tvb, g_free);
-        add_new_data_source(pinfo, next_tvb, "Decompressed Data");
-    } else {
-        next_tvb = tvb_new_subset_remaining(tvb, offset);
-    }
-    offset = 0;
-    /* process next_tvb from here on */
-]]>
-   </programlisting></example>
-       <para>
-       The first steps here are to recognise the compression. In this case
-       a flag byte alerts us to the fact the remainder of the packet is compressed.
-       Next we retrieve the original size of the packet, which in this case
-       is conveniently within the protocol. If it's not, it may be part of the
-       compression routine to work it out for you, in which case the logic would
-       be different.
-       </para>
-       <para>
-       So armed with the size, a buffer is allocated to receive the uncompressed
-       data using g_malloc, and the packet is decompressed into it.
-       The <function>tvb_get_ptr()</function> function is useful to get a pointer
-       to the raw data of the packet from the offset onwards. In this case the
-       decompression routine also needs to know the length, which is
-       given by the <function>tvb_length_remaining()</function> function.
-       </para>
-       <para>
-       Next we build a new tvb buffer from this data, using the
-       <function>tvb_new_child_real_data()</function> call.
-       This data is a child of our original data, so calling this function also acknowledges that.
-       One procedural step is to add a callback handler to free the data when it's no longer needed
-       via a call to <function>tvb_set_free_cb()</function>.
-       In this case <function>g_malloc()</function> was used to allocate the
-       memory, so <function>g_free()</function> is the appropriate callback function.
-       Finally we add this tvb as a new data source, so that the detailed display can show
-       the decompressed bytes as well as the original.
-       </para>
-       <para>
-       After this has been set up the remainder of the dissector can dissect the
-       buffer <varname>next_tvb</varname>, as it's a new buffer the offset needs to be 0 as we start
-       again from the beginning of this buffer. To make the rest of the dissector
-       work regardless of whether compression was involved or not, in the case that
-       compression was not signaled, we use <function>tvb_new_subset_remaining()</function>
-       to deliver us a new buffer based on the old one but starting at the current offset, and
-       extending to the end. This makes dissecting the packet from this point on
-       exactly the same regardless of compression.
-       </para>
-  </section>
-  <section id="ChDissectReassemble">
-       <title>How to reassemble split packets</title>
-       <para>
-       Some protocols have times when they have to split a large packet across
-       multiple other packets. In this case the dissection can't be carried out correctly
-       until you have all the data. The first packet doesn't have enough data,
-       and the subsequent packets don't have the expect format.
-       To dissect these packets you need to wait until all the parts have
-       arrived and then start the dissection.
-       </para>
-         <section id="ChDissectReassembleUdp">
-               <title>How to reassemble split UDP packets</title>
-               <para>
-               As an example, let's examine a protocol that is layered on
-               top of UDP that splits up its own data stream.
-               If a packet is bigger than some given size, it will be split into
-               chunks, and somehow signaled within its protocol.
-               </para>
-               <para>
-               To deal with such streams, we need several things to trigger
-               from. We need to know that this packet is part of a multi-packet
-               sequence. We need to know how many packets are in the sequence.
-               We also need to know when we have all the packets.
-               </para>
-               <para>
-               For this example we'll assume there is a simple in-protocol
-               signaling mechanism to give details. A flag byte that signals
-               the presence of a multi-packet sequence and also the last packet,
-               followed by an ID of the sequence and a packet sequence number.
-               </para>
-                <programlisting>
-<![CDATA[msg_pkt ::= SEQUENCE {
-    .....
-    flags ::= SEQUENCE {
-        fragment    BOOLEAN,
-        last_fragment   BOOLEAN,
-    .....
-    }
-    msg_id  INTEGER(0..65535),
-    frag_id INTEGER(0..65535),
-    .....
-}]]>
-                </programlisting>
-          <example><title>Reassembling fragments - Part 1</title>
-   <programlisting>
-<![CDATA[#include <epan/reassemble.h>
-   ...
-save_fragmented = pinfo->fragmented;
-flags = tvb_get_guint8(tvb, offset); offset++;
-if (flags & FL_FRAGMENT) { /* fragmented */
-    tvbuff_t* new_tvb = NULL;
-    fragment_data *frag_msg = NULL;
-    guint16 msg_seqid = tvb_get_ntohs(tvb, offset); offset += 2;
-    guint16 msg_num = tvb_get_ntohs(tvb, offset); offset += 2;
-
-    pinfo->fragmented = TRUE;
-    frag_msg = fragment_add_seq_check(tvb, offset, pinfo,
-        msg_seqid, /* ID for fragments belonging together */
-        msg_fragment_table, /* list of message fragments */
-        msg_reassembled_table, /* list of reassembled messages */
-        msg_num, /* fragment sequence number */
-        tvb_length_remaining(tvb, offset), /* fragment length - to the end */
-        flags & FL_FRAG_LAST); /* More fragments? */]]>
-   </programlisting></example>
-       <para>
-       We start by saving the fragmented state of this packet, so we can restore it later.
-       Next comes some protocol specific stuff, to dig the fragment data
-       out of the stream if it's present. Having decided it is present, we
-       let the function <function>fragment_add_seq_check()</function> do its work.
-       We need to provide this with a certain amount of data.
-       </para>
-       <itemizedlist>
-       <listitem><para>
-       The tvb buffer we are dissecting.
-       </para></listitem>
-       <listitem><para>
-       The offset where the partial packet starts.
-       </para></listitem>
-       <listitem><para>
-       The provided packet info.
-       </para></listitem>
-       <listitem><para>
-       The sequence number of the fragment stream. There may be several
-       streams of fragments in flight, and this is used to key the
-       relevant one to be used for reassembly.
-       </para></listitem>
-       <listitem><para>
-       The msg_fragment_table and the msg_reassembled_table are variables
-       we need to declare. We'll consider these in detail later.
-       </para></listitem>
-       <listitem><para>
-       msg_num is the packet number within the sequence.
-       </para></listitem>
-       <listitem><para>
-       The length here is specified as the rest of the tvb as we want the rest of the packet data.
-       </para></listitem>
-       <listitem><para>
-       Finally a parameter that signals if this is the last fragment or not.
-       This might be a flag as in this case, or there may be a counter in the
-       protocol.
-       </para></listitem>
-       </itemizedlist>
-          <example><title>Reassembling fragments part 2</title>
-          <programlisting>
-       <![CDATA[
-    new_tvb = process_reassembled_data(tvb, offset, pinfo,
-        "Reassembled Message", frag_msg, &msg_frag_items,
-        NULL, msg_tree);
-
-    if (frag_msg) { /* Reassembled */
-        col_append_str(pinfo->cinfo, COL_INFO,
-                " (Message Reassembled)");
-    } else { /* Not last packet of reassembled Short Message */
-        col_append_fstr(pinfo->cinfo, COL_INFO,
-                " (Message fragment %u)", msg_num);
-    }
-
-    if (new_tvb) { /* take it all */
-        next_tvb = new_tvb;
-    } else { /* make a new subset */
-        next_tvb = tvb_new_subset(tvb, offset, -1, -1);
-    }
-}
-else { /* Not fragmented */
-    next_tvb = tvb_new_subset(tvb, offset, -1, -1);
-}
-
-.....
-pinfo->fragmented = save_fragmented;
-]]>
-   </programlisting></example>
-          <para>
-          Having passed the fragment data to the reassembly handler, we can
-          now check if we have the whole message. If there is enough information,
-          this routine will return the newly reassembled data buffer.
-          </para>
-          <para>
-          After that, we add a couple of informative messages to the display
-          to show that this is part of a sequence. Then a bit of manipulation
-          of the buffers and the dissection can proceed.
-          Normally you will probably not bother dissecting further unless the
-          fragments have been reassembled as there won't be much to find. Sometimes
-          the first packet in the sequence can be partially decoded though if you wish.
-          </para>
-          <para>
-          Now the mysterious data we passed into the <function>fragment_add_seq_check()</function>.
-          </para>
-          <example><title>Reassembling fragments - Initialisation</title>
-          <programlisting>
-<![CDATA[static GHashTable *msg_fragment_table = NULL;
-static GHashTable *msg_reassembled_table = NULL;
-
-static void
-msg_init_protocol(void)
-{
-    fragment_table_init(&msg_fragment_table);
-    reassembled_table_init(&msg_reassembled_table);
-}]]>
-   </programlisting></example>
-       <para>
-       First a couple of hash tables are declared, and these are initialised
-       in the protocol initialisation routine.
-       Following that, a fragment_items structure is allocated and filled
-       in with a series of ett items, hf data items, and a string tag.
-       The ett and hf values should be included in the relevant tables like
-       all the other variables your protocol may use. The hf variables
-       need to be placed in the structure something like the following.
-       Of course the names may need to be adjusted.
-       </para>
-          <example><title>Reassembling fragments - Data</title>
-          <programlisting>
-<![CDATA[...
-static int hf_msg_fragments = -1;
-static int hf_msg_fragment = -1;
-static int hf_msg_fragment_overlap = -1;
-static int hf_msg_fragment_overlap_conflicts = -1;
-static int hf_msg_fragment_multiple_tails = -1;
-static int hf_msg_fragment_too_long_fragment = -1;
-static int hf_msg_fragment_error = -1;
-static int hf_msg_fragment_count = -1;
-static int hf_msg_reassembled_in = -1;
-static int hf_msg_reassembled_length = -1;
-...
-static gint ett_msg_fragment = -1;
-static gint ett_msg_fragments = -1;
-...
-static const fragment_items msg_frag_items = {
-    /* Fragment subtrees */
-    &ett_msg_fragment,
-    &ett_msg_fragments,
-    /* Fragment fields */
-    &hf_msg_fragments,
-    &hf_msg_fragment,
-    &hf_msg_fragment_overlap,
-    &hf_msg_fragment_overlap_conflicts,
-    &hf_msg_fragment_multiple_tails,
-    &hf_msg_fragment_too_long_fragment,
-    &hf_msg_fragment_error,
-    &hf_msg_fragment_count,
-    /* Reassembled in field */
-    &hf_msg_reassembled_in,
-    /* Reassembled length field */
-    &hf_msg_reassembled_length,
-    /* Tag */
-    "Message fragments"
-};
-...
-static hf_register_info hf[] =
-{
-...
-{&hf_msg_fragments,
-    {"Message fragments", "msg.fragments",
-    FT_NONE, BASE_NONE, NULL, 0x00, NULL, HFILL } },
-{&hf_msg_fragment,
-    {"Message fragment", "msg.fragment",
-    FT_FRAMENUM, BASE_NONE, NULL, 0x00, NULL, HFILL } },
-{&hf_msg_fragment_overlap,
-    {"Message fragment overlap", "msg.fragment.overlap",
-    FT_BOOLEAN, 0, NULL, 0x00, NULL, HFILL } },
-{&hf_msg_fragment_overlap_conflicts,
-    {"Message fragment overlapping with conflicting data",
-    "msg.fragment.overlap.conflicts",
-    FT_BOOLEAN, 0, NULL, 0x00, NULL, HFILL } },
-{&hf_msg_fragment_multiple_tails,
-    {"Message has multiple tail fragments",
-    "msg.fragment.multiple_tails",
-    FT_BOOLEAN, 0, NULL, 0x00, NULL, HFILL } },
-{&hf_msg_fragment_too_long_fragment,
-    {"Message fragment too long", "msg.fragment.too_long_fragment",
-    FT_BOOLEAN, 0, NULL, 0x00, NULL, HFILL } },
-{&hf_msg_fragment_error,
-    {"Message defragmentation error", "msg.fragment.error",
-    FT_FRAMENUM, BASE_NONE, NULL, 0x00, NULL, HFILL } },
-{&hf_msg_fragment_count,
-    {"Message fragment count", "msg.fragment.count",
-    FT_UINT32, BASE_DEC, NULL, 0x00, NULL, HFILL } },
-{&hf_msg_reassembled_in,
-    {"Reassembled in", "msg.reassembled.in",
-    FT_FRAMENUM, BASE_NONE, NULL, 0x00, NULL, HFILL } },
-{&hf_msg_reassembled_length,
-    {"Reassembled length", "msg.reassembled.length",
-    FT_UINT32, BASE_DEC, NULL, 0x00, NULL, HFILL } },
-...
-static gint *ett[] =
-{
-...
-&ett_msg_fragment,
-&ett_msg_fragments
-...]]>
-   </programlisting></example>
-   <para>
-   These hf variables are used internally within the reassembly routines
-   to make useful links, and to add data to the dissection. It produces
-   links from one packet to another - such as a partial packet having
-   a link to the fully reassembled packet. Likewise there are back pointers
-   to the individual packets from the reassembled one.
-   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 that 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 arbitrary 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[#include "config.h"
-
-#include <epan/packet.h>
-#include <epan/prefs.h>
-#include "packet-tcp.h"
-
-...
-
-#define FRAME_HEADER_LEN 8
-
-/* This method dissects fully reassembled messages */
-static int dissect_foo_message(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void* data _U_)
-{
-    /* TODO: implement your dissecting code */
-    return tvb_length(tvb);
-}
-
-/* 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 */
-}
-
-/* The main dissecting routine */
-static int dissect_foo(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void* data)
-{
-    tcp_dissect_pdus(tvb, pinfo, tree, TRUE, FRAME_HEADER_LEN,
-                     get_foo_message_len, dissect_foo_message, data);
-    return tvb_length(tvb);
-}
-
-...]]>
-                       </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>, <parameter>tree</parameter>
-      and <parameter>data</parameter> are just handed over to <function>tcp_dissect_pdus()</function>.
-      The 4th parameter is a flag to indicate if the data should be reassembled 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.
-      Parameter 8 is a the data passed in from parent 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 the tap interface.
-       </para>
-       <para>
-       A tap is basically a way of allowing other items to see whats happening as
-       a protocol is dissected. A tap is registered with the main program, and
-       then called on each dissection. Some arbitrary protocol specific data
-       is provided with the routine that can be used.
-       </para>
-       <para>
-       To create a tap, you first need to register a tap.
-       A tap is registered with an integer handle, and registered
-       with the routine register_tap. This takes a string name
-       with which to find it again.
-       </para>
-          <example><title>Initialising a tap</title>
-          <programlisting>
-<![CDATA[#include <epan/packet.h>
-#include <epan/tap.h>
-
-static int foo_tap = -1;
-
-struct FooTap {
-    gint packet_type;
-    gint priority;
-       ...
-};
-
-void proto_register_foo(void)
-{
-       ...
-    foo_tap = register_tap("foo");]]>
-   </programlisting></example>
-       <para>
-       Whilst you can program a tap without protocol specific data, it
-       is generally not very useful. Therefore it's a good idea
-       to declare a structure that can be passed through the tap.
-       This needs to be a static structure as it will be used after the
-       dissection routine has returned. It's generally best to pick out some
-       generic parts of the protocol you are dissecting into the tap data.
-       A packet type, a priority or a status code maybe.
-       The structure really needs to be included in a header file so
-       that it can be included by other components that want to listen in
-       to the tap.
-       </para>
-       <para>
-       Once you have these defined, it's simply a case of populating the
-       protocol specific structure and then calling tap_queue_packet, probably
-       as the last part of the dissector.
-       </para>
-          <example><title>Calling a protocol tap</title>
-          <programlisting>
-<![CDATA[
-void dissect_foo(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
-{
-       ...
-    fooinfo = ep_alloc(sizeof(struct FooTap));
-    fooinfo->packet_type = tvb_get_guint8(tvb, 0);
-    fooinfo->priority = tvb_get_ntohs(tvb, 8);
-       ...
-    tap_queue_packet(foo_tap, pinfo, fooinfo);
-}
-]]>
-   </programlisting></example>
-       <para>
-       This now enables those interested parties to listen in on the details
-       of this protocol conversation.
-       </para>
-  </section>
-  <section id="ChDissectStats">
-       <title>How to produce protocol stats</title>
-       <para>
-       Given that you have a tap interface for the protocol, you can use this
-       to produce some interesting statistics (well presumably interesting!) from
-       protocol traces.
-       </para>
-       <para>
-       This can be done in a separate plugin, or in the same plugin that is
-       doing the dissection. The latter scheme is better, as the tap and stats
-       module typically rely on sharing protocol specific data, which might get out
-       of step between two different plugins.
-       </para>
-       <para>
-       Here is a mechanism to produce statistics from the above TAP interface.
-       </para>
-          <example><title>Initialising a stats interface</title>
-          <programlisting>
-<![CDATA[/* register all http trees */
-static void register_foo_stat_trees(void) {
-    stats_tree_register("foo", "foo", "Foo/Packet Types",
-        foo_stats_tree_packet, foo_stats_tree_init, NULL);
-}
-
-WS_DLL_PUBLIC_DEF const gchar version[] = "0.0";
-
-WS_DLL_PUBLIC_DEF void plugin_register_tap_listener(void)
-{
-    register_foo_stat_trees();
-}
-
-#endif]]>
-   </programlisting></example>
-       <para>
-       Working from the bottom up, first the plugin interface entry point is defined,
-       <function>plugin_register_tap_listener()</function>. This simply calls the
-       initialisation function <function>register_foo_stat_trees()</function>.
-       </para>
-       <para>
-       This in turn calls the <function>stats_tree_register()</function> function,
-       which takes three strings, and three functions.
-       </para>
-       <orderedlist>
-       <listitem><para>
-       This is the tap name that is registered.
-       </para></listitem>
-       <listitem><para>
-       An abbreviation of the stats name.
-       </para></listitem>
-       <listitem><para>
-       The name of the stats module. A '/' character can be used to make sub menus.
-       </para></listitem>
-       <listitem><para>
-       The function that will called to generate the stats.
-       </para></listitem>
-       <listitem><para>
-       A function that can be called to initialise the stats data.
-       </para></listitem>
-       <listitem><para>
-       A function that will be called to clean up the stats data.
-       </para></listitem>
-       </orderedlist>
-       <para>
-       In this case we only need the first two functions, as there is nothing specific to clean up.
-       </para>
-          <example><title>Initialising a stats session</title>
-          <programlisting>
-<![CDATA[static const guint8* st_str_packets = "Total Packets";
-static const guint8* st_str_packet_types = "FOO Packet Types";
-static int st_node_packets = -1;
-static int st_node_packet_types = -1;
-
-static void foo_stats_tree_init(stats_tree* st)
-{
-    st_node_packets = stats_tree_create_node(st, st_str_packets, 0, TRUE);
-    st_node_packet_types = stats_tree_create_pivot(st, st_str_packet_types, st_node_packets);
-}]]>
-   </programlisting></example>
-       <para>
-       In this case we create a new tree node, to handle the total packets,
-       and as a child of that we create a pivot table to handle the stats about
-       different packet types.
-       </para>
-          <example><title>Generating the stats</title>
-          <programlisting>
-<![CDATA[static int foo_stats_tree_packet(stats_tree* st, packet_info* pinfo, epan_dissect_t* edt, const void* p)
-{
-    struct FooTap *pi = (struct FooTap *)p;
-    tick_stat_node(st, st_str_packets, 0, FALSE);
-    stats_tree_tick_pivot(st, st_node_packet_types,
-            val_to_str(pi->packet_type, msgtypevalues, "Unknown packet type (%d)"));
-    return 1;
-}]]>
-   </programlisting></example>
-       <para>
-       In this case the processing of the stats is quite simple.
-       First we call the tick_stat_node for the st_str_packets packet node, to count
-       packets.
-       Then a call to stats_tree_tick_pivot on the st_node_packet_types subtree
-       allows us to record statistics by packet type.
-       </para>
-  </section>
-
-  <section id="ChDissectConversation">
-       <title>How to use conversations</title>
-       <para>
-       Some info about how to use conversations in a dissector can be
-       found in the file <filename>doc/README.developer</filename> chapter 2.2.
-       </para>
-  </section>
-
-</chapter>
-<!-- End of WSDG Chapter Dissection -->