Have TPKT support a TCP port range preference instead of having "subdissectors?"...
[metze/wireshark/wip.git] / epan / dissectors / packet-tpkt.c
index 40ddb58a74b0af262bc5ffe22ca5badc16e6448f..964ed7263dc8e0253a44b83e47205091be75660b 100644 (file)
@@ -7,8 +7,6 @@
  * Routine to dissect RFC 1006 TPKT packet containing OSI TP PDU
  * Copyright 2001, Martin Thomas <Martin_A_Thomas@yahoo.com>
  *
- * $Id$
- *
  * Wireshark - Network traffic analyzer
  * By Gerald Combs <gerald@wireshark.org>
  * Copyright 1998 Gerald Combs
  *
  * You should have received a copy of the GNU General Public License
  * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
  */
 
-#ifdef HAVE_CONFIG_H
-# include "config.h"
-#endif
+#include "config.h"
 
-#include <glib.h>
 #include <epan/packet.h>
+#include <epan/exceptions.h>
+#include <epan/prefs.h>
+#include <epan/show_exception.h>
 
 #include "packet-tpkt.h"
-#include "packet-frame.h"
-#include <epan/prefs.h>
-#include <ctype.h>
+
+void proto_register_tpkt(void);
+void proto_reg_handoff_tpkt(void);
+
 /* TPKT header fields             */
-static int proto_tpkt          = -1;
+static int proto_tpkt                = -1;
 static protocol_t *proto_tpkt_ptr;
-static int hf_tpkt_version     = -1;
-static int hf_tpkt_reserved    = -1;
-static int hf_tpkt_length      = -1;
+static int hf_tpkt_version           = -1;
+static int hf_tpkt_reserved          = -1;
+static int hf_tpkt_length            = -1;
+static int hf_tpkt_continuation_data = -1;
 
 
 /* TPKT fields defining a sub tree */
@@ -53,14 +53,11 @@ static gint ett_tpkt           = -1;
 /* desegmentation of OSI over TPKT over TCP */
 static gboolean tpkt_desegment = TRUE;
 
-#define TCP_PORT_TPKT          102
-#define TCP_PORT_TPKT_X224     3389
-
 /* find the dissector for OSI TP (aka COTP) */
 static dissector_handle_t osi_tp_handle;
 
-/* find the dissector for X.224 */
-static dissector_handle_t x224_handle;
+#define DEFAULT_TPKT_PORT_RANGE "102"
+static range_t *tpkt_tcp_port_range;
 
 /*
  * Check whether this could be a TPKT-encapsulated PDU.
@@ -74,39 +71,39 @@ static dissector_handle_t x224_handle;
 int
 is_tpkt(tvbuff_t *tvb, int min_len)
 {
-       guint16 pkt_len;
-
-       /*
-        * If TPKT is disabled, don't dissect it, just return -1, meaning
-        * "this isn't TPKT".
-        */
-       if (!proto_is_protocol_enabled(proto_tpkt_ptr))
-               return -1;
-
-       /* There should at least be 4 bytes left in the frame */
-       if (tvb_length(tvb) < 4)
-               return -1;      /* there aren't */
-
-       /*
-        * The first octet should be 3 and the second one should be 0
-        * The H.323 implementers guide suggests that this might not
-        * always be the case....
-        */
-       if (!(tvb_get_guint8(tvb, 0) == 3 && tvb_get_guint8(tvb, 1) == 0))
-               return -1;      /* they're not */
-
-       /*
-        * Get the length from the TPKT header.  Make sure it's large
-        * enough.
-        */
-       pkt_len = tvb_get_ntohs(tvb, 2);
-       if (pkt_len < 4 + min_len)
-               return -1;      /* it's not */
-
-       /*
-        * Return the length from the header.
-        */
-       return pkt_len;
+    guint16 pkt_len;
+
+    /*
+     * If TPKT is disabled, don't dissect it, just return -1, meaning
+     * "this isn't TPKT".
+     */
+    if (!proto_is_protocol_enabled(proto_tpkt_ptr))
+        return -1;
+
+    /* There should at least be 4 bytes left in the frame */
+    if (tvb_captured_length(tvb) < 4)
+        return -1;  /* there aren't */
+
+    /*
+     * The first octet should be 3 and the second one should be 0
+     * The H.323 implementers guide suggests that this might not
+     * always be the case....
+     */
+    if (!(tvb_get_guint8(tvb, 0) == 3 && tvb_get_guint8(tvb, 1) == 0))
+        return -1;  /* they're not */
+
+    /*
+     * Get the length from the TPKT header.  Make sure it's large
+     * enough.
+     */
+    pkt_len = tvb_get_ntohs(tvb, 2);
+    if (pkt_len < 4 + min_len)
+        return -1;  /* it's not */
+
+    /*
+     * Return the length from the header.
+     */
+    return pkt_len;
 }
 guint16
 is_asciitpkt(tvbuff_t *tvb)
@@ -124,11 +121,11 @@ is_asciitpkt(tvbuff_t *tvb)
         return -1;      /* there aren't */
 
         /*
-         * The first four  octets should be ASCII
+         * The first four  octets should be alphanumeric ASCII
          */
     for (count = 0; count <=7 ; count ++)
         {
-        if(!isalnum(tvb_get_guint8(tvb,count)))
+        if(!g_ascii_isalnum(tvb_get_guint8(tvb,count)))
           {
           return 0;
           }
@@ -202,12 +199,18 @@ parseReservedText ( guint8* pTpktData )
 
     return value;
 }
+
+/*
+ * Length of the TPKT text-layer header.
+ */
+static const int TEXT_LAYER_LENGTH   = 9;
+
 /*
  * Dissect ASCII TPKT-encapsulated data in a TCP stream.
  */
 void
 dissect_asciitpkt(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree,
-                 dissector_handle_t subdissector_handle)
+          dissector_handle_t subdissector_handle)
 {
     proto_item *ti = NULL;
     proto_tree *tpkt_tree = NULL;
@@ -221,7 +224,6 @@ dissect_asciitpkt(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree,
     tvbuff_t *volatile next_tvb;
     const char *saved_proto;
     guint8 string[4];
-    void *pd_save;
 
     /*
      * If we're reassembling segmented TPKT PDUs, empty the COL_INFO
@@ -234,7 +236,7 @@ dissect_asciitpkt(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree,
      * anyway.
      */
     if (tpkt_desegment)
-        col_add_str(pinfo->cinfo, COL_INFO, "");
+        col_set_str(pinfo->cinfo, COL_INFO, "");
 
     while (tvb_reported_length_remaining(tvb, offset) != 0) {
         /*
@@ -252,17 +254,15 @@ dissect_asciitpkt(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree,
             col_set_str(pinfo->cinfo, COL_INFO, "Continuation");
             if (tree) {
                 ti = proto_tree_add_item(tree, proto_tpkt, tvb,
-                    offset, -1, FALSE);
+                             offset, -1, ENC_NA);
                 tpkt_tree = proto_item_add_subtree(ti, ett_tpkt);
-                proto_item_set_text(ti, "TPKT");
 
-                proto_tree_add_text(tpkt_tree, tvb, offset, -1,
-                    "Continuation data");
+                proto_tree_add_item(tpkt_tree, hf_tpkt_continuation_data, tvb, offset, -1, ENC_NA);
             }
             return;
         }
 
-        length_remaining = tvb_length_remaining(tvb, offset);
+        length_remaining = tvb_captured_length_remaining(tvb, offset);
 
         /*
          * Get the length from the TPKT header.
@@ -295,26 +295,26 @@ dissect_asciitpkt(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree,
          */
         if (!tpkt_desegment && !pinfo->fragmented) {
             col_add_fstr(pinfo->cinfo, COL_INFO,
-                "TPKT Data length = %u", data_len);
+                     "TPKT Data length = %u", data_len);
         }
 
         if (tree) {
             ti = proto_tree_add_item(tree, proto_tpkt, tvb,
-                offset, 8, FALSE);
+                         offset, 8, ENC_NA);
             tpkt_tree = proto_item_add_subtree(ti, ett_tpkt);
             proto_item_set_text(ti, "TPKT");
 
             /* Version */
             proto_tree_add_uint(tpkt_tree, hf_tpkt_version, tvb,
-                            offset, 2, mgcp_version);
+                        offset, 2, mgcp_version);
 
             /* Reserved octet*/
             proto_tree_add_uint(tpkt_tree, hf_tpkt_reserved, tvb,
-                            offset + 2, 2, mgcp_reserved);
+                        offset + 2, 2, mgcp_reserved);
 
             /* Length */
             proto_tree_add_uint(tpkt_tree, hf_tpkt_length, tvb,
-                            offset + 4, 4, mgcp_packet_len);
+                        offset + 4, 4, mgcp_packet_len);
         }
         pinfo->current_proto = saved_proto;
 
@@ -329,31 +329,22 @@ dissect_asciitpkt(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree,
         /*
          * Call the subdissector.
          *
-         * Catch the ReportedBoundsError exception; if this
-         * particular message happens to get a ReportedBoundsError
-         * exception, that doesn't mean that we should stop
-         * dissecting TPKT messages within this frame or chunk
-         * of reassembled data.
+         * If it gets an error that means there's no point in
+         * dissecting any more TPKT messages, rethrow the
+         * exception in question.
          *
-         * If it gets a BoundsError, we can stop, as there's nothing
-         * more to see, so we just re-throw it.
+         * If it gets any other error, report it and continue, as that
+         * means that TPKT message got an error, but that doesn't mean
+         * we should stop dissecting TPKT messages within this frame
+         * or chunk of reassembled data.
          */
-       pd_save = pinfo->private_data;
         TRY {
             call_dissector(subdissector_handle, next_tvb, pinfo,
-                tree);
-        }
-        CATCH(BoundsError) {
-            RETHROW;
+                       tree);
         }
-        CATCH(ReportedBoundsError) {
-           /*  Restore the private_data structure in case one of the
-            *  called dissectors modified it (and, due to the exception,
-            *  was unable to restore it).
-            */
-           pinfo->private_data = pd_save;
-
-            show_reported_bounds_error(tvb, pinfo, tree);
+        CATCH_NONFATAL_ERRORS {
+
+            show_exception(tvb, pinfo, tree, EXCEPT_CODE, GET_MESSAGE);
         }
         ENDTRY;
 
@@ -369,233 +360,214 @@ dissect_asciitpkt(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree,
  */
 void
 dissect_tpkt_encap(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree,
-                  gboolean desegment, dissector_handle_t subdissector_handle)
+           gboolean desegment, dissector_handle_t subdissector_handle)
 {
-       proto_item *ti = NULL;
-       proto_tree *tpkt_tree = NULL;
-       volatile int offset = 0;
-       int length_remaining;
-       int data_len;
-       volatile int length;
-       tvbuff_t *volatile next_tvb;
-       const char *saved_proto;
-       void *pd_save;
-
-       /*
-        * If we're reassembling segmented TPKT PDUs, empty the COL_INFO
-        * column, so subdissectors can append information
-        * without having to worry about emptying the column.
-        *
-        * We use "col_add_str()" because the subdissector
-        * might be appending information to the column, in
-        * which case we'd have to zero the buffer out explicitly
-        * anyway.
-        */
-       if (desegment)
-               col_set_str(pinfo->cinfo, COL_INFO, "");
-
-       while (tvb_reported_length_remaining(tvb, offset) != 0) {
-               /*
-                * Is the first byte of this putative TPKT header
-                * a valid TPKT version number, i.e. 3?
-                */
-               if (tvb_get_guint8(tvb, offset) != 3) {
-                       /*
-                        * No, so don't assume this is a TPKT header;
-                        * we might be in the middle of TPKT data,
-                        * so don't get the length and don't try to
-                        * do reassembly.
-                        */
-                       col_set_str(pinfo->cinfo, COL_PROTOCOL, "TPKT");
-                       col_set_str(pinfo->cinfo, COL_INFO, "Continuation");
-                       if (tree) {
-                               ti = proto_tree_add_item(tree, proto_tpkt, tvb,
-                                   offset, -1, FALSE);
-                               tpkt_tree = proto_item_add_subtree(ti, ett_tpkt);
-                               proto_item_set_text(ti, "TPKT");
-
-                               proto_tree_add_text(tpkt_tree, tvb, offset, -1,
-                                   "Continuation data");
-                       }
-                       return;
-               }
-
-               length_remaining = tvb_length_remaining(tvb, offset);
-
-               /*
-                * Can we do reassembly?
-                */
-               if (desegment && pinfo->can_desegment) {
-                       /*
-                        * Yes - is the TPKT header split across segment
-                        * boundaries?
-                        */
-                       if (length_remaining < 4) {
-                               /*
-                                * Yes.  Tell the TCP dissector where
-                                * the data for this message starts in
-                                * the data it handed us, and how many
-                                * more bytes we need, and return.
-                                */
-                               pinfo->desegment_offset = offset;
-                               pinfo->desegment_len = 4 - length_remaining;
-                               return;
-                       }
-               }
-
-               /*
-                * Get the length from the TPKT header.
-                */
-               data_len = tvb_get_ntohs(tvb, offset + 2);
-
-               /*
-                * Can we do reassembly?
-                */
-               if (desegment && pinfo->can_desegment) {
-                       /*
-                        * Yes - is the payload split across segment
-                        * boundaries?
-                        */
-                       if (length_remaining < data_len) {
-                               /*
-                                * Yes.  Tell the TCP dissector where
-                                * the data for this message starts in
-                                * the data it handed us, and how many
-                                * more bytes we need, and return.
-                                */
-                               pinfo->desegment_offset = offset;
-                               pinfo->desegment_len =
-                                   data_len - length_remaining;
-                               return;
-                       }
-               }
-
-               /*
-                * Dissect the TPKT header.
-                * Save and restore "pinfo->current_proto".
-                */
-               saved_proto = pinfo->current_proto;
-               pinfo->current_proto = "TPKT";
-
-               col_set_str(pinfo->cinfo, COL_PROTOCOL, "TPKT");
-               /*
-                * Don't add the TPKT header information if we're
-                * reassembling segmented TPKT PDUs or if this
-                * PDU isn't reassembled.
-                *
-                * XXX - the first is so that subdissectors can append
-                * information without getting TPKT stuff in the middle;
-                * why the second?
-                */
-               if (!desegment && !pinfo->fragmented) {
-                       col_add_fstr(pinfo->cinfo, COL_INFO,
-                           "TPKT Data length = %u", data_len);
-               }
-
-               if (tree) {
-                       ti = proto_tree_add_item(tree, proto_tpkt, tvb,
-                           offset, 4, FALSE);
-                       tpkt_tree = proto_item_add_subtree(ti, ett_tpkt);
-                       proto_item_set_text(ti, "TPKT");
-
-                       /* Version */
-                       proto_tree_add_item(tpkt_tree, hf_tpkt_version, tvb,
-                           offset, 1, FALSE);
-                       proto_item_append_text(ti, ", Version: 3");
-
-                       /* Reserved octet*/
-                       proto_tree_add_item(tpkt_tree, hf_tpkt_reserved, tvb,
-                           offset + 1, 1, FALSE);
-
-                       /* Length */
-                       proto_tree_add_uint(tpkt_tree, hf_tpkt_length, tvb,
-                           offset + 2, 2, data_len);
-                       proto_item_append_text(ti, ", Length: %u", data_len);
-               }
-               pinfo->current_proto = saved_proto;
-
-               /* Skip the TPKT header. */
-               offset += 4;
-               data_len -= 4;
-
-               /*
-                * Construct a tvbuff containing the amount of the payload
-                * we have available.  Make its reported length the
-                * amount of data in this TPKT packet.
-                *
-                * XXX - if reassembly isn't enabled. the subdissector
-                * will throw a BoundsError exception, rather than a
-                * ReportedBoundsError exception.  We really want
-                * a tvbuff where the length is "length", the reported
-                * length is "plen + 2", and the "if the snapshot length
-                * were infinite" length were the minimum of the
-                * reported length of the tvbuff handed to us and "plen+2",
-                * with a new type of exception thrown if the offset is
-                * within the reported length but beyond that third length,
-                * with that exception getting the "Unreassembled Packet"
-                * error.
-                */
-               length = length_remaining - 4;
-               if (length > data_len)
-                       length = data_len;
-               next_tvb = tvb_new_subset(tvb, offset, length, data_len);
-
-               /*
-                * Call the subdissector.
-                *
-                * Catch the ReportedBoundsError exception; if this
-                * particular message happens to get a ReportedBoundsError
-                * exception, that doesn't mean that we should stop
-                * dissecting TPKT messages within this frame or chunk
-                * of reassembled data.
-                *
-                * If it gets a BoundsError, we can stop, as there's nothing
-                * more to see, so we just re-throw it.
-                */
-               pd_save = pinfo->private_data;
-               TRY {
-                       call_dissector(subdissector_handle, next_tvb, pinfo,
-                           tree);
-               }
-               CATCH(BoundsError) {
-                       RETHROW;
-               }
-               CATCH(ReportedBoundsError) {
-                       /*  Restore the private_data structure in case one of the
-                        *  called dissectors modified it (and, due to the exception,
-                        *  was unable to restore it).
-                        */
-                       pinfo->private_data = pd_save;
-
-                       show_reported_bounds_error(tvb, pinfo, tree);
-               }
-               ENDTRY;
-
-               /*
-                * Skip the payload.
-                */
-               offset += length;
-       }
-}
+    proto_item *ti = NULL;
+    proto_tree *tpkt_tree = NULL;
+    volatile int offset = 0;
+    int length_remaining;
+    int data_len;
+    volatile int length;
+    tvbuff_t *volatile next_tvb;
+    const char *saved_proto;
 
-/*
- * Dissect RFC 1006 TPKT, which wraps a TPKT header around an OSI TP
- * PDU.
- */
-static void
-dissect_tpkt(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
-{
-       dissect_tpkt_encap(tvb, pinfo, tree, tpkt_desegment, osi_tp_handle);
+    /*
+     * If we're reassembling segmented TPKT PDUs, empty the COL_INFO
+     * column, so subdissectors can append information
+     * without having to worry about emptying the column.
+     *
+     * We use "col_add_str()" because the subdissector
+     * might be appending information to the column, in
+     * which case we'd have to zero the buffer out explicitly
+     * anyway.
+     */
+    if (desegment)
+        col_set_str(pinfo->cinfo, COL_INFO, "");
+
+    while (tvb_reported_length_remaining(tvb, offset) != 0) {
+        /*
+         * Is the first byte of this putative TPKT header
+         * a valid TPKT version number, i.e. 3?
+         */
+        if (tvb_get_guint8(tvb, offset) != 3) {
+            /*
+             * No, so don't assume this is a TPKT header;
+             * we might be in the middle of TPKT data,
+             * so don't get the length and don't try to
+             * do reassembly.
+             */
+            col_set_str(pinfo->cinfo, COL_PROTOCOL, "TPKT");
+            col_set_str(pinfo->cinfo, COL_INFO, "Continuation");
+            if (tree) {
+                ti = proto_tree_add_item(tree, proto_tpkt, tvb,
+                    offset, -1, ENC_NA);
+                tpkt_tree = proto_item_add_subtree(ti, ett_tpkt);
+
+                proto_tree_add_item(tpkt_tree, hf_tpkt_continuation_data, tvb, offset, -1, ENC_NA);
+            }
+            return;
+        }
+
+        length_remaining = tvb_captured_length_remaining(tvb, offset);
+
+        /*
+         * Can we do reassembly?
+         */
+        if (desegment && pinfo->can_desegment) {
+            /*
+             * Yes - is the TPKT header split across segment
+             * boundaries?
+             */
+            if (length_remaining < 4) {
+                /*
+                 * Yes.  Tell the TCP dissector where the data
+                 * for this message starts in the data it
+                 * handed us and that we need "some more data."
+                 * Don't tell it exactly how many bytes we need
+                 * because if/when we ask for even more (after
+                 * the header) that will break reassembly.
+                 */
+                pinfo->desegment_offset = offset;
+                pinfo->desegment_len = DESEGMENT_ONE_MORE_SEGMENT;
+                return;
+            }
+        }
+
+        /*
+         * Get the length from the TPKT header.
+         */
+        data_len = tvb_get_ntohs(tvb, offset + 2);
+
+        /*
+         * Can we do reassembly?
+         */
+        if (desegment && pinfo->can_desegment) {
+            /*
+             * Yes - is the payload split across segment
+             * boundaries?
+             */
+            if (length_remaining < data_len) {
+                /*
+                 * Yes.  Tell the TCP dissector where
+                 * the data for this message starts in
+                 * the data it handed us, and how many
+                 * more bytes we need, and return.
+                 */
+                pinfo->desegment_offset = offset;
+                pinfo->desegment_len =
+                    data_len - length_remaining;
+                return;
+            }
+        }
+
+        /*
+         * Dissect the TPKT header.
+         * Save and restore "pinfo->current_proto".
+         */
+        saved_proto = pinfo->current_proto;
+        pinfo->current_proto = "TPKT";
+
+        col_set_str(pinfo->cinfo, COL_PROTOCOL, "TPKT");
+        /*
+         * Don't add the TPKT header information if we're
+         * reassembling segmented TPKT PDUs or if this
+         * PDU isn't reassembled.
+         *
+         * XXX - the first is so that subdissectors can append
+         * information without getting TPKT stuff in the middle;
+         * why the second?
+         */
+        if (!desegment && !pinfo->fragmented) {
+            col_add_fstr(pinfo->cinfo, COL_INFO,
+                "TPKT Data length = %u", data_len);
+        }
+
+        if (tree) {
+            ti = proto_tree_add_item(tree, proto_tpkt, tvb,
+                offset, 4, ENC_NA);
+            tpkt_tree = proto_item_add_subtree(ti, ett_tpkt);
+            proto_item_set_text(ti, "TPKT");
+
+            /* Version */
+            proto_tree_add_item(tpkt_tree, hf_tpkt_version, tvb,
+                offset, 1, ENC_BIG_ENDIAN);
+            proto_item_append_text(ti, ", Version: 3");
+
+            /* Reserved octet*/
+            proto_tree_add_item(tpkt_tree, hf_tpkt_reserved, tvb,
+                offset + 1, 1, ENC_BIG_ENDIAN);
+
+            /* Length */
+            proto_tree_add_uint(tpkt_tree, hf_tpkt_length, tvb,
+                offset + 2, 2, data_len);
+            proto_item_append_text(ti, ", Length: %u", data_len);
+        }
+        pinfo->current_proto = saved_proto;
+
+        /* Skip the TPKT header. */
+        offset += 4;
+        data_len -= 4;
+
+        /*
+         * Construct a tvbuff containing the amount of the payload
+         * we have available.  Make its reported length the
+         * amount of data in this TPKT packet.
+         *
+         * XXX - if reassembly isn't enabled. the subdissector
+         * will throw a BoundsError exception, rather than a
+         * ReportedBoundsError exception.  We really want
+         * a tvbuff where the length is "length", the reported
+         * length is "plen + 2", and the "if the snapshot length
+         * were infinite" length were the minimum of the
+         * reported length of the tvbuff handed to us and "plen+2",
+         * with a new type of exception thrown if the offset is
+         * within the reported length but beyond that third length,
+         * with that exception getting the "Unreassembled Packet"
+         * error.
+         */
+        length = length_remaining - 4;
+        if (length > data_len)
+            length = data_len;
+        next_tvb = tvb_new_subset(tvb, offset, length, data_len);
+
+        /*
+         * Call the subdissector.
+         *
+         * If it gets an error that means there's no point in
+         * dissecting any more TPKT messages, rethrow the
+         * exception in question.
+         *
+         * If it gets any other error, report it and continue,
+         * as that means that TPKT message got an error, but
+         * that doesn't mean we should stop dissecting TPKT
+         * messages within this frame or chunk of reassembled
+         * data.
+         */
+        TRY {
+            call_dissector(subdissector_handle, next_tvb, pinfo,
+                tree);
+        }
+        CATCH_NONFATAL_ERRORS {
+            show_exception(tvb, pinfo, tree, EXCEPT_CODE, GET_MESSAGE);
+        }
+        ENDTRY;
+
+        /*
+         * Skip the payload.
+         */
+        offset += length;
+    }
 }
 
 /*
- * Dissect RFC 1006 TPKT, which wraps a TPKT header around an X.224
+ * Dissect RFC 1006 TPKT, which wraps a TPKT header around an OSI TP
  * PDU.
  */
-static void
-dissect_tpkt_x224(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
+static int
+dissect_tpkt(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void* data _U_)
 {
-       dissect_tpkt_encap(tvb, pinfo, tree, tpkt_desegment, x224_handle);
+    dissect_tpkt_encap(tvb, pinfo, tree, tpkt_desegment, osi_tp_handle);
+    return tvb_captured_length(tvb);
 }
 
 /*
@@ -603,92 +575,133 @@ dissect_tpkt_x224(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
  * PDU.
  */
 #if 0
-static void
-dissect_ascii_tpkt(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
+static int
+dissect_ascii_tpkt(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void* data _U_)
 {
-        dissect_asciitpkt(tvb, pinfo, tree, osi_tp_handle);
+    dissect_asciitpkt(tvb, pinfo, tree, osi_tp_handle);
+    return tvb_captured_length(tvb);
 }
 #endif
 
 void
 proto_register_tpkt(void)
 {
-       static hf_register_info hf[] =
-       {
-               {
-                       &hf_tpkt_version,
-                       {
-                               "Version",
-                               "tpkt.version",
-                               FT_UINT8,
-                               BASE_DEC,
-                               NULL,
-                               0x0,
-                               "Version, only version 3 is defined", HFILL
-                       }
-               },
-               {
-                       &hf_tpkt_reserved,
-                       {
-                               "Reserved",
-                               "tpkt.reserved",
-                               FT_UINT8,
-                               BASE_DEC,
-                               NULL,
-                               0x0,
-                               "Reserved, should be 0", HFILL
-                       }
-               },
-               {
-                       &hf_tpkt_length,
-                       {
-                               "Length",
-                               "tpkt.length",
-                               FT_UINT16,
-                               BASE_DEC,
-                               NULL,
-                               0x0,
-                               "Length of data unit, including this header", HFILL
-                       }
-               },
-       };
-
-       static gint *ett[] =
-       {
-               &ett_tpkt,
-       };
-       module_t *tpkt_module;
-
-       proto_tpkt = proto_register_protocol("TPKT - ISO on TCP - RFC1006", "TPKT", "tpkt");
-       proto_tpkt_ptr = find_protocol_by_id(proto_tpkt);
-       proto_register_field_array(proto_tpkt, hf, array_length(hf));
-       proto_register_subtree_array(ett, array_length(ett));
-       register_dissector("tpkt", dissect_tpkt, proto_tpkt);
-
-       tpkt_module = prefs_register_protocol(proto_tpkt, NULL);
-       prefs_register_bool_preference(tpkt_module, "desegment",
-           "Reassemble TPKT messages spanning multiple TCP segments",
-           "Whether the TPKT dissector should reassemble messages spanning multiple TCP segments. "
-           "To use this option, you must also enable \"Allow subdissectors to reassemble TCP streams\" in the TCP protocol settings.",
-           &tpkt_desegment);
+    static hf_register_info hf[] = {
+        {
+            &hf_tpkt_version,
+            {
+                "Version",
+                "tpkt.version",
+                FT_UINT8,
+                BASE_DEC,
+                NULL,
+                0x0,
+                "Version, only version 3 is defined", HFILL
+            }
+        },
+        {
+            &hf_tpkt_reserved,
+            {
+                "Reserved",
+                "tpkt.reserved",
+                FT_UINT8,
+                BASE_DEC,
+                NULL,
+                0x0,
+                "Reserved, should be 0", HFILL
+            }
+        },
+        {
+            &hf_tpkt_length,
+            {
+                "Length",
+                "tpkt.length",
+                FT_UINT16,
+                BASE_DEC,
+                NULL,
+                0x0,
+                "Length of data unit, including this header", HFILL
+            }
+        },
+        {
+            &hf_tpkt_continuation_data,
+            {
+                "Continuation data",
+                "tpkt.continuation_data",
+                FT_BYTES,
+                BASE_NONE,
+                NULL,
+                0x0,
+                NULL, HFILL
+            }
+        },
+    };
+
+    static gint *ett[] =
+    {
+        &ett_tpkt,
+    };
+    module_t *tpkt_module;
+
+    proto_tpkt = proto_register_protocol("TPKT - ISO on TCP - RFC1006", "TPKT", "tpkt");
+    proto_tpkt_ptr = find_protocol_by_id(proto_tpkt);
+    proto_register_field_array(proto_tpkt, hf, array_length(hf));
+    proto_register_subtree_array(ett, array_length(ett));
+    register_dissector("tpkt", dissect_tpkt, proto_tpkt);
+
+    tpkt_module = prefs_register_protocol(proto_tpkt, proto_reg_handoff_tpkt);
+    prefs_register_bool_preference(tpkt_module, "desegment",
+        "Reassemble TPKT messages spanning multiple TCP segments",
+        "Whether the TPKT dissector should reassemble messages spanning multiple TCP segments. "
+        "To use this option, you must also enable \"Allow subdissectors to reassemble TCP streams\" in the TCP protocol settings.",
+        &tpkt_desegment);
+
+    range_convert_str(&tpkt_tcp_port_range, DEFAULT_TPKT_PORT_RANGE, MAX_TCP_PORT);
+
+    prefs_register_range_preference(tpkt_module, "tcp.ports", "TPKT TCP ports",
+                                  "TCP ports to be decoded as TPKT (default: "
+                                  DEFAULT_TPKT_PORT_RANGE ")",
+                                  &tpkt_tcp_port_range, MAX_TCP_PORT);
 }
 
 void
 proto_reg_handoff_tpkt(void)
 {
-       dissector_handle_t tpkt_handle, tpkt_x224_handle;
-
-       osi_tp_handle = find_dissector("ositp");
-       tpkt_handle = find_dissector("tpkt");
-       dissector_add_uint("tcp.port", TCP_PORT_TPKT, tpkt_handle);
+    static dissector_handle_t tpkt_handle;
+    static range_t *port_range;
+    static gboolean initialized = FALSE;
+
+    if (!initialized)
+    {
+        osi_tp_handle = find_dissector("ositp");
+        tpkt_handle = find_dissector("tpkt");
+        initialized = TRUE;
+    }
+    else
+    {
+        dissector_delete_uint_range("tcp.port", port_range, tpkt_handle);
+        g_free(port_range);
+    }
 
-       x224_handle = find_dissector("x224");
-       tpkt_x224_handle = create_dissector_handle(dissect_tpkt_x224, proto_tpkt);
-       dissector_add_uint("tcp.port", TCP_PORT_TPKT_X224, tpkt_x224_handle);
+    port_range = range_copy(tpkt_tcp_port_range);
+    dissector_add_uint_range("tcp.port", port_range, tpkt_handle);
 
-       /*
-       tpkt_ascii_handle = create_dissector_handle(dissect_ascii_tpkt, proto_tpkt);
-       dissector_add_uint("tcp.port", TCP_PORT_TPKT, tpkt_ascii_handle);
-       */
+    /*
+    tpkt_ascii_handle = create_dissector_handle(dissect_ascii_tpkt, proto_tpkt);
+    dissector_add_uint("tcp.port", TCP_PORT_TPKT, tpkt_ascii_handle);
+    */
 
 }
+
+/*
+ * Editor modelines  -  http://www.wireshark.org/tools/modelines.html
+ *
+ * Local variables:
+ * c-basic-offset: 4
+ * tab-width: 8
+ * indent-tabs-mode: nil
+ * End:
+ *
+ * vi: set shiftwidth=4 tabstop=8 expandtab:
+ * :indentSize=4:tabSize=8:noTabs=true:
+ */