Try to fix Windows compilation
[metze/wireshark/wip.git] / epan / packet.c
index 6561d0724df817862e61db519862b75085ff6ed1..5e1c180b3c0833f745bc56a4649c32d1cff4ae8f 100644 (file)
  *
  * 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 "tvbuff.h"
 #include "plugins.h"
 #include "epan_dissect.h"
+
 #include "emem.h"
+#include "wmem/wmem.h"
 
 #include <epan/reassemble.h>
 #include <epan/stream.h>
+#include <epan/expert.h>
 
 static gint proto_malformed = -1;
 static dissector_handle_t frame_handle = NULL;
 static dissector_handle_t data_handle = NULL;
 
-const true_false_string flags_set_truth = {
-  "Set",
-  "Not set"
+/**
+ * A data source.
+ * Has a tvbuff and a name.
+ */
+struct data_source {
+  tvbuff_t *tvb;
+  char *name;
 };
 
 void
 packet_init(void)
 {
-  frame_handle = find_dissector("frame");
-  data_handle = find_dissector("data");
-  proto_malformed = proto_get_id_by_filter_name("malformed");
+       frame_handle = find_dissector("frame");
+       data_handle = find_dissector("data");
+       proto_malformed = proto_get_id_by_filter_name("malformed");
 }
 
 void
@@ -84,17 +89,17 @@ packet_cleanup(void)
  * of the tvbuff to reflect the specified length.
  */
 void
-set_actual_length(tvbuff_t *tvb, guint specified_len)
+set_actual_length(tvbuff_t *tvb, const guint specified_len)
 {
-  if (specified_len < tvb_reported_length(tvb)) {
-    /* Adjust the length of this tvbuff to include only the specified
-       payload length.
+       if (specified_len < tvb_reported_length(tvb)) {
+               /* Adjust the length of this tvbuff to include only the specified
+                  payload length.
 
-       The dissector above the one calling us (the dissector above is
-       probably us) may use that to determine how much of its packet
-       was padding. */
-    tvb_set_reported_length(tvb, specified_len);
-  }
+                  The dissector above the one calling us (the dissector above is
+                  probably us) may use that to determine how much of its packet
+                  was padding. */
+               tvb_set_reported_length(tvb, specified_len);
+       }
 }
 
 /* Allow protocols to register "init" routines, which are called before
@@ -133,6 +138,15 @@ init_dissection(void)
        /* Reclaim and reinitialize all memory of seasonal scope */
        se_free_all();
 
+       wmem_enter_file_scope();
+
+       /*
+        * Reinitialize resolution information. We do initialization here in
+        * case we need to resolve between captures.
+        */
+       host_name_lookup_cleanup();
+       host_name_lookup_init();
+
        /* Initialize the table of conversations. */
        epan_conversation_init();
 
@@ -142,20 +156,45 @@ init_dissection(void)
        /* Initialize protocol-specific variables. */
        g_slist_foreach(init_routines, &call_init_routine, NULL);
 
-       /* Initialize the common data structures for fragment reassembly.
-          Must be done *after* calling init routines, as those routines
-          may free up space for fragments, which they find by using the
-          data structures that "reassemble_init()" frees. */
-       reassemble_init();
-
-       /* Initialise the stream-handling tables */
+       /* Initialize the stream-handling tables */
        stream_init();
+
+       /* Initialize the expert infos */
+       expert_init();
 }
 
 void
 cleanup_dissection(void)
 {
-       init_dissection();
+       /* Cleanup the table of conversations. Do this before freeing seasonal
+        * memory (at least until conversation's use of g_slist is changed).
+        */
+       epan_conversation_cleanup();
+
+       /* Reclaim all memory of seasonal scope */
+       se_free_all();
+
+       /* Cleanup the table of circuits. */
+       epan_circuit_cleanup();
+
+       /* TODO: Introduce cleanup_routines */
+       /* Cleanup protocol-specific variables. */
+       g_slist_foreach(init_routines, &call_init_routine, NULL);
+
+       /* Cleanup the stream-handling tables */
+       stream_cleanup();
+
+       /* Initialize the expert infos */
+       expert_cleanup();
+       
+       wmem_leave_file_scope();
+
+       /*
+        * Reinitialize resolution information. We do initialization here in
+        * case we need to resolve between captures.
+        */
+       host_name_lookup_cleanup();
+       host_name_lookup_init();
 }
 
 /* Allow protocols to register a "cleanup" routine to be
@@ -193,27 +232,53 @@ postseq_cleanup_all_protocols(void)
 void
 add_new_data_source(packet_info *pinfo, tvbuff_t *tvb, const char *name)
 {
-       data_source *src;
+       struct data_source *src;
 
-       src = ep_alloc(sizeof (data_source));
+       src = g_malloc(sizeof(struct data_source));
        src->tvb = tvb;
-       /*
-        * XXX - if we require this argument to be a string constant,
-        * we don't need to allocate a buffer for a copy and make a
-        * copy, and wouldn't need to free the buffer, either.
-        */
-       src->name = ep_strdup_printf("%s (%u bytes)", name, tvb_length(tvb));
+       src->name = g_strdup(name);
        pinfo->data_src = g_slist_append(pinfo->data_src, src);
 }
 
+const char*
+get_data_source_name(const struct data_source *src)
+{
+       return ep_strdup_printf("%s (%u bytes)", src->name, tvb_length(src->tvb));
+}
+
+tvbuff_t *
+get_data_source_tvb(const struct data_source *src)
+{
+       return src->tvb;
+}
+
 /*
  * Free up a frame's list of data sources.
  */
 void
 free_data_sources(packet_info *pinfo)
 {
-       g_slist_free(pinfo->data_src);
-       pinfo->data_src = NULL;
+       if (pinfo->data_src) {
+               GSList *l;
+
+               for (l = pinfo->data_src; l; l = l->next) {
+                       struct data_source *src = l->data;
+
+                       g_free(src->name);
+                       g_free(src);
+               }
+               g_slist_free(pinfo->data_src);
+               pinfo->data_src = NULL;
+       }
+}
+
+void
+mark_frame_as_depended_upon(packet_info *pinfo, guint32 frame_num)
+{
+       /* Don't mark a frame as dependent on itself */
+       if (frame_num != PINFO_FD_NUM(pinfo)) {
+               pinfo->dependent_frames = g_slist_prepend(pinfo->dependent_frames, GUINT_TO_POINTER(frame_num));
+       }
 }
 
 /* Allow dissectors to register a "final_registration" routine
@@ -251,69 +316,64 @@ final_registration_all_protocols(void)
 
 /* Creates the top-most tvbuff and calls dissect_frame() */
 void
-dissect_packet(epan_dissect_t *edt, union wtap_pseudo_header *pseudo_header,
+dissect_packet(epan_dissect_t *edt, struct wtap_pkthdr *phdr,
               const guchar *pd, frame_data *fd, column_info *cinfo)
 {
        if (cinfo != NULL)
                col_init(cinfo);
+       memset(&edt->pi, 0, sizeof(edt->pi));
        edt->pi.current_proto = "<Missing Protocol Name>";
        edt->pi.cinfo = cinfo;
        edt->pi.fd = fd;
-       edt->pi.pseudo_header = pseudo_header;
-       edt->pi.data_src = NULL;
+       edt->pi.phdr = phdr;
+       edt->pi.pseudo_header = &phdr->pseudo_header;
        edt->pi.dl_src.type = AT_NONE;
-       edt->pi.dl_src.len = 0;
-       edt->pi.dl_src.data = NULL;
        edt->pi.dl_dst.type = AT_NONE;
-       edt->pi.dl_dst.len = 0;
-       edt->pi.dl_dst.data = NULL;
        edt->pi.net_src.type = AT_NONE;
-       edt->pi.net_src.len = 0;
-       edt->pi.net_src.data = NULL;
        edt->pi.net_dst.type = AT_NONE;
-       edt->pi.net_dst.len = 0;
-       edt->pi.net_dst.data = NULL;
        edt->pi.src.type = AT_NONE;
-       edt->pi.src.len = 0;
-       edt->pi.src.data = NULL;
        edt->pi.dst.type = AT_NONE;
-       edt->pi.dst.len = 0;
-       edt->pi.dst.data = NULL;
-       edt->pi.ethertype = 0;
-       edt->pi.ipproto  = 0;
-       edt->pi.ipxptype = 0;
        edt->pi.ctype = CT_NONE;
-       edt->pi.circuit_id = 0;
        edt->pi.noreassembly_reason = "";
-       edt->pi.fragmented = FALSE;
-       edt->pi.in_error_pkt = FALSE;
        edt->pi.ptype = PT_NONE;
-       edt->pi.srcport  = 0;
-       edt->pi.destport = 0;
-       edt->pi.match_port = 0;
-       edt->pi.match_string = NULL;
-       edt->pi.can_desegment = 0;
-       edt->pi.want_pdu_tracking = 0;
        edt->pi.p2p_dir = P2P_DIR_UNKNOWN;
-       edt->pi.private_data = NULL;
-       edt->pi.oxid = 0;
-       edt->pi.rxid = 0;
-       edt->pi.r_ctl = 0;
-       edt->pi.src_idx = 0;
-       edt->pi.dst_idx = 0;
-       edt->pi.vsan = 0;
-       edt->pi.dcectxid = 0;
        edt->pi.dcetransporttype = -1;
-       edt->pi.decrypt_gssapi_tvb = 0;
-       edt->pi.gssapi_wrap_tvb = NULL;
-       edt->pi.gssapi_encrypted_tvb = NULL;
-       edt->pi.gssapi_decrypted_tvb = NULL;
-       edt->pi.layer_names = NULL;
-       edt->pi.link_number = 0;
        edt->pi.annex_a_used = MTP2_ANNEX_A_USED_UNKNOWN;
+       edt->pi.dcerpc_procedure_name="";
+       edt->pi.link_dir = LINK_DIR_UNKNOWN;
+       edt->tvb = NULL;
+
+       /* to enable decode as for ethertype=0x0000 (fix for bug 4721) */
+       edt->pi.ethertype = G_MAXINT;
+
+       EP_CHECK_CANARY(("before dissecting frame %d",fd->num));
 
        TRY {
-               edt->tvb = tvb_new_real_data(pd, fd->cap_len, fd->pkt_len);
+               /*
+                * XXX - currently, the length arguments to
+                * tvb_new_real_data() are signed, but the captured
+                * and reported length values are unsigned; this means
+                * that length values > 2^31 - 1 will appear as
+                * negative lengths in tvb_new_real_data().
+                *
+                * Captured length values that large will already
+                * have been filtered out by the Wiretap modules
+                * (the file will be reported as corrupted), to
+                * avoid trying to allocate large chunks of data.
+                *
+                * Reported length values will not have been
+                * filtered out, and should not be filtered out,
+                * as those lengths are not necessarily invalid.
+                *
+                * For now, we clip the reported length at G_MAXINT,
+                * so that tvb_new_real_data() doesn't fail.  It
+                * would throw an exception, which we'd catch, but
+                * that would mean we would have no tvbuffs
+                * associated with edt, which would upset much of
+                * the rest of the application.
+                */
+               edt->tvb = tvb_new_real_data(pd, fd->cap_len,
+                   fd->pkt_len > G_MAXINT ? G_MAXINT : fd->pkt_len);
                /* Add this tvbuffer into the data_src list */
                add_new_data_source(&edt->pi, edt->tvb, "Frame");
 
@@ -331,20 +391,25 @@ dissect_packet(epan_dissect_t *edt, union wtap_pseudo_header *pseudo_header,
        CATCH(ReportedBoundsError) {
                if(proto_malformed != -1){
                        proto_tree_add_protocol_format(edt->tree, proto_malformed, edt->tvb, 0, 0,
-                                                      "[Malformed Frame: Packet Length]" );
+                                                      "[Malformed Frame: Packet Length]" );
                } else {
                        g_assert_not_reached();
                }
        }
+       CATCH(OutOfMemoryError) {
+               RETHROW;
+       }
        ENDTRY;
 
+       EP_CHECK_CANARY(("after dissecting frame %d",fd->num));
+
        fd->flags.visited = 1;
 }
 
 /*********************** code added for sub-dissector lookup *********************/
 
 /*
- * An dissector handle.
+ * A dissector handle.
  */
 struct dissector_handle {
        const char      *name;          /* dissector name */
@@ -368,22 +433,26 @@ struct dissector_handle {
  */
 static int
 call_dissector_through_handle(dissector_handle_t handle, tvbuff_t *tvb,
-    packet_info *pinfo, proto_tree *tree)
+                             packet_info *pinfo, proto_tree *tree, void *data)
 {
        const char *saved_proto;
-       int ret;
+       int         ret;
 
        saved_proto = pinfo->current_proto;
 
        if (handle->protocol != NULL) {
                pinfo->current_proto =
-                   proto_get_protocol_short_name(handle->protocol);
+                       proto_get_protocol_short_name(handle->protocol);
        }
 
        if (handle->is_new) {
-               ret = (*handle->dissector.new)(tvb, pinfo, tree);
+               EP_CHECK_CANARY(("before calling handle->dissector.new for %s",handle->name));
+               ret = (*handle->dissector.new)(tvb, pinfo, tree, data);
+               EP_CHECK_CANARY(("after calling handle->dissector.new for %s",handle->name));
        } else {
+               EP_CHECK_CANARY(("before calling handle->dissector.old for %s",handle->name));
                (*handle->dissector.old)(tvb, pinfo, tree);
+               EP_CHECK_CANARY(("after calling handle->dissector.old for %s",handle->name));
                ret = tvb_length(tvb);
                if (ret == 0) {
                        /*
@@ -408,22 +477,20 @@ call_dissector_through_handle(dissector_handle_t handle, tvbuff_t *tvb,
  * dissector and return its return value, otherwise call it and return
  * the length of the tvbuff pointed to by the argument.
  */
+
 static int
-call_dissector_work(dissector_handle_t handle, tvbuff_t *tvb,
-    packet_info *pinfo_arg, proto_tree *tree)
+call_dissector_work_error(dissector_handle_t handle, tvbuff_t *tvb,
+                         packet_info *pinfo_arg, proto_tree *tree, void *);
+
+static int
+call_dissector_work(dissector_handle_t handle, tvbuff_t *tvb, packet_info *pinfo_arg,
+                   proto_tree *tree, gboolean add_proto_name, void *data)
 {
-       packet_info *volatile pinfo = pinfo_arg;
-       const char *saved_proto;
-       guint16 saved_can_desegment;
-       volatile int ret = 0;
-       gboolean save_writable;
-       volatile address save_dl_src;
-       volatile address save_dl_dst;
-       volatile address save_net_src;
-       volatile address save_net_dst;
-       volatile address save_src;
-       volatile address save_dst;
-       volatile gint saved_layer_names_len = 0;
+       packet_info *pinfo = pinfo_arg;
+       const char  *saved_proto;
+       guint16      saved_can_desegment;
+       int          ret;
+       gint         saved_layer_names_len = 0;
 
        if (handle->protocol != NULL &&
            !proto_is_protocol_enabled(handle->protocol)) {
@@ -437,7 +504,7 @@ call_dissector_work(dissector_handle_t handle, tvbuff_t *tvb,
        saved_can_desegment = pinfo->can_desegment;
 
        if (pinfo->layer_names != NULL)
-               saved_layer_names_len = pinfo->layer_names->len;
+               saved_layer_names_len = (gint) pinfo->layer_names->len;
 
        /*
         * can_desegment is set to 2 by anyone which offers the
@@ -455,125 +522,150 @@ call_dissector_work(dissector_handle_t handle, tvbuff_t *tvb,
        pinfo->can_desegment = saved_can_desegment-(saved_can_desegment>0);
        if (handle->protocol != NULL) {
                pinfo->current_proto =
-                   proto_get_protocol_short_name(handle->protocol);
+                       proto_get_protocol_short_name(handle->protocol);
 
                /*
                 * Add the protocol name to the layers
+                * if not told not to. Asn2wrs generated dissectors may be added multiple times otherwise.
                 */
-               if (pinfo->layer_names) {
+               if ((pinfo->layer_names)&&(add_proto_name)) {
                        if (pinfo->layer_names->len > 0)
                                g_string_append(pinfo->layer_names, ":");
-                       g_string_append(pinfo->layer_names,
-                           proto_get_protocol_filter_name(proto_get_id(handle->protocol)));
+                               g_string_append(pinfo->layer_names,
+                               proto_get_protocol_filter_name(proto_get_id(handle->protocol)));
                }
        }
 
-       if (pinfo->in_error_pkt) {
+       if (pinfo->flags.in_error_pkt) {
+               ret = call_dissector_work_error(handle, tvb, pinfo, tree, data);
+       } else {
                /*
-                * This isn't a packet being transported inside
-                * the protocol whose dissector is calling us,
-                * it's a copy of a packet that caused an error
-                * in some protocol included in a packet that
-                * reports the error (e.g., an ICMP Unreachable
-                * packet).
-                */
-
+                * Just call the subdissector.
+                */
+               ret = call_dissector_through_handle(handle, tvb, pinfo, tree, data);
+       }
+       if (ret == 0) {
                /*
-                * Save the current state of the writability of
-                * the columns, and restore them after the
-                * dissector returns, so that the columns
-                * don't reflect the packet that got the error,
-                * they reflect the packet that reported the
-                * error.
+                * That dissector didn't accept the packet, so
+                * remove its protocol's name from the list
+                * of protocols.
                 */
-               save_writable = col_get_writable(pinfo->cinfo);
-               col_set_writable(pinfo->cinfo, FALSE);
-               save_dl_src = pinfo->dl_src;
-               save_dl_dst = pinfo->dl_dst;
-               save_net_src = pinfo->net_src;
-               save_net_dst = pinfo->net_dst;
-               save_src = pinfo->src;
-               save_dst = pinfo->dst;
-
-               /* Dissect the contained packet. */
-               TRY {
-                       ret = call_dissector_through_handle(handle, tvb,
-                           pinfo, tree);
+               if ((pinfo->layer_names != NULL)&&(add_proto_name)) {
+                       g_string_truncate(pinfo->layer_names, saved_layer_names_len);
                }
-               CATCH(BoundsError) {
-                       /*
-                        * Restore the column writability and addresses.
-                        */
-                       col_set_writable(pinfo->cinfo, save_writable);
-                       pinfo->dl_src = save_dl_src;
-                       pinfo->dl_dst = save_dl_dst;
-                       pinfo->net_src = save_net_src;
-                       pinfo->net_dst = save_net_dst;
-                       pinfo->src = save_src;
-                       pinfo->dst = save_dst;
+       }
+       pinfo->current_proto = saved_proto;
+       pinfo->can_desegment = saved_can_desegment;
+       return ret;
+}
 
-                       /*
-                        * Restore the current protocol, so any
-                        * "Short Frame" indication reflects that
-                        * protocol, not the protocol for the
-                        * packet that got the error.
-                        */
-                       pinfo->current_proto = saved_proto;
 
-                       /*
-                        * Restore the desegmentability state.
-                        */
-                       pinfo->can_desegment = saved_can_desegment;
+static int
+call_dissector_work_error(dissector_handle_t handle, tvbuff_t *tvb,
+                         packet_info *pinfo_arg, proto_tree *tree, void *data)
+{
+       packet_info  *pinfo = pinfo_arg;
+       const char   *saved_proto;
+       guint16       saved_can_desegment;
+       volatile int  ret = 0;
+       gboolean      save_writable;
+       address       save_dl_src;
+       address       save_dl_dst;
+       address       save_net_src;
+       address       save_net_dst;
+       address       save_src;
+       address       save_dst;
 
-                       /*
-                        * Rethrow the exception, so this will be
-                        * reported as a short frame.
-                        */
-                       RETHROW;
-               }
-               CATCH(ReportedBoundsError) {
-                       /*
-                        * "ret" wasn't set because an exception was thrown
-                        * before "call_dissector_through_handle()" returned.
-                        * As it called something, at least one dissector
-                        * accepted the packet, and, as an exception was
-                        * thrown, not only was all the tvbuff dissected,
-                        * a dissector tried dissecting past the end of
-                        * the data in some tvbuff, so we'll assume that
-                        * the entire tvbuff was dissected.
-                        */
-                       ret = tvb_length(tvb);
-               }
-               ENDTRY;
+       /*
+       * This isn't a packet being transported inside
+       * the protocol whose dissector is calling us,
+       * it's a copy of a packet that caused an error
+       * in some protocol included in a packet that
+       * reports the error (e.g., an ICMP Unreachable
+       * packet).
+       */
+
+       /*
+       * Save the current state of the writability of
+       * the columns, and restore them after the
+       * dissector returns, so that the columns
+       * don't reflect the packet that got the error,
+       * they reflect the packet that reported the
+       * error.
+       */
+       saved_proto = pinfo->current_proto;
+       saved_can_desegment = pinfo->can_desegment;
+
+       save_writable = col_get_writable(pinfo->cinfo);
+       col_set_writable(pinfo->cinfo, FALSE);
+       save_dl_src   = pinfo->dl_src;
+       save_dl_dst   = pinfo->dl_dst;
+       save_net_src  = pinfo->net_src;
+       save_net_dst  = pinfo->net_dst;
+       save_src      = pinfo->src;
+       save_dst      = pinfo->dst;
 
+       /* Dissect the contained packet. */
+       TRY {
+               ret = call_dissector_through_handle(handle, tvb,pinfo, tree, data);
+       }
+       CATCH(BoundsError) {
+               /*
+               * Restore the column writability and addresses.
+               */
                col_set_writable(pinfo->cinfo, save_writable);
-               pinfo->dl_src = save_dl_src;
-               pinfo->dl_dst = save_dl_dst;
+               pinfo->dl_src  = save_dl_src;
+               pinfo->dl_dst  = save_dl_dst;
                pinfo->net_src = save_net_src;
                pinfo->net_dst = save_net_dst;
-               pinfo->src = save_src;
-               pinfo->dst = save_dst;
-               pinfo->want_pdu_tracking = 0;
-       } else {
+               pinfo->src     = save_src;
+               pinfo->dst     = save_dst;
+
                /*
-                * Just call the subdissector.
-                */
-               ret = call_dissector_through_handle(handle, tvb, pinfo, tree);
-       }
+               * Restore the current protocol, so any
+               * "Short Frame" indication reflects that
+               * protocol, not the protocol for the
+               * packet that got the error.
+               */
+               pinfo->current_proto = saved_proto;
 
-       if (ret == 0) {
                /*
-                * That dissector didn't accept the packet, so
-                * remove its protocol's name from the list
-                * of protocols.
-                */
-               if (pinfo->layer_names != NULL) {
-                       g_string_truncate(pinfo->layer_names,
-                           saved_layer_names_len);
-               }
+               * Restore the desegmentability state.
+               */
+               pinfo->can_desegment = saved_can_desegment;
+
+               /*
+               * Rethrow the exception, so this will be
+               * reported as a short frame.
+               */
+               RETHROW;
        }
-       pinfo->current_proto = saved_proto;
-       pinfo->can_desegment = saved_can_desegment;
+       CATCH(ReportedBoundsError) {
+               /*
+               * "ret" wasn't set because an exception was thrown
+               * before "call_dissector_through_handle()" returned.
+               * As it called something, at least one dissector
+               * accepted the packet, and, as an exception was
+               * thrown, not only was all the tvbuff dissected,
+               * a dissector tried dissecting past the end of
+               * the data in some tvbuff, so we'll assume that
+               * the entire tvbuff was dissected.
+               */
+               ret = tvb_length(tvb);
+       }
+       CATCH(OutOfMemoryError) {
+               RETHROW;
+       }
+       ENDTRY;
+
+       col_set_writable(pinfo->cinfo, save_writable);
+       pinfo->dl_src  = save_dl_src;
+       pinfo->dl_dst  = save_dl_dst;
+       pinfo->net_src = save_net_src;
+       pinfo->net_dst = save_net_dst;
+       pinfo->src     = save_src;
+       pinfo->dst     = save_dst;
+       pinfo->want_pdu_tracking = 0;
        return ret;
 }
 
@@ -590,19 +682,21 @@ struct dtbl_entry {
  *
  * "hash_table" is a hash table, indexed by port number, supplying
  * a "struct dtbl_entry"; it records what dissector is assigned to
- * that port number in that table.
+ * that uint or string value in that table.
  *
  * "dissector_handles" is a list of all dissectors that *could* be
  * used in that table; not all of them are necessarily in the table,
- * as they may be for protocols that don't have a fixed port number.
+ * as they may be for protocols that don't have a fixed uint value,
+ * e.g. for TCP or UDP port number tables and protocols with no fixed
+ * port number.
  *
  * "ui_name" is the name the dissector table has in the user interface.
  *
- * "type" is a field type giving the width of the port number for that
- * dissector table.
+ * "type" is a field type giving the width of the uint value for that
+ * dissector table, if it's a uint dissector table.
  *
- * "base" is the base in which to display the port number for that
- * dissector table.
+ * "base" is the base in which to display the uint value for that
+ * dissector table, if it's a uint dissector table.
  */
 struct dissector_table {
        GHashTable      *hash_table;
@@ -624,7 +718,7 @@ find_dissector_table(const char *name)
 
 /* Find an entry in a uint dissector table. */
 static dtbl_entry_t *
-find_uint_dtbl_entry(dissector_table_t sub_dissectors, guint32 pattern)
+find_uint_dtbl_entry(dissector_table_t sub_dissectors, const guint32 pattern)
 {
        switch (sub_dissectors->type) {
 
@@ -633,13 +727,13 @@ find_uint_dtbl_entry(dissector_table_t sub_dissectors, guint32 pattern)
        case FT_UINT24:
        case FT_UINT32:
                /*
-                * You can do a port lookup in these tables.
+                * You can do a uint lookup in these tables.
                 */
                break;
 
        default:
                /*
-                * But you can't do a port lookup in any other types
+                * But you can't do a uint lookup in any other types
                 * of tables.
                 */
                g_assert_not_reached();
@@ -649,18 +743,53 @@ find_uint_dtbl_entry(dissector_table_t sub_dissectors, guint32 pattern)
         * Find the entry.
         */
        return g_hash_table_lookup(sub_dissectors->hash_table,
-           GUINT_TO_POINTER(pattern));
+                                  GUINT_TO_POINTER(pattern));
 }
 
+#if 0
+static void
+dissector_add_uint_sanity_check(const char *name, guint32 pattern, dissector_handle_t handle, dissector_table_t sub_dissectors)
+{
+       dtbl_entry_t *dtbl_entry;
+
+       if (pattern == 0) {
+               g_warning("%s: %s registering using a pattern of 0",
+                         name, proto_get_protocol_filter_name(proto_get_id(handle->protocol)));
+       }
+
+       dtbl_entry = g_hash_table_lookup(sub_dissectors->hash_table, GUINT_TO_POINTER(pattern));
+       if (dtbl_entry != NULL) {
+               g_warning("%s: %s registering using pattern %d already registered by %s",
+                         name, proto_get_protocol_filter_name(proto_get_id(handle->protocol)),
+                         pattern, proto_get_protocol_filter_name(proto_get_id(dtbl_entry->initial->protocol)));
+       }
+}
+#endif
+
 /* Add an entry to a uint dissector table. */
 void
-dissector_add(const char *name, guint32 pattern, dissector_handle_t handle)
+dissector_add_uint(const char *name, const guint32 pattern, dissector_handle_t handle)
 {
-       dissector_table_t sub_dissectors = find_dissector_table( name);
-       dtbl_entry_t *dtbl_entry;
+       dissector_table_t  sub_dissectors;
+       dtbl_entry_t      *dtbl_entry;
 
-/* sanity checks */
-       g_assert( sub_dissectors);
+       sub_dissectors = find_dissector_table(name);
+
+       /*
+        * Make sure the dissector table exists.
+        */
+       if (sub_dissectors == NULL) {
+               fprintf(stderr, "OOPS: dissector table \"%s\" doesn't exist\n",
+                   name);
+               fprintf(stderr, "Protocol being registered is \"%s\"\n",
+                   proto_get_protocol_long_name(handle->protocol));
+               if (getenv("WIRESHARK_ABORT_ON_DISSECTOR_BUG") != NULL)
+                       abort();
+               return;
+       }
+
+       /* sanity checks */
+       g_assert(handle!=NULL);
        switch (sub_dissectors->type) {
 
        case FT_UINT8:
@@ -668,25 +797,29 @@ dissector_add(const char *name, guint32 pattern, dissector_handle_t handle)
        case FT_UINT24:
        case FT_UINT32:
                /*
-                * You can do a port lookup in these tables.
+                * You can do a uint lookup in these tables.
                 */
                break;
 
        default:
                /*
-                * But you can't do a port lookup in any other types
+                * But you can't do a uint lookup in any other types
                 * of tables.
                 */
                g_assert_not_reached();
        }
 
+#if 0
+       dissector_add_uint_sanity_check(name, pattern, handle, sub_dissectors);
+#endif
+
        dtbl_entry = g_malloc(sizeof (dtbl_entry_t));
        dtbl_entry->current = handle;
        dtbl_entry->initial = dtbl_entry->current;
 
-/* do the table insertion */
-       g_hash_table_insert( sub_dissectors->hash_table,
-           GUINT_TO_POINTER( pattern), (gpointer)dtbl_entry);
+       /* do the table insertion */
+       g_hash_table_insert( sub_dissectors->hash_table,
+                            GUINT_TO_POINTER( pattern), (gpointer)dtbl_entry);
 
        /*
         * Now add it to the list of handles that could be used with this
@@ -699,18 +832,18 @@ dissector_add(const char *name, guint32 pattern, dissector_handle_t handle)
    with a particular pattern. */
 
 /* NOTE: this doesn't use the dissector call variable. It is included to */
-/*     be consistant with the dissector_add and more importantly to be used */
+/*     be consistant with the dissector_add_uint and more importantly to be used */
 /*     if the technique of adding a temporary dissector is implemented.  */
 /*     If temporary dissectors are deleted, then the original dissector must */
 /*     be available. */
 void
-dissector_delete(const char *name, guint32 pattern,
+dissector_delete_uint(const char *name, const guint32 pattern,
        dissector_handle_t handle _U_)
 {
        dissector_table_t sub_dissectors = find_dissector_table( name);
        dtbl_entry_t *dtbl_entry;
 
-/* sanity check */
+       /* sanity check */
        g_assert( sub_dissectors);
 
        /*
@@ -723,24 +856,19 @@ dissector_delete(const char *name, guint32 pattern,
                 * Found - remove it.
                 */
                g_hash_table_remove(sub_dissectors->hash_table,
-                   GUINT_TO_POINTER(pattern));
-
-               /*
-                * Now free up the entry.
-                */
-               g_free(dtbl_entry);
+                                   GUINT_TO_POINTER(pattern));
        }
 }
 
 /* Change the entry for a dissector in a uint dissector table
    with a particular pattern to use a new dissector handle. */
 void
-dissector_change(const char *name, guint32 pattern, dissector_handle_t handle)
+dissector_change_uint(const char *name, const guint32 pattern, dissector_handle_t handle)
 {
        dissector_table_t sub_dissectors = find_dissector_table( name);
        dtbl_entry_t *dtbl_entry;
 
-/* sanity check */
+       /* sanity check */
        g_assert( sub_dissectors);
 
        /*
@@ -748,8 +876,8 @@ dissector_change(const char *name, guint32 pattern, dissector_handle_t handle)
         */
        dtbl_entry = find_uint_dtbl_entry(sub_dissectors, pattern);
        if (dtbl_entry != NULL) {
-         dtbl_entry->current = handle;
-         return;
+               dtbl_entry->current = handle;
+               return;
        }
 
        /*
@@ -758,25 +886,25 @@ dissector_change(const char *name, guint32 pattern, dissector_handle_t handle)
         * in the first place.
         */
        if (handle == NULL)
-         return;
+               return;
 
        dtbl_entry = g_malloc(sizeof (dtbl_entry_t));
        dtbl_entry->initial = NULL;
        dtbl_entry->current = handle;
 
-/* do the table insertion */
-       g_hash_table_insert( sub_dissectors->hash_table,
-           GUINT_TO_POINTER( pattern), (gpointer)dtbl_entry);
+       /* do the table insertion */
+       g_hash_table_insert( sub_dissectors->hash_table,
+                            GUINT_TO_POINTER( pattern), (gpointer)dtbl_entry);
 }
 
 /* Reset an entry in a uint dissector table to its initial value. */
 void
-dissector_reset(const char *name, guint32 pattern)
+dissector_reset_uint(const char *name, const guint32 pattern)
 {
-       dissector_table_t sub_dissectors = find_dissector_table( name);
-       dtbl_entry_t *dtbl_entry;
+       dissector_table_t  sub_dissectors = find_dissector_table( name);
+       dtbl_entry_t      *dtbl_entry;
 
-/* sanity check */
+       /* sanity check */
        g_assert( sub_dissectors);
 
        /*
@@ -794,24 +922,25 @@ dissector_reset(const char *name, guint32 pattern)
                dtbl_entry->current = dtbl_entry->initial;
        } else {
                g_hash_table_remove(sub_dissectors->hash_table,
-                   GUINT_TO_POINTER(pattern));
-               g_free(dtbl_entry);
+                                   GUINT_TO_POINTER(pattern));
        }
 }
 
 /* Look for a given value in a given uint dissector table and, if found,
    call the dissector with the arguments supplied, and return TRUE,
    otherwise return FALSE. */
+
 gboolean
-dissector_try_port(dissector_table_t sub_dissectors, guint32 port,
-    tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
+dissector_try_uint_new(dissector_table_t sub_dissectors, const guint32 uint_val,
+                      tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree,
+                      const gboolean add_proto_name, void *data)
 {
-       dtbl_entry_t *dtbl_entry;
+       dtbl_entry_t            *dtbl_entry;
        struct dissector_handle *handle;
-       guint32 saved_match_port;
+       guint32                  saved_match_uint;
        int ret;
 
-       dtbl_entry = find_uint_dtbl_entry(sub_dissectors, port);
+       dtbl_entry = find_uint_dtbl_entry(sub_dissectors, uint_val);
        if (dtbl_entry != NULL) {
                /*
                 * Is there currently a dissector handle for this entry?
@@ -827,14 +956,14 @@ dissector_try_port(dissector_table_t sub_dissectors, guint32 port,
                }
 
                /*
-                * Save the current value of "pinfo->match_port",
-                * set it to the port that matched, call the
-                * dissector, and restore "pinfo->match_port".
+                * Save the current value of "pinfo->match_uint",
+                * set it to the uint_val that matched, call the
+                * dissector, and restore "pinfo->match_uint".
                 */
-               saved_match_port = pinfo->match_port;
-               pinfo->match_port = port;
-               ret = call_dissector_work(handle, tvb, pinfo, tree);
-               pinfo->match_port = saved_match_port;
+               saved_match_uint  = pinfo->match_uint;
+               pinfo->match_uint = uint_val;
+               ret = call_dissector_work(handle, tvb, pinfo, tree, add_proto_name, data);
+               pinfo->match_uint = saved_match_uint;
 
                /*
                 * If a new-style dissector returned 0, it means that
@@ -854,14 +983,22 @@ dissector_try_port(dissector_table_t sub_dissectors, guint32 port,
        return FALSE;
 }
 
+gboolean
+dissector_try_uint(dissector_table_t sub_dissectors, const guint32 uint_val,
+                  tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
+{
+
+       return dissector_try_uint_new(sub_dissectors, uint_val, tvb, pinfo, tree, TRUE, NULL);
+}
+
 /* Look for a given value in a given uint dissector table and, if found,
    return the dissector handle for that value. */
 dissector_handle_t
-dissector_get_port_handle(dissector_table_t sub_dissectors, guint32 port)
+dissector_get_uint_handle(dissector_table_t const sub_dissectors, const guint32 uint_val)
 {
        dtbl_entry_t *dtbl_entry;
 
-       dtbl_entry = find_uint_dtbl_entry(sub_dissectors, port);
+       dtbl_entry = find_uint_dtbl_entry(sub_dissectors, uint_val);
        if (dtbl_entry != NULL)
                return dtbl_entry->current;
        else
@@ -870,7 +1007,7 @@ dissector_get_port_handle(dissector_table_t sub_dissectors, guint32 port)
 
 /* Find an entry in a string dissector table. */
 static dtbl_entry_t *
-find_string_dtbl_entry(dissector_table_t sub_dissectors, const gchar *pattern)
+find_string_dtbl_entry(dissector_table_t const sub_dissectors, const gchar *pattern)
 {
        switch (sub_dissectors->type) {
 
@@ -898,14 +1035,26 @@ find_string_dtbl_entry(dissector_table_t sub_dissectors, const gchar *pattern)
 /* Add an entry to a string dissector table. */
 void
 dissector_add_string(const char *name, const gchar *pattern,
-    dissector_handle_t handle)
+                    dissector_handle_t handle)
 {
-       dissector_table_t sub_dissectors = find_dissector_table( name);
-       dtbl_entry_t *dtbl_entry;
+       dissector_table_t  sub_dissectors = find_dissector_table( name);
+       dtbl_entry_t      *dtbl_entry;
 
-/* sanity check */
-       g_assert( sub_dissectors);
+       /*
+        * Make sure the dissector table exists.
+        */
+       if (sub_dissectors == NULL) {
+               fprintf(stderr, "OOPS: dissector table \"%s\" doesn't exist\n",
+                   name);
+               fprintf(stderr, "Protocol being registered is \"%s\"\n",
+                   proto_get_protocol_long_name(handle->protocol));
+               if (getenv("WIRESHARK_ABORT_ON_DISSECTOR_BUG") != NULL)
+                       abort();
+               return;
+       }
 
+       /* sanity checks */
+       g_assert(handle!=NULL);
        switch (sub_dissectors->type) {
 
        case FT_STRING:
@@ -927,9 +1076,9 @@ dissector_add_string(const char *name, const gchar *pattern,
        dtbl_entry->current = handle;
        dtbl_entry->initial = dtbl_entry->current;
 
-/* do the table insertion */
-       g_hash_table_insert( sub_dissectors->hash_table, (gpointer)pattern,
-           (gpointer)dtbl_entry);
+       /* do the table insertion */
+       g_hash_table_insert( sub_dissectors->hash_table, (gpointer)pattern,
+                            (gpointer)dtbl_entry);
 
        /*
         * Now add it to the list of handles that could be used with this
@@ -951,10 +1100,10 @@ void
 dissector_delete_string(const char *name, const gchar *pattern,
        dissector_handle_t handle _U_)
 {
-       dissector_table_t sub_dissectors = find_dissector_table( name);
-       dtbl_entry_t *dtbl_entry;
+       dissector_table_t  sub_dissectors = find_dissector_table( name);
+       dtbl_entry_t      *dtbl_entry;
 
-/* sanity check */
+       /* sanity check */
        g_assert( sub_dissectors);
 
        /*
@@ -967,24 +1116,19 @@ dissector_delete_string(const char *name, const gchar *pattern,
                 * Found - remove it.
                 */
                g_hash_table_remove(sub_dissectors->hash_table, pattern);
-
-               /*
-                * Now free up the entry.
-                */
-               g_free(dtbl_entry);
        }
 }
 
 /* Change the entry for a dissector in a string dissector table
    with a particular pattern to use a new dissector handle. */
 void
-dissector_change_string(const char *name, gchar *pattern,
-    dissector_handle_t handle)
+dissector_change_string(const char *name, const gchar *pattern,
+                       dissector_handle_t handle)
 {
-       dissector_table_t sub_dissectors = find_dissector_table( name);
-       dtbl_entry_t *dtbl_entry;
+       dissector_table_t  sub_dissectors = find_dissector_table( name);
+       dtbl_entry_t      *dtbl_entry;
 
-/* sanity check */
+       /* sanity check */
        g_assert( sub_dissectors);
 
        /*
@@ -992,8 +1136,8 @@ dissector_change_string(const char *name, gchar *pattern,
         */
        dtbl_entry = find_string_dtbl_entry(sub_dissectors, pattern);
        if (dtbl_entry != NULL) {
-         dtbl_entry->current = handle;
-         return;
+               dtbl_entry->current = handle;
+               return;
        }
 
        /*
@@ -1002,25 +1146,25 @@ dissector_change_string(const char *name, gchar *pattern,
         * in the first place.
         */
        if (handle == NULL)
-         return;
+               return;
 
        dtbl_entry = g_malloc(sizeof (dtbl_entry_t));
        dtbl_entry->initial = NULL;
        dtbl_entry->current = handle;
 
-/* do the table insertion */
-       g_hash_table_insert( sub_dissectors->hash_table, pattern,
-           (gpointer)dtbl_entry);
+       /* do the table insertion */
+       g_hash_table_insert( sub_dissectors->hash_table, (gpointer)pattern,
+                            (gpointer)dtbl_entry);
 }
 
 /* Reset an entry in a string sub-dissector table to its initial value. */
 void
 dissector_reset_string(const char *name, const gchar *pattern)
 {
-       dissector_table_t sub_dissectors = find_dissector_table( name);
-       dtbl_entry_t *dtbl_entry;
+       dissector_table_t  sub_dissectors = find_dissector_table( name);
+       dtbl_entry_t      *dtbl_entry;
 
-/* sanity check */
+       /* sanity check */
        g_assert( sub_dissectors);
 
        /*
@@ -1038,7 +1182,6 @@ dissector_reset_string(const char *name, const gchar *pattern)
                dtbl_entry->current = dtbl_entry->initial;
        } else {
                g_hash_table_remove(sub_dissectors->hash_table, pattern);
-               g_free(dtbl_entry);
        }
 }
 
@@ -1047,13 +1190,15 @@ dissector_reset_string(const char *name, const gchar *pattern)
    return FALSE. */
 gboolean
 dissector_try_string(dissector_table_t sub_dissectors, const gchar *string,
-    tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
+                    tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
 {
-       dtbl_entry_t *dtbl_entry;
+       dtbl_entry_t            *dtbl_entry;
        struct dissector_handle *handle;
-       int ret;
-       const gchar *saved_match_string;
+       int                      ret;
+       const gchar             *saved_match_string;
 
+       /* XXX ASSERT instead ? */
+       if (!string) return FALSE;
        dtbl_entry = find_string_dtbl_entry(sub_dissectors, string);
        if (dtbl_entry != NULL) {
                /*
@@ -1076,7 +1221,7 @@ dissector_try_string(dissector_table_t sub_dissectors, const gchar *string,
                 */
                saved_match_string = pinfo->match_string;
                pinfo->match_string = string;
-               ret = call_dissector_work(handle, tvb, pinfo, tree);
+               ret = call_dissector_work(handle, tvb, pinfo, tree, TRUE, NULL);
                pinfo->match_string = saved_match_string;
 
                /*
@@ -1101,7 +1246,7 @@ dissector_try_string(dissector_table_t sub_dissectors, const gchar *string,
    return the dissector handle for that value. */
 dissector_handle_t
 dissector_get_string_handle(dissector_table_t sub_dissectors,
-    const gchar *string)
+                           const gchar *string)
 {
        dtbl_entry_t *dtbl_entry;
 
@@ -1118,16 +1263,48 @@ dtbl_entry_get_handle (dtbl_entry_t *dtbl_entry)
        return dtbl_entry->current;
 }
 
+gint
+dissector_compare_filter_name(gconstpointer dissector_a, gconstpointer dissector_b)
+{
+       dissector_handle_t a = (dissector_handle_t)dissector_a;
+       dissector_handle_t b = (dissector_handle_t)dissector_b;
+       const char *a_name, *b_name;
+       gint ret;
+
+       if (a->protocol == NULL)
+               a_name = "";
+       else
+               a_name = proto_get_protocol_filter_name(proto_get_id(a->protocol));
+
+       if (b->protocol == NULL)
+               b_name = "";
+       else
+               b_name = proto_get_protocol_filter_name(proto_get_id(b->protocol));
+
+       ret = strcmp(a_name, b_name);
+       return ret;
+}
+
 /* Add a handle to the list of handles that *could* be used with this
    table.  That list is used by code in the UI. */
 void
 dissector_add_handle(const char *name, dissector_handle_t handle)
 {
-       dissector_table_t sub_dissectors = find_dissector_table( name);
-       GSList *entry;
+       dissector_table_t  sub_dissectors = find_dissector_table( name);
+       GSList            *entry;
 
-       /* sanity check */
-       g_assert(sub_dissectors != NULL);
+       /*
+        * Make sure the dissector table exists.
+        */
+       if (sub_dissectors == NULL) {
+               fprintf(stderr, "OOPS: dissector table \"%s\" doesn't exist\n",
+                   name);
+               fprintf(stderr, "Protocol being registered is \"%s\"\n",
+                   proto_get_protocol_long_name(handle->protocol));
+               if (getenv("WIRESHARK_ABORT_ON_DISSECTOR_BUG") != NULL)
+                       abort();
+               return;
+       }
 
        /* Is it already in this list? */
        entry = g_slist_find(sub_dissectors->dissector_handles, (gpointer)handle);
@@ -1140,7 +1317,7 @@ dissector_add_handle(const char *name, dissector_handle_t handle)
 
        /* Add it to the list. */
        sub_dissectors->dissector_handles =
-           g_slist_append(sub_dissectors->dissector_handles, (gpointer)handle);
+               g_slist_insert_sorted(sub_dissectors->dissector_handles, (gpointer)handle, (GCompareFunc)dissector_compare_filter_name);
 }
 
 dissector_handle_t
@@ -1156,11 +1333,11 @@ dtbl_entry_get_initial_handle (dtbl_entry_t *dtbl_entry)
 /**************************************************/
 
 typedef struct dissector_foreach_info {
-  gpointer     caller_data;
-  DATFunc      caller_func;
-  GHFunc       next_func;
-  gchar       *table_name;
-  ftenum_t     selector_type;
+       gpointer      caller_data;
+       DATFunc       caller_func;
+       GHFunc        next_func;
+       const gchar  *table_name;
+       ftenum_t      selector_type;
 } dissector_foreach_info_t;
 
 /*
@@ -1170,7 +1347,7 @@ static void
 dissector_table_foreach_func (gpointer key, gpointer value, gpointer user_data)
 {
        dissector_foreach_info_t *info;
-       dtbl_entry_t *dtbl_entry;
+       dtbl_entry_t             *dtbl_entry;
 
        g_assert(value);
        g_assert(user_data);
@@ -1190,7 +1367,7 @@ dissector_table_foreach_func (gpointer key, gpointer value, gpointer user_data)
 
        info = user_data;
        info->caller_func(info->table_name, info->selector_type, key, value,
-           info->caller_data);
+                         info->caller_data);
 }
 
 /*
@@ -1199,7 +1376,7 @@ dissector_table_foreach_func (gpointer key, gpointer value, gpointer user_data)
 static void
 dissector_all_tables_foreach_func (gpointer key, gpointer value, gpointer user_data)
 {
-       dissector_table_t sub_dissectors;
+       dissector_table_t         sub_dissectors;
        dissector_foreach_info_t *info;
 
        g_assert(value);
@@ -1224,7 +1401,7 @@ dissector_all_tables_foreach (DATFunc func,
 
        info.caller_data = user_data;
        info.caller_func = func;
-       info.next_func = dissector_table_foreach_func;
+       info.next_func   = dissector_table_foreach_func;
        g_hash_table_foreach(dissector_tables, dissector_all_tables_foreach_func, &info);
 }
 
@@ -1233,17 +1410,17 @@ dissector_all_tables_foreach (DATFunc func,
  * on each entry.
  */
 void
-dissector_table_foreach (char *name,
-                        DATFunc func,
-                        gpointer user_data)
+dissector_table_foreach (const char *name,
+                        DATFunc     func,
+                        gpointer    user_data)
 {
        dissector_foreach_info_t info;
-       dissector_table_t sub_dissectors = find_dissector_table( name);
+       dissector_table_t        sub_dissectors = find_dissector_table( name);
 
-       info.table_name = name;
+       info.table_name    = name;
        info.selector_type = sub_dissectors->type;
-       info.caller_func = func;
-       info.caller_data = user_data;
+       info.caller_func   = func;
+       info.caller_data   = user_data;
        g_hash_table_foreach(sub_dissectors->hash_table, dissector_table_foreach_func, &info);
 }
 
@@ -1252,15 +1429,15 @@ dissector_table_foreach (char *name,
  * function on each entry.
  */
 void
-dissector_table_foreach_handle(const char *name,
-                              DATFunc_handle func,
-                              gpointer user_data)
+dissector_table_foreach_handle(const char     *name,
+                              DATFunc_handle  func,
+                              gpointer        user_data)
 {
        dissector_table_t sub_dissectors = find_dissector_table( name);
        GSList *tmp;
 
        for (tmp = sub_dissectors->dissector_handles; tmp != NULL;
-           tmp = g_slist_next(tmp))
+            tmp = g_slist_next(tmp))
                func(name, tmp->data, user_data);
 }
 
@@ -1270,7 +1447,7 @@ dissector_table_foreach_handle(const char *name,
 static void
 dissector_table_foreach_changed_func (gpointer key, gpointer value, gpointer user_data)
 {
-       dtbl_entry_t *dtbl_entry;
+       dtbl_entry_t             *dtbl_entry;
        dissector_foreach_info_t *info;
 
        g_assert(value);
@@ -1286,7 +1463,7 @@ dissector_table_foreach_changed_func (gpointer key, gpointer value, gpointer use
 
        info = user_data;
        info->caller_func(info->table_name, info->selector_type, key, value,
-           info->caller_data);
+                         info->caller_data);
 }
 
 /*
@@ -1294,14 +1471,14 @@ dissector_table_foreach_changed_func (gpointer key, gpointer value, gpointer use
  * any entry that has been changed from its original state.
  */
 void
-dissector_all_tables_foreach_changed (DATFunc func,
+dissector_all_tables_foreach_changed (DATFunc  func,
                                      gpointer user_data)
 {
        dissector_foreach_info_t info;
 
        info.caller_data = user_data;
        info.caller_func = func;
-       info.next_func = dissector_table_foreach_changed_func;
+       info.next_func   = dissector_table_foreach_changed_func;
        g_hash_table_foreach(dissector_tables, dissector_all_tables_foreach_func, &info);
 }
 
@@ -1310,33 +1487,33 @@ dissector_all_tables_foreach_changed (DATFunc func,
  * any entry that has been changed from its original state.
  */
 void
-dissector_table_foreach_changed (char *name,
-                                DATFunc func,
-                                gpointer user_data)
+dissector_table_foreach_changed (const char *name,
+                                DATFunc     func,
+                                gpointer    user_data)
 {
        dissector_foreach_info_t info;
        dissector_table_t sub_dissectors = find_dissector_table( name);
 
-       info.table_name = name;
+       info.table_name    = name;
        info.selector_type = sub_dissectors->type;
-       info.caller_func = func;
-       info.caller_data = user_data;
+       info.caller_func   = func;
+       info.caller_data   = user_data;
        g_hash_table_foreach(sub_dissectors->hash_table,
-           dissector_table_foreach_changed_func, &info);
+                            dissector_table_foreach_changed_func, &info);
 }
 
 typedef struct dissector_foreach_table_info {
-  gpointer      caller_data;
-  DATFunc_table caller_func;
+       gpointer      caller_data;
+       DATFunc_table caller_func;
 } dissector_foreach_table_info_t;
 
 /*
  * Called for each entry in the table of all dissector tables.
  */
 static void
-dissector_all_tables_foreach_table_func (gpointer key, gpointer value, gpointer user_data)
+dissector_all_tables_foreach_table_func (gpointer key, const gpointer value, const gpointer user_data)
 {
-       dissector_table_t table;
+       dissector_table_t               table;
        dissector_foreach_table_info_t *info;
 
        table = value;
@@ -1344,24 +1521,50 @@ dissector_all_tables_foreach_table_func (gpointer key, gpointer value, gpointer
        (*info->caller_func)((gchar*)key, table->ui_name, info->caller_data);
 }
 
+/*
+ * Called for each key in the table of all dissector tables.
+ */
+static void
+dissector_all_tables_foreach_list_func (gpointer key, gpointer user_data)
+{
+       dissector_table_t               table;
+       dissector_foreach_table_info_t *info;
+
+       table = g_hash_table_lookup( dissector_tables, key );
+       info = user_data;
+       (*info->caller_func)((gchar*)key, table->ui_name, info->caller_data);
+}
+
 /*
  * Walk all dissector tables calling a user supplied function on each
  * table.
  */
 void
 dissector_all_tables_foreach_table (DATFunc_table func,
-                                   gpointer user_data)
+                                       gpointer      user_data,
+                                       GCompareFunc compare_key_func)
 {
        dissector_foreach_table_info_t info;
+       GList* list;
 
        info.caller_data = user_data;
        info.caller_func = func;
-       g_hash_table_foreach(dissector_tables, dissector_all_tables_foreach_table_func, &info);
+       if (compare_key_func != NULL)
+       {
+               list = g_hash_table_get_keys(dissector_tables);
+               list = g_list_sort(list, compare_key_func);
+               g_list_foreach(list, dissector_all_tables_foreach_list_func, &info);
+               g_list_free(list);
+       }
+       else
+       {
+               g_hash_table_foreach(dissector_tables, dissector_all_tables_foreach_table_func, &info);
+       }
 }
 
 dissector_table_t
-register_dissector_table(const char *name, const char *ui_name, ftenum_t type,
-    int base)
+register_dissector_table(const char *name, const char *ui_name, const ftenum_t type,
+                        const int base)
 {
        dissector_table_t       sub_dissectors;
 
@@ -1372,7 +1575,9 @@ register_dissector_table(const char *name, const char *ui_name, ftenum_t type,
        }
 
        /* Make sure the registration is unique */
-       g_assert(!g_hash_table_lookup( dissector_tables, name ));
+       if(g_hash_table_lookup( dissector_tables, name )) {
+               g_error("The filter name %s (%s) is already registered - do you use a buggy plugin?", name, ui_name);
+       }
 
        /* Create and register the dissector table for this name; returns */
        /* a pointer to the dissector table. */
@@ -1387,14 +1592,18 @@ register_dissector_table(const char *name, const char *ui_name, ftenum_t type,
                 * XXX - there's no "g_uint_hash()" or "g_uint_equal()",
                 * so we use "g_direct_hash()" and "g_direct_equal()".
                 */
-               sub_dissectors->hash_table = g_hash_table_new( g_direct_hash,
-                   g_direct_equal );
+               sub_dissectors->hash_table = g_hash_table_new_full( g_direct_hash,
+                                                              g_direct_equal,
+                                                              NULL,
+                                                              &g_free );
                break;
 
        case FT_STRING:
        case FT_STRINGZ:
-               sub_dissectors->hash_table = g_hash_table_new( g_str_hash,
-                   g_str_equal );
+               sub_dissectors->hash_table = g_hash_table_new_full( g_str_hash,
+                                                              g_str_equal,
+                                                              NULL,
+                                                              &g_free );
                break;
 
        default:
@@ -1402,8 +1611,8 @@ register_dissector_table(const char *name, const char *ui_name, ftenum_t type,
        }
        sub_dissectors->dissector_handles = NULL;
        sub_dissectors->ui_name = ui_name;
-       sub_dissectors->type = type;
-       sub_dissectors->base = base;
+       sub_dissectors->type    = type;
+       sub_dissectors->base    = base;
        g_hash_table_insert( dissector_tables, (gpointer)name, (gpointer) sub_dissectors );
        return sub_dissectors;
 }
@@ -1434,12 +1643,8 @@ get_dissector_table_base(const char *name)
 
 static GHashTable *heur_dissector_lists = NULL;
 
-typedef struct {
-       heur_dissector_t dissector;
-       protocol_t *protocol;
-} heur_dtbl_entry_t;
 
-/* Finds a heuristic dissector table by field name. */
+/* Finds a heuristic dissector table by table name. */
 static heur_dissector_list_t *
 find_heur_dissector_list(const char *name)
 {
@@ -1448,32 +1653,103 @@ find_heur_dissector_list(const char *name)
 }
 
 void
-heur_dissector_add(const char *name, heur_dissector_t dissector, int proto)
+heur_dissector_add(const char *name, heur_dissector_t dissector, const int proto)
 {
        heur_dissector_list_t *sub_dissectors = find_heur_dissector_list(name);
-       heur_dtbl_entry_t *dtbl_entry;
+       const char            *proto_name;
+       heur_dtbl_entry_t     *hdtbl_entry;
+
+       /*
+        * Make sure the dissector table exists.
+        */
+       if (sub_dissectors == NULL) {
+               fprintf(stderr, "OOPS: dissector table \"%s\" doesn't exist\n",
+                   name);
+               proto_name = proto_get_protocol_name(proto);
+               if (proto_name != NULL) {
+                       fprintf(stderr, "Protocol being registered is \"%s\"\n",
+                           proto_name);
+               }
+               if (getenv("WIRESHARK_ABORT_ON_DISSECTOR_BUG") != NULL)
+                       abort();
+               return;
+       }
+
+       /* XXX: Should verify that sub-dissector is not already in the list ? */
+
+       hdtbl_entry = g_malloc(sizeof (heur_dtbl_entry_t));
+       hdtbl_entry->dissector = dissector;
+       hdtbl_entry->protocol  = find_protocol_by_id(proto);
+       hdtbl_entry->enabled   = TRUE;
+
+       /* do the table insertion */
+       *sub_dissectors = g_slist_append(*sub_dissectors, (gpointer)hdtbl_entry);
+}
+
+
+
+static int
+find_matching_heur_dissector( gconstpointer a, gconstpointer b) {
+       const heur_dtbl_entry_t *hdtbl_entry_a = (const heur_dtbl_entry_t *) a;
+       const heur_dtbl_entry_t *hdtbl_entry_b = (const heur_dtbl_entry_t *) b;
+       return (hdtbl_entry_a->dissector == hdtbl_entry_b->dissector) &&
+               (hdtbl_entry_a->protocol == hdtbl_entry_b->protocol) ? 0 : 1;
+}
+
+void
+heur_dissector_delete(const char *name, heur_dissector_t dissector, const int proto) {
+       heur_dissector_list_t *sub_dissectors = find_heur_dissector_list(name);
+       heur_dtbl_entry_t      hdtbl_entry;
+       GSList                *found_entry;
 
        /* sanity check */
        g_assert(sub_dissectors != NULL);
 
-       dtbl_entry = g_malloc(sizeof (heur_dtbl_entry_t));
-       dtbl_entry->dissector = dissector;
-       dtbl_entry->protocol = find_protocol_by_id(proto);
+       hdtbl_entry.dissector = dissector;
 
-       /* do the table insertion */
-       *sub_dissectors = g_slist_append(*sub_dissectors, (gpointer)dtbl_entry);
+       hdtbl_entry.protocol  = find_protocol_by_id(proto);
+
+       found_entry = g_slist_find_custom(*sub_dissectors, (gpointer) &hdtbl_entry, find_matching_heur_dissector);
+
+       if (found_entry) {
+               *sub_dissectors = g_slist_remove_link(*sub_dissectors, found_entry);
+               g_free(g_slist_nth_data(found_entry, 1));
+               g_slist_free_1(found_entry);
+       }
+}
+
+void
+heur_dissector_set_enabled(const char *name, heur_dissector_t dissector, const int proto, const gboolean enabled) {
+       heur_dissector_list_t *sub_dissectors = find_heur_dissector_list(name);
+       GSList                *found_entry;
+       heur_dtbl_entry_t      hdtbl_entry;
+
+       /* sanity check */
+       g_assert(sub_dissectors != NULL);
+
+       hdtbl_entry.dissector = dissector;
+
+       hdtbl_entry.protocol  = find_protocol_by_id(proto);
+
+       found_entry = g_slist_find_custom(*sub_dissectors, (gpointer) &hdtbl_entry, find_matching_heur_dissector);
+
+       if (found_entry) {
+               heur_dtbl_entry_t *hdtbl_entry_p;
+               hdtbl_entry_p = (heur_dtbl_entry_t *)found_entry->data;
+               hdtbl_entry_p->enabled = enabled;
+       }
 }
 
 gboolean
-dissector_try_heuristic(heur_dissector_list_t sub_dissectors,
-    tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
+dissector_try_heuristic(heur_dissector_list_t sub_dissectors, tvbuff_t *tvb,
+                       packet_info *pinfo, proto_tree *tree, void *data)
 {
-       gboolean status;
-       const char *saved_proto;
-       GSList *entry;
-       heur_dtbl_entry_t *dtbl_entry;
-       guint16 saved_can_desegment;
-       gint saved_layer_names_len = 0;
+       gboolean           status;
+       const char        *saved_proto;
+       GSList            *entry;
+       heur_dtbl_entry_t *hdtbl_entry;
+       guint16            saved_can_desegment;
+       gint               saved_layer_names_len = 0;
 
        /* can_desegment is set to 2 by anyone which offers this api/service.
           then everytime a subdissector is called it is decremented by one.
@@ -1484,32 +1760,32 @@ dissector_try_heuristic(heur_dissector_list_t sub_dissectors,
           can restore it and allow the dissectors they call to use
           the desegmentation service.
        */
-       saved_can_desegment=pinfo->can_desegment;
+       saved_can_desegment        = pinfo->can_desegment;
        pinfo->saved_can_desegment = saved_can_desegment;
-       pinfo->can_desegment = saved_can_desegment-(saved_can_desegment>0);
+       pinfo->can_desegment       = saved_can_desegment-(saved_can_desegment>0);
 
-       status = FALSE;
+       status      = FALSE;
        saved_proto = pinfo->current_proto;
 
        if (pinfo->layer_names != NULL)
-               saved_layer_names_len = pinfo->layer_names->len;
+               saved_layer_names_len = (gint) pinfo->layer_names->len;
 
        for (entry = sub_dissectors; entry != NULL; entry = g_slist_next(entry)) {
                /* XXX - why set this now and above? */
                pinfo->can_desegment = saved_can_desegment-(saved_can_desegment>0);
-               dtbl_entry = (heur_dtbl_entry_t *)entry->data;
+               hdtbl_entry = (heur_dtbl_entry_t *)entry->data;
 
-               if (dtbl_entry->protocol != NULL &&
-                   !proto_is_protocol_enabled(dtbl_entry->protocol)) {
+               if (hdtbl_entry->protocol != NULL &&
+                   (!proto_is_protocol_enabled(hdtbl_entry->protocol)||(hdtbl_entry->enabled==FALSE))) {
                        /*
                         * No - don't try this dissector.
                         */
                        continue;
                }
 
-               if (dtbl_entry->protocol != NULL) {
+               if (hdtbl_entry->protocol != NULL) {
                        pinfo->current_proto =
-                           proto_get_protocol_short_name(dtbl_entry->protocol);
+                               proto_get_protocol_short_name(hdtbl_entry->protocol);
 
                        /*
                         * Add the protocol name to the layers; we'll remove it
@@ -1518,23 +1794,28 @@ dissector_try_heuristic(heur_dissector_list_t sub_dissectors,
                        if (pinfo->layer_names) {
                                if (pinfo->layer_names->len > 0)
                                        g_string_append(pinfo->layer_names, ":");
-                               g_string_append(pinfo->layer_names,
-                                       proto_get_protocol_filter_name(proto_get_id(dtbl_entry->protocol)));
+                                       g_string_append(pinfo->layer_names,
+                                       proto_get_protocol_filter_name(proto_get_id(hdtbl_entry->protocol)));
                        }
                }
-
-               if ((*dtbl_entry->dissector)(tvb, pinfo, tree)) {
+               EP_CHECK_CANARY(("before calling heuristic dissector for protocol: %s",
+                                proto_get_protocol_filter_name(proto_get_id(hdtbl_entry->protocol))));
+               if ((*hdtbl_entry->dissector)(tvb, pinfo, tree, data)) {
+                       EP_CHECK_CANARY(("after heuristic dissector for protocol: %s has accepted and dissected packet",
+                                        proto_get_protocol_filter_name(proto_get_id(hdtbl_entry->protocol))));
                        status = TRUE;
                        break;
                } else {
+                       EP_CHECK_CANARY(("after heuristic dissector for protocol: %s has returned false",
+                                        proto_get_protocol_filter_name(proto_get_id(hdtbl_entry->protocol))));
+
                        /*
                         * That dissector didn't accept the packet, so
                         * remove its protocol's name from the list
                         * of protocols.
                         */
                        if (pinfo->layer_names != NULL) {
-                               g_string_truncate(pinfo->layer_names,
-                                   saved_layer_names_len);
+                               g_string_truncate(pinfo->layer_names, saved_layer_names_len);
                        }
                }
        }
@@ -1543,6 +1824,68 @@ dissector_try_heuristic(heur_dissector_list_t sub_dissectors,
        return status;
 }
 
+/*
+ * Called for each entry in the table of all heuristic dissector tables.
+ */
+typedef struct heur_dissector_foreach_table_info {
+       gpointer           caller_data;
+       DATFunc_heur_table caller_func;
+} heur_dissector_foreach_table_info_t;
+
+
+static void
+dissector_dump_heur_decodes_display(const gchar *table_name, const gpointer value, const gpointer user_data _U_)
+{
+       heur_dissector_list_t  sub_dissectors = *(heur_dissector_list_t *)value;
+       GSList                *entry;
+       heur_dtbl_entry_t     *hdtbl_entry;
+
+       for (entry = sub_dissectors; entry != NULL; entry = g_slist_next(entry)) {
+               hdtbl_entry = (heur_dtbl_entry_t *)entry->data;
+               if (hdtbl_entry->protocol != NULL) {
+                       printf("%s\t%s\t%c\n",
+                              table_name,
+                              proto_get_protocol_filter_name(proto_get_id(hdtbl_entry->protocol)),
+                              (proto_is_protocol_enabled(hdtbl_entry->protocol) && hdtbl_entry->enabled) ? 'T' : 'F');
+               }
+       }
+}
+
+
+static void
+dissector_all_heur_tables_foreach_table_func (gpointer key, const gpointer value, const gpointer user_data)
+{
+       heur_dissector_foreach_table_info_t *info;
+
+       info = user_data;
+       (*info->caller_func)((gchar*)key, value, info->caller_data);
+}
+
+/*
+ * Walk all heuristic dissector tables calling a user supplied function on each
+ * table.
+ */
+void
+dissector_all_heur_tables_foreach_table (DATFunc_heur_table func,
+                                        gpointer user_data)
+{
+       heur_dissector_foreach_table_info_t info;
+
+       info.caller_data = user_data;
+       info.caller_func = func;
+       g_hash_table_foreach(heur_dissector_lists, dissector_all_heur_tables_foreach_table_func, &info);
+}
+
+/*
+ * For each heuristic dissector table, dump list of dissectors (filter_names) for that table
+ */
+void
+dissector_dump_heur_decodes(void)
+{
+       dissector_all_heur_tables_foreach_table(dissector_dump_heur_decodes_display, NULL);
+}
+
+
 void
 register_heur_dissector_list(const char *name, heur_dissector_list_t *sub_dissectors)
 {
@@ -1557,7 +1900,7 @@ register_heur_dissector_list(const char *name, heur_dissector_list_t *sub_dissec
 
        *sub_dissectors = NULL; /* initially empty */
        g_hash_table_insert(heur_dissector_lists, (gpointer)name,
-           (gpointer) sub_dissectors);
+                           (gpointer) sub_dissectors);
 }
 
 /*
@@ -1572,10 +1915,21 @@ register_heur_dissector_list(const char *name, heur_dissector_list_t *sub_dissec
  */
 static GHashTable *registered_dissectors = NULL;
 
+/* Get the long name of the protocol for a dissector handle, if it has
+   a protocol. */
+const char *
+dissector_handle_get_long_name(const dissector_handle_t handle)
+{
+       if (handle == NULL || handle->protocol == NULL) {
+               return NULL;
+       }
+       return proto_get_protocol_long_name(handle->protocol);
+}
+
 /* Get the short name of the protocol for a dissector handle, if it has
    a protocol. */
 const char *
-dissector_handle_get_short_name(dissector_handle_t handle)
+dissector_handle_get_short_name(const dissector_handle_t handle)
 {
        if (handle->protocol == NULL) {
                /*
@@ -1592,7 +1946,7 @@ dissector_handle_get_short_name(dissector_handle_t handle)
 /* Get the index of the protocol for a dissector handle, if it has
    a protocol. */
 int
-dissector_handle_get_protocol_index(dissector_handle_t handle)
+dissector_handle_get_protocol_index(const dissector_handle_t handle)
 {
        if (handle->protocol == NULL) {
                /*
@@ -1616,36 +1970,36 @@ find_dissector(const char *name)
 
 /* Create an anonymous handle for a dissector. */
 dissector_handle_t
-create_dissector_handle(dissector_t dissector, int proto)
+create_dissector_handle(dissector_t dissector, const int proto)
 {
        struct dissector_handle *handle;
 
-       handle = g_malloc(sizeof (struct dissector_handle));
-       handle->name = NULL;
-       handle->is_new = FALSE;
+       handle                = g_malloc(sizeof (struct dissector_handle));
+       handle->name          = NULL;
+       handle->is_new        = FALSE;
        handle->dissector.old = dissector;
-       handle->protocol = find_protocol_by_id(proto);
+       handle->protocol      = find_protocol_by_id(proto);
 
        return handle;
 }
 
 dissector_handle_t
-new_create_dissector_handle(new_dissector_t dissector, int proto)
+new_create_dissector_handle(new_dissector_t dissector, const int proto)
 {
        struct dissector_handle *handle;
 
-       handle = g_malloc(sizeof (struct dissector_handle));
-       handle->name = NULL;
-       handle->is_new = TRUE;
+       handle                = g_malloc(sizeof (struct dissector_handle));
+       handle->name          = NULL;
+       handle->is_new        = TRUE;
        handle->dissector.new = dissector;
-       handle->protocol = find_protocol_by_id(proto);
+       handle->protocol      = find_protocol_by_id(proto);
 
        return handle;
 }
 
 /* Register a dissector by name. */
 void
-register_dissector(const char *name, dissector_t dissector, int proto)
+register_dissector(const char *name, dissector_t dissector, const int proto)
 {
        struct dissector_handle *handle;
 
@@ -1658,18 +2012,18 @@ register_dissector(const char *name, dissector_t dissector, int proto)
        /* Make sure the registration is unique */
        g_assert(g_hash_table_lookup(registered_dissectors, name) == NULL);
 
-       handle = g_malloc(sizeof (struct dissector_handle));
-       handle->name = name;
-       handle->is_new = FALSE;
+       handle                = g_malloc(sizeof (struct dissector_handle));
+       handle->name          = name;
+       handle->is_new        = FALSE;
        handle->dissector.old = dissector;
-       handle->protocol = find_protocol_by_id(proto);
+       handle->protocol      = find_protocol_by_id(proto);
 
        g_hash_table_insert(registered_dissectors, (gpointer)name,
-           (gpointer) handle);
+                           (gpointer) handle);
 }
 
 void
-new_register_dissector(const char *name, new_dissector_t dissector, int proto)
+new_register_dissector(const char *name, new_dissector_t dissector, const int proto)
 {
        struct dissector_handle *handle;
 
@@ -1682,50 +2036,58 @@ new_register_dissector(const char *name, new_dissector_t dissector, int proto)
        /* Make sure the registration is unique */
        g_assert(g_hash_table_lookup(registered_dissectors, name) == NULL);
 
-       handle = g_malloc(sizeof (struct dissector_handle));
-       handle->name = name;
-       handle->is_new = TRUE;
+       handle                = g_malloc(sizeof (struct dissector_handle));
+       handle->name          = name;
+       handle->is_new        = TRUE;
        handle->dissector.new = dissector;
-       handle->protocol = find_protocol_by_id(proto);
+       handle->protocol      = find_protocol_by_id(proto);
 
        g_hash_table_insert(registered_dissectors, (gpointer)name,
-           (gpointer) handle);
+                           (gpointer) handle);
+}
+
+/* Call a dissector through a handle but if the dissector rejected it
+ * return 0.
+ */
+int
+call_dissector_only(dissector_handle_t handle, tvbuff_t *tvb,
+                   packet_info *pinfo, proto_tree *tree, void *data)
+{
+       int ret;
+
+       g_assert(handle != NULL);
+       ret = call_dissector_work(handle, tvb, pinfo, tree, TRUE, data);
+       return ret;
 }
 
 /* Call a dissector through a handle and if this fails call the "data"
  * dissector.
  */
 int
-call_dissector(dissector_handle_t handle, tvbuff_t *tvb,
-    packet_info *pinfo, proto_tree *tree)
+call_dissector_with_data(dissector_handle_t handle, tvbuff_t *tvb,
+                        packet_info *pinfo, proto_tree *tree, void *data)
 {
        int ret;
 
-       ret = call_dissector_work(handle, tvb, pinfo, tree);
+       ret = call_dissector_only(handle, tvb, pinfo, tree, data);
        if (ret == 0) {
                /*
                 * The protocol was disabled, or the dissector rejected
                 * it.  Just dissect this packet as data.
                 */
-               g_assert(data_handle != NULL);
+               g_assert(data_handle != NULL);
                g_assert(data_handle->protocol != NULL);
-               call_dissector(data_handle, tvb, pinfo, tree);
+               call_dissector_work(data_handle, tvb, pinfo, tree, TRUE, NULL);
                return tvb_length(tvb);
        }
        return ret;
 }
 
-/* Call a dissector through a handle but if the dissector rejected it
- * return 0 instead of using the default "data" dissector.
- */
 int
-call_dissector_only(dissector_handle_t handle, tvbuff_t *tvb,
-    packet_info *pinfo, proto_tree *tree)
+call_dissector(dissector_handle_t handle, tvbuff_t *tvb,
+              packet_info *pinfo, proto_tree *tree)
 {
-       int ret;
-
-       ret = call_dissector_work(handle, tvb, pinfo, tree);
-       return ret;
+       return call_dissector_with_data(handle, tvb, pinfo, tree, NULL);
 }
 
 /*
@@ -1741,15 +2103,16 @@ call_dissector_only(dissector_handle_t handle, tvbuff_t *tvb,
 
 
 static void
-dissector_dump_decodes_display(gchar *table_name, ftenum_t selector_type _U_,
-    gpointer key, gpointer value, gpointer user_data _U_)
+dissector_dump_decodes_display(const gchar *table_name,
+                              ftenum_t selector_type _U_, const gpointer key, const gpointer value,
+                              gpointer user_data _U_)
 {
-       guint32 selector = (guint32) key;
-       dissector_table_t sub_dissectors = find_dissector_table(table_name);
-       dtbl_entry_t *dtbl_entry;
-       dissector_handle_t handle;
-       gint proto_id;
-       const gchar *decode_as;
+       guint32             selector       = (guint32)(unsigned long) key;
+       dissector_table_t   sub_dissectors = find_dissector_table(table_name);
+       dtbl_entry_t       *dtbl_entry;
+       dissector_handle_t  handle;
+       gint                proto_id;
+       const gchar        *decode_as;
 
        g_assert(sub_dissectors);
        switch (sub_dissectors->type) {
@@ -1761,7 +2124,7 @@ dissector_dump_decodes_display(gchar *table_name, ftenum_t selector_type _U_,
                        dtbl_entry = value;
                        g_assert(dtbl_entry);
 
-                       handle = dtbl_entry->current;
+                       handle   = dtbl_entry->current;
                        g_assert(handle);
 
                        proto_id = dissector_handle_get_protocol_index(handle);
@@ -1779,26 +2142,62 @@ dissector_dump_decodes_display(gchar *table_name, ftenum_t selector_type _U_,
 }
 
 void
-dissector_dump_decodes() {
+dissector_dump_decodes(void)
+{
        dissector_all_tables_foreach(dissector_dump_decodes_display, NULL);
 }
 
 static GPtrArray* post_dissectors = NULL;
 static guint num_of_postdissectors = 0;
 
-void register_postdissector(dissector_handle_t handle) {
-    if (!post_dissectors)
-        post_dissectors = g_ptr_array_new();
+void
+register_postdissector(dissector_handle_t handle)
+{
+       if (!post_dissectors)
+               post_dissectors = g_ptr_array_new();
+
+       g_ptr_array_add(post_dissectors, handle);
+       num_of_postdissectors++;
+}
+
+gboolean
+have_postdissector(void)
+{
+       guint i;
+       dissector_handle_t handle;
 
-    g_ptr_array_add(post_dissectors, handle);
-    num_of_postdissectors++;
+       for(i = 0; i < num_of_postdissectors; i++) {
+               handle = (dissector_handle_t) g_ptr_array_index(post_dissectors,i);
+
+               if (handle->protocol != NULL
+                   && proto_is_protocol_enabled(handle->protocol)) {
+                       /* We have at least one enabled postdissector */
+                       return TRUE;
+               }
+       }
+       return FALSE;
 }
 
-extern void call_all_postdissectors(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree) {
-    guint i;
-    for(i=0;i<num_of_postdissectors;i++) {
-        call_dissector((dissector_handle_t) g_ptr_array_index(post_dissectors,i),
-                       tvb,pinfo,tree);
-    }
+void
+call_all_postdissectors(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
+{
+       guint i;
+
+       for(i = 0; i < num_of_postdissectors; i++) {
+               call_dissector_only((dissector_handle_t) g_ptr_array_index(post_dissectors,i),
+                                   tvb,pinfo,tree, NULL);
+       }
 }
 
+/*
+ * Editor modelines  -  http://www.wireshark.org/tools/modelines.html
+ *
+ * Local variables:
+ * c-basic-offset: 8
+ * tab-width: 8
+ * indent-tabs-mode: t
+ * End:
+ *
+ * vi: set shiftwidth=8 tabstop=8 noexpandtab:
+ * :indentSize=8:tabSize=8:noTabs=false:
+ */