Add an API to let a postdissector specify fields whose values it needs.
authorGuy Harris <guy@alum.mit.edu>
Wed, 12 Apr 2017 02:53:48 +0000 (19:53 -0700)
committerGuy Harris <guy@alum.mit.edu>
Wed, 12 Apr 2017 04:31:19 +0000 (04:31 +0000)
Currently, this is only used to determine whether a protocol tree needs
to be built on the first pass or not - if there are postdissectors that
need fields, it does - but eventually we should be able to use it to
prime the dissection to deliver those fields in cases where we don't
need the *entire* protocol tree (rather than using a hack such as
cooking up a fake tap with a fake filter to do that).

Update MATE and TRANSUM to use it.

Clean up code to check whether we need a protocol tree, and add comments
before that code indicating, in each case, what the criteria are.

The array of postdissectors includes a length, so we don't need to
separately keep track of the number of postdissectors.

Clean up indentation while we're at it.

Change-Id: I71d4025848206d144bc54cc82941089a50e80ab7
Reviewed-on: https://code.wireshark.org/review/21029
Reviewed-by: Guy Harris <guy@alum.mit.edu>
14 files changed:
debian/libwireshark0.symbols
epan/packet.c
epan/packet.h
epan/wslua/wslua_proto.c
file.c
plugins/mate/mate.h
plugins/mate/mate_setup.c
plugins/mate/packet-mate.c
plugins/transum/packet-transum.c
sharkd.c
tfshark.c
tshark.c
ui/gtk/packet_list_store.c
ui/qt/packet_list_record.cpp

index a7da4fd9659cbfe7fd7143dd3db1e11f66c5ebbc..86816fbba71688550fc1274504dd01913be64767 100644 (file)
@@ -939,6 +939,7 @@ libwireshark.so.0 libwireshark0 #MINVER#
  port_type_to_str@Base 1.12.0~rc1
  port_with_resolution_to_str@Base 2.1.0
  port_with_resolution_to_str_buf@Base 2.0.0
+ postdissectors_want_fields@Base 2.3.0
  postseq_cleanup_all_protocols@Base 1.9.1
  pref_clean_stash@Base 2.3.0
  pref_stash@Base 2.3.0
@@ -1353,6 +1354,7 @@ libwireshark.so.0 libwireshark0 #MINVER#
  set_enabled_protos_list@Base 2.3.0
  set_fd_time@Base 1.9.1
  set_mac_lte_proto_data@Base 1.9.1
+ set_postdissector_wanted_fields@Base 2.3.0
  set_srt_table_param_data@Base 1.99.8
  set_tap_dfilter@Base 1.9.1
  show_exception@Base 1.9.1
index de0a84854ae3b3e9e06abec59bc990375fc59b12..4a3b5cbd6434fba6b633b8e1d11f8a02f89e42af 100644 (file)
@@ -127,8 +127,24 @@ static GHashTable *depend_dissector_lists = NULL;
  * the final cleanup. */
 static GSList *postseq_cleanup_routines;
 
-static GPtrArray* post_dissectors = NULL;
-static guint num_of_postdissectors = 0;
+/*
+ * Post-dissector information - handle for the dissector and a list
+ * of hfids for the fields the post-dissector wants.
+ */
+typedef struct {
+       dissector_handle_t handle;
+       GArray *wanted_fields;
+} postdissector;
+
+/*
+ * Array of all postdissectors.
+ */
+static GArray *postdissectors = NULL;
+
+/*
+ * i-th element of that array.
+ */
+#define POSTDISSECTORS(i)      g_array_index(postdissectors, postdissector, i)
 
 static void
 destroy_depend_dissector_list(void *data)
@@ -248,8 +264,8 @@ packet_cleanup(void)
        g_hash_table_destroy(heuristic_short_names);
        g_slist_foreach(shutdown_routines, &call_routine, NULL);
        g_slist_free(shutdown_routines);
-       if (post_dissectors)
-               g_ptr_array_free(post_dissectors, TRUE);
+       if (postdissectors)
+               g_array_free(postdissectors, TRUE);
 }
 
 /*
@@ -3252,20 +3268,43 @@ dissector_dump_dissector_tables(void)
 void
 register_postdissector(dissector_handle_t handle)
 {
-       if (!post_dissectors)
-               post_dissectors = g_ptr_array_new();
+       postdissector p;
 
-       g_ptr_array_add(post_dissectors, handle);
-       num_of_postdissectors++;
+       if (!postdissectors)
+               postdissectors = g_array_sized_new(FALSE, FALSE, (guint)sizeof(postdissector), 1);
+
+       p.handle = handle;
+       p.wanted_fields = NULL;
+       postdissectors = g_array_append_val(postdissectors, p);
+}
+
+void
+set_postdissector_wanted_fields(dissector_handle_t handle, GArray *wanted_fields)
+{
+    guint i;
+
+    if (!postdissectors) return;
+
+    for (i = 0; i < postdissectors->len; i++) {
+        if (POSTDISSECTORS(i).handle == handle) {
+            POSTDISSECTORS(i).wanted_fields = wanted_fields;
+            break;
+        }
+    }
 }
 
 void
 deregister_postdissector(dissector_handle_t handle)
 {
-    if (!post_dissectors) return;
+    guint i;
+
+    if (!postdissectors) return;
 
-    if (g_ptr_array_remove(post_dissectors, handle)) {
-        num_of_postdissectors--;
+    for (i = 0; i < postdissectors->len; i++) {
+        if (POSTDISSECTORS(i).handle == handle) {
+            postdissectors = g_array_remove_index_fast(postdissectors, i);
+            break;
+        }
     }
 }
 
@@ -3275,8 +3314,8 @@ have_postdissector(void)
        guint i;
        dissector_handle_t handle;
 
-       for(i = 0; i < num_of_postdissectors; i++) {
-               handle = (dissector_handle_t) g_ptr_array_index(post_dissectors,i);
+       for (i = 0; i < postdissectors->len; i++) {
+               handle = POSTDISSECTORS(i).handle;
 
                if (handle->protocol != NULL
                    && proto_is_protocol_enabled(handle->protocol)) {
@@ -3292,12 +3331,25 @@ 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);
+       for (i = 0; i < postdissectors->len; i++) {
+               call_dissector_only(POSTDISSECTORS(i).handle,
+                                   tvb, pinfo, tree, NULL);
        }
 }
 
+gboolean
+postdissectors_want_fields(void)
+{
+       guint i;
+
+       for (i = 0; i < postdissectors->len; i++) {
+               if (POSTDISSECTORS(i).wanted_fields != NULL &&
+                   POSTDISSECTORS(i).wanted_fields->len != 0)
+                       return TRUE;
+       }
+       return FALSE;
+}
+
 /*
  * Editor modelines  -  http://www.wireshark.org/tools/modelines.html
  *
index 9d4efaf02d325cc056c03ce841f668725f283b75..47eed6fe337a3ddd19f8d0f6a346650f9f54a49f 100644 (file)
@@ -765,15 +765,50 @@ WS_DLL_PUBLIC void dissector_dump_decodes(void);
 WS_DLL_PUBLIC void dissector_dump_heur_decodes(void);
 
 /*
- * post dissectors are to be called by packet-frame.c after every other
+ * postdissectors are to be called by packet-frame.c after every other
  * dissector has been called.
  */
-WS_DLL_PUBLIC void register_postdissector(dissector_handle_t);
+
+/*
+ * Register a postdissector; the argument is the dissector handle for it.
+ */
+WS_DLL_PUBLIC void register_postdissector(dissector_handle_t handle);
+
+/*
+ * Specify a set of fields that the postdissector will need.
+ * The GArray is an array of hfids.
+ */
+WS_DLL_PUBLIC void set_postdissector_wanted_fields(dissector_handle_t handle,
+    GArray *wanted_fields);
+
+/*
+ * Deregister a postdissector.  Not for use in (post)dissectors or
+ * applications; only to be used by libwireshark itself.
+ */
 void deregister_postdissector(dissector_handle_t handle);
 
+/*
+ * Return TRUE if we have at least one postdissector, FALSE if not.
+ * Not for use in (post)dissectors or applications; only to be used
+ * by libwireshark itself.
+ */
 extern gboolean have_postdissector(void);
+
+/*
+ * Call all postdissectors, handing them the supplied arguments.
+ * Not for use in (post)dissectors or applications; only to be used
+ * by libwireshark itself.
+ */
 extern void call_all_postdissectors(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree);
 
+/*
+ * Return TRUE if at least one postdissector wants fields, FALSE otherwise.
+ * XXX - at some point this should return a bag of all fields requested by
+ * all postdissectors, so we can prime the epan_dissect_t with them rather
+ * than constructing a bogus tap with a bogus filter.
+ */
+WS_DLL_PUBLIC gboolean postdissectors_want_fields(void);
+
 /** @} */
 
 #ifdef __cplusplus
index acbdb67e7653325cc87fac078339721cebe904c2..b8e2cc41a162690de8e97ebc9cb08c5b56032412 100644 (file)
@@ -203,6 +203,16 @@ WSLUA_FUNCTION wslua_register_postdissector(lua_State* L) {
     }
 
     if (all_fields) {
+        /*
+         * XXX - are there any Lua postdissectors that need "all fields",
+         * i.e. the entire protocol tree, or do they just look for
+         * *particular* fields, with field extractors?
+         *
+         * And do all of them require the actual *displayed* format of
+         * the fields they need?
+         *
+         * If not, this is overkill.
+         */
         epan_set_always_visible(TRUE);
     }
 
diff --git a/file.c b/file.c
index ff39a9dffe493cde4da6a3a28ce76c08938d4c45..4f3908009facd54207b121bb9e1a419d5a825216 100644 (file)
--- a/file.c
+++ b/file.c
@@ -561,8 +561,22 @@ cf_read(capture_file *cf, gboolean reloading)
 
   /* Get the union of the flags for all tap listeners. */
   tap_flags = union_of_tap_listener_flags();
+
+  /*
+   * Determine whether we need to create a protocol tree.
+   * We do if:
+   *
+   *    we're going to apply a display filter;
+   *
+   *    one of the tap listeners is going to apply a filter;
+   *
+   *    one of the tap listeners requires a protocol tree;
+   *
+   *    a postdissector wants field values on the first pass.
+   */
   create_proto_tree =
-    (dfcode != NULL || have_filtering_tap_listeners() || (tap_flags & TL_REQUIRES_PROTO_TREE));
+    (dfcode != NULL || have_filtering_tap_listeners() ||
+     (tap_flags & TL_REQUIRES_PROTO_TREE) || postdissectors_want_fields());
 
   reset_tap_listeners();
 
@@ -597,6 +611,7 @@ cf_read(capture_file *cf, gboolean reloading)
 
     column_info *cinfo;
 
+    /* If any tap listeners require the columns, construct them. */
     cinfo = (tap_flags & TL_REQUIRES_COLUMNS) ? &cf->cinfo : NULL;
 
     /* Find the size of the file. */
@@ -786,8 +801,22 @@ cf_continue_tail(capture_file *cf, volatile int to_read, int *err)
 
   /* Get the union of the flags for all tap listeners. */
   tap_flags = union_of_tap_listener_flags();
+
+  /*
+   * Determine whether we need to create a protocol tree.
+   * We do if:
+   *
+   *    we're going to apply a display filter;
+   *
+   *    one of the tap listeners is going to apply a filter;
+   *
+   *    one of the tap listeners requires a protocol tree;
+   *
+   *    a postdissector wants field values on the first pass.
+   */
   create_proto_tree =
-    (dfcode != NULL || have_filtering_tap_listeners() || (tap_flags & TL_REQUIRES_PROTO_TREE));
+    (dfcode != NULL || have_filtering_tap_listeners() ||
+     (tap_flags & TL_REQUIRES_PROTO_TREE) || postdissectors_want_fields());
 
   *err = 0;
 
@@ -803,6 +832,7 @@ cf_continue_tail(capture_file *cf, volatile int to_read, int *err)
     gint64 data_offset = 0;
     column_info *cinfo;
 
+    /* If any tap listeners require the columns, construct them. */
     cinfo = (tap_flags & TL_REQUIRES_COLUMNS) ? &cf->cinfo : NULL;
 
     while (to_read != 0) {
@@ -913,9 +943,25 @@ cf_finish_tail(capture_file *cf, int *err)
 
   /* Get the union of the flags for all tap listeners. */
   tap_flags = union_of_tap_listener_flags();
+
+  /* If any tap listeners require the columns, construct them. */
   cinfo = (tap_flags & TL_REQUIRES_COLUMNS) ? &cf->cinfo : NULL;
+
+  /*
+   * Determine whether we need to create a protocol tree.
+   * We do if:
+   *
+   *    we're going to apply a display filter;
+   *
+   *    one of the tap listeners is going to apply a filter;
+   *
+   *    one of the tap listeners requires a protocol tree;
+   *
+   *    a postdissector wants field values on the first pass.
+   */
   create_proto_tree =
-    (dfcode != NULL || have_filtering_tap_listeners() || (tap_flags & TL_REQUIRES_PROTO_TREE));
+    (dfcode != NULL || have_filtering_tap_listeners() ||
+     (tap_flags & TL_REQUIRES_PROTO_TREE) || postdissectors_want_fields());
 
   if (cf->wth == NULL) {
     cf_close(cf);
@@ -1573,9 +1619,27 @@ rescan_packets(capture_file *cf, const char *action, const char *action_item, gb
 
   /* Get the union of the flags for all tap listeners. */
   tap_flags = union_of_tap_listener_flags();
+
+  /* If any tap listeners require the columns, construct them. */
   cinfo = (tap_flags & TL_REQUIRES_COLUMNS) ? &cf->cinfo : NULL;
+
+  /*
+   * Determine whether we need to create a protocol tree.
+   * We do if:
+   *
+   *    we're going to apply a display filter;
+   *
+   *    one of the tap listeners is going to apply a filter;
+   *
+   *    one of the tap listeners requires a protocol tree;
+   *
+   *    we're redissecting and a postdissector wants field
+   *    values on the first pass.
+   */
   create_proto_tree =
-    (dfcode != NULL || have_filtering_tap_listeners() || (tap_flags & TL_REQUIRES_PROTO_TREE));
+    (dfcode != NULL || have_filtering_tap_listeners() ||
+     (tap_flags & TL_REQUIRES_PROTO_TREE) ||
+     (redissect && postdissectors_want_fields()));
 
   reset_tap_listeners();
   /* Which frame, if any, is the currently selected frame?
@@ -2103,8 +2167,7 @@ cf_retap_packets(capture_file *cf)
 {
   packet_range_t        range;
   retap_callback_args_t callback_args;
-  gboolean              construct_protocol_tree;
-  gboolean              filtering_tap_listeners;
+  gboolean              create_proto_tree;
   guint                 tap_flags;
   psp_return_t          ret;
 
@@ -2115,23 +2178,27 @@ cf_retap_packets(capture_file *cf)
 
   cf_callback_invoke(cf_cb_file_retap_started, cf);
 
-  /* Do we have any tap listeners with filters? */
-  filtering_tap_listeners = have_filtering_tap_listeners();
-
+  /* Get the union of the flags for all tap listeners. */
   tap_flags = union_of_tap_listener_flags();
 
-  /* If any tap listeners have filters, or require the protocol tree,
-     construct the protocol tree. */
-  construct_protocol_tree = filtering_tap_listeners ||
-                            (tap_flags & TL_REQUIRES_PROTO_TREE);
-
   /* If any tap listeners require the columns, construct them. */
   callback_args.cinfo = (tap_flags & TL_REQUIRES_COLUMNS) ? &cf->cinfo : NULL;
 
+  /*
+   * Determine whether we need to create a protocol tree.
+   * We do if:
+   *
+   *    one of the tap listeners is going to apply a filter;
+   *
+   *    one of the tap listeners requires a protocol tree.
+   */
+  create_proto_tree =
+    (have_filtering_tap_listeners() || (tap_flags & TL_REQUIRES_PROTO_TREE));
+
   /* Reset the tap listeners. */
   reset_tap_listeners();
 
-  epan_dissect_init(&callback_args.edt, cf->epan, construct_protocol_tree, FALSE);
+  epan_dissect_init(&callback_args.edt, cf->epan, create_proto_tree, FALSE);
 
   /* Iterate through the list of packets, dissecting all packets and
      re-running the taps. */
index 3e9582ec294341e03ce57398cac7b93ea257b230..01f5435f942e111e26a844eaf9cbd595f5b376ea 100644 (file)
@@ -197,6 +197,8 @@ typedef struct _mate_config {
 
        int hfid_mate;
 
+       GArray *wanted_fields;  /* hfids of fields MATE needs */
+
        GString* fields_filter; /* "ip.addr || dns.id || ... " for the tap */
        GString* protos_filter; /* "dns || ftp || ..." for the tap */
        gchar* tap_filter;
index 46e2ff1f6b3e6637d96954b7bf1c034a31c9100d..0ced43af34f5a0fcd214f5bde558642893064e14 100644 (file)
@@ -187,6 +187,10 @@ extern gboolean add_hfid(header_field_info*  hfi, gchar* how, GHashTable* where)
        return exists;
 }
 
+#if 0
+/*
+ * XXX - where is this suposed to be used?
+ */
 extern gchar* add_ranges(gchar* range,GPtrArray* range_ptr_arr) {
        gchar**  ranges;
        guint i;
@@ -214,6 +218,7 @@ extern gchar* add_ranges(gchar* range,GPtrArray* range_ptr_arr) {
 
        return NULL;
 }
+#endif
 
 static void new_attr_hfri(gchar* item_name, GHashTable* hfids, gchar* name) {
        int* p_id = (int *)g_malloc(sizeof(int));
@@ -248,6 +253,11 @@ static void analyze_pdu_hfids(gpointer k, gpointer v, gpointer p) {
        mate_cfg_pdu* cfg = (mate_cfg_pdu *)p;
        new_attr_hfri(cfg->name,cfg->my_hfids,(gchar*) v);
 
+       /*
+        * Add this hfid to our table of hfids.
+        */
+       matecfg->wanted_fields = g_array_append_val(matecfg->wanted_fields, *(int *)k);
+
        g_string_append_printf(matecfg->fields_filter,"||%s",my_protoname(*(int*)k));
 }
 
@@ -577,6 +587,8 @@ extern mate_config* mate_make_config(const gchar* filename, int mate_hfid) {
 
        matecfg->hfid_mate = mate_hfid;
 
+       matecfg->wanted_fields = g_array_new(FALSE, FALSE, (guint)sizeof(int));
+
        matecfg->fields_filter = g_string_new("");
        matecfg->protos_filter = g_string_new("");
 
index 047ebae889ed79e7a5764ec56c24653c7919484a..65f08209fb5ab26f5437e7c4f355ab4aa4b406b2 100644 (file)
@@ -53,6 +53,8 @@ static const gchar* current_mate_config_filename = NULL;
 
 static proto_item *mate_i = NULL;
 
+static dissector_handle_t mate_handle;
+
 static void
 pdu_attrs_tree(proto_tree* tree, packet_info *pinfo, tvbuff_t *tvb, mate_pdu* pdu)
 {
@@ -352,6 +354,12 @@ proto_reg_handoff_mate(void)
                                proto_register_subtree_array((gint**)(void*)mc->ett->data, mc->ett->len);
                                register_init_routine(initialize_mate_runtime);
 
+                               /*
+                                * Set the list of fields we want.
+                                */
+                               set_postdissector_wanted_fields(mate_handle,
+                                   mc->wanted_fields);
+
                                tap_error = register_tap_listener("frame", &mate_tap_data,
                                    (char*) mc->tap_filter,
                                    0,
@@ -393,7 +401,6 @@ proto_register_mate(void)
 
        expert_module_t* expert_mate;
        module_t *mate_module;
-       dissector_handle_t mate_handle;
 
        proto_mate = proto_register_protocol("Meta Analysis Tracing Engine", "MATE", "mate");
        proto_register_field_array(proto_mate, hf, array_length(hf));
index cb066843930bd04d477c22450f58d883227cea05..79f4507e929479310fda03d822716e1a033c7936 100644 (file)
@@ -41,6 +41,8 @@
 void proto_register_transum(void);
 void proto_reg_handoff_transum(void);
 
+static dissector_handle_t transum_handle;
+
 #define CAPTURE_CLIENT 0
 #define CAPTURE_INTERMEDIATE 1
 #define CAPTURE_SERVICE 2
@@ -142,6 +144,10 @@ static wmem_map_t *output_rrpd;
  */
 static wmem_list_t *temp_rsp_rrpd_list = NULL;  /* Reuse these for speed and efficient memory use - issue a warning if we run out */
 
+/*
+ * GArray of the hfids of all fields we're interested in.
+ */
+GArray *wanted_fields;
 
 static gint ett_transum = -1;
 static gint ett_transum_header = -1;
@@ -715,6 +721,14 @@ static void init_globals(void)
     rrpd_list = wmem_list_new(wmem_file_scope());
     temp_rsp_rrpd_list = wmem_list_new(wmem_file_scope());
 
+    /* Indicate what fields we're interested in. */
+    wanted_fields = g_array_new(FALSE, FALSE, (guint)sizeof(int));
+    for (int i = 0; i < HF_INTEREST_END_OF_LIST; i++)
+    {
+        g_array_append_val(wanted_fields, hf_of_interest[i].hf);
+    }
+    set_postdissector_wanted_fields(transum_handle, wanted_fields);
+
     GString* fake_tap_filter = g_string_new("frame || eth.type");
 
     for (int i = 0; i < HF_INTEREST_END_OF_LIST; i++)
@@ -1001,8 +1015,13 @@ static int dissect_transum(tvbuff_t *buffer, packet_info *pinfo, proto_tree *tre
         RRPD *rrpd = (RRPD*)wmem_map_lookup(output_rrpd, GUINT_TO_POINTER(pinfo->num));
 
         if (rrpd)
-            /* Add the RTE data to the protocol decode tree if we output_flag is set */
-            write_rte(rrpd, buffer, tree, NULL);
+        {
+            if (tree)
+            {
+                /* Add the RTE data to the protocol decode tree if we output_flag is set */
+                write_rte(rrpd, buffer, tree, NULL);
+            }
+        }
     }
     else
     {
@@ -1030,7 +1049,6 @@ void
 proto_register_transum(void)
 {
     module_t *transum_module;
-    dissector_handle_t transum_handle;
 
     static hf_register_info hf[] = {
         { &hf_tsum_status,
index 712e73117d2784c2465517aa6ae100f2b0b32ff9..666e46a65213ebdc2407f04546e7f88c342bf04f 100644 (file)
--- a/sharkd.c
+++ b/sharkd.c
@@ -364,12 +364,20 @@ load_cap_file(capture_file *cf, int max_packet_count, gint64 max_byte_count)
     cf->frames = new_frame_data_sequence();
 
     {
-       gboolean create_proto_tree = FALSE;
-
-      /* If we're going to be applying a filter, we'll need to
-         create a protocol tree against which to apply the filter. */
-      if (cf->rfcode || cf->dfcode)
-        create_proto_tree = TRUE;
+      gboolean create_proto_tree;
+
+      /*
+       * Determine whether we need to create a protocol tree.
+       * We do if:
+       *
+       *    we're going to apply a read filter;
+       *
+       *    we're going to apply a display filter;
+       *
+       *    a postdissector wants field values on the first pass.
+       */
+      create_proto_tree =
+        (cf->rfcode != NULL || cf->dfcode != NULL || postdissectors_want_fields());
 
       /* We're not going to display the protocol tree on this pass,
          so it's not going to be "visible". */
@@ -809,21 +817,31 @@ sharkd_retap(void)
   int err;
   char *err_info = NULL;
 
-  gboolean      filtering_tap_listeners;
   guint         tap_flags;
-  gboolean      construct_protocol_tree;
+  gboolean      create_proto_tree;
   epan_dissect_t edt;
   column_info   *cinfo;
 
-  filtering_tap_listeners = have_filtering_tap_listeners();
+  /* Get the union of the flags for all tap listeners. */
   tap_flags = union_of_tap_listener_flags();
 
-  construct_protocol_tree = filtering_tap_listeners || (tap_flags & TL_REQUIRES_PROTO_TREE);
+  /* If any tap listeners require the columns, construct them. */
   cinfo = (tap_flags & TL_REQUIRES_COLUMNS) ? &cfile.cinfo : NULL;
 
+  /*
+   * Determine whether we need to create a protocol tree.
+   * We do if:
+   *
+   *    one of the tap listeners is going to apply a filter;
+   *
+   *    one of the tap listeners requires a protocol tree.
+   */
+  create_proto_tree =
+    (have_filtering_tap_listeners() || (tap_flags & TL_REQUIRES_PROTO_TREE));
+
   wtap_phdr_init(&phdr);
   ws_buffer_init(&buf, 1500);
-  epan_dissect_init(&edt, cfile.epan, construct_protocol_tree, FALSE);
+  epan_dissect_init(&edt, cfile.epan, create_proto_tree, FALSE);
 
   reset_tap_listeners();
 
index 2dcd57385f4ba15235ac9d4cd65a2e6e79c5feec..28c2c42ab56e22decd283abfec0fd14f8b5e6d25 100644 (file)
--- a/tfshark.c
+++ b/tfshark.c
@@ -1331,12 +1331,18 @@ load_cap_file(capture_file *cf, int max_packet_count, gint64 max_byte_count)
     cf->frames = new_frame_data_sequence();
 
     if (do_dissection) {
-       gboolean create_proto_tree = FALSE;
+      gboolean create_proto_tree;
 
-      /* If we're going to be applying a filter, we'll need to
-         create a protocol tree against which to apply the filter. */
-      if (cf->rfcode)
-        create_proto_tree = TRUE;
+      /*
+       * Determine whether we need to create a protocol tree.
+       * We do if:
+       *
+       *    we're going to apply a read filter;
+       *
+       *    a postdissector wants field values on the first pass.
+       */
+      create_proto_tree =
+        (cf->rfcode != NULL || postdissectors_want_fields());
 
       /* We're not going to display the protocol tree on this pass,
          so it's not going to be "visible". */
@@ -1379,11 +1385,22 @@ load_cap_file(capture_file *cf, int max_packet_count, gint64 max_byte_count)
     if (do_dissection) {
       gboolean create_proto_tree;
 
-      if (cf->dfcode || print_details || filtering_tap_listeners ||
-         (tap_flags & TL_REQUIRES_PROTO_TREE) || have_custom_cols(&cf->cinfo))
-           create_proto_tree = TRUE;
-      else
-           create_proto_tree = FALSE;
+      /*
+       * Determine whether we need to create a protocol tree.
+       * We do if:
+       *
+       *    we're going to apply a display filter;
+       *
+       *    we're going to print the protocol tree;
+       *
+       *    one of the tap listeners requires a protocol tree;
+       *
+       *    we have custom columns (which require field values, which
+       *    currently requires that we build a protocol tree).
+       */
+      create_proto_tree =
+        (cf->dfcode || print_details || filtering_tap_listeners ||
+         (tap_flags & TL_REQUIRES_PROTO_TREE) || have_custom_cols(&cf->cinfo));
 
       /* The protocol tree will be "visible", i.e., printed, only if we're
          printing packet details, which is true if we're printing stuff
@@ -1418,11 +1435,29 @@ load_cap_file(capture_file *cf, int max_packet_count, gint64 max_byte_count)
     if (do_dissection) {
       gboolean create_proto_tree;
 
-      if (cf->rfcode || cf->dfcode || print_details || filtering_tap_listeners ||
-          (tap_flags & TL_REQUIRES_PROTO_TREE) || have_custom_cols(&cf->cinfo))
-        create_proto_tree = TRUE;
-      else
-        create_proto_tree = FALSE;
+      /*
+       * Determine whether we need to create a protocol tree.
+       * We do if:
+       *
+       *    we're going to apply a read filter;
+       *
+       *    we're going to apply a display filter;
+       *
+       *    we're going to print the protocol tree;
+       *
+       *    one of the tap listeners is going to apply a filter;
+       *
+       *    one of the tap listeners requires a protocol tree;
+       *
+       *    a postdissector wants field values on the first pass;
+       *
+       *    we have custom columns (which require field values, which
+       *    currently requires that we build a protocol tree).
+       */
+      create_proto_tree =
+        (cf->rfcode || cf->dfcode || print_details || filtering_tap_listeners ||
+          (tap_flags & TL_REQUIRES_PROTO_TREE) || postdissectors_want_fields() ||
+          have_custom_cols(&cf->cinfo));
 
       /* The protocol tree will be "visible", i.e., printed, only if we're
          printing packet details, which is true if we're printing stuff
index d8e70622a657fe061aed0c2ee2b5ea01748fdb7e..dee68f3c96178869245d411c07ff13ba1f7e246a 100644 (file)
--- a/tshark.c
+++ b/tshark.c
@@ -2561,11 +2561,29 @@ capture_input_new_packets(capture_session *cap_session, int to_read)
     gboolean create_proto_tree;
     epan_dissect_t *edt;
 
-    if (cf->rfcode || cf->dfcode || print_details || filtering_tap_listeners ||
-        (tap_flags & TL_REQUIRES_PROTO_TREE) || have_custom_cols(&cf->cinfo))
-      create_proto_tree = TRUE;
-    else
-      create_proto_tree = FALSE;
+    /*
+     * Determine whether we need to create a protocol tree.
+     * We do if:
+     *
+     *    we're going to apply a read filter;
+     *
+     *    we're going to apply a display filter;
+     *
+     *    we're going to print the protocol tree;
+     *
+     *    one of the tap listeners is going to apply a filter;
+     *
+     *    one of the tap listeners requires a protocol tree;
+     *
+     *    a postdissector wants field values on the first pass;
+     *
+     *    we have custom columns (which require field values, which
+     *    currently requires that we build a protocol tree).
+     */
+    create_proto_tree =
+      (cf->rfcode || cf->dfcode || print_details || filtering_tap_listeners ||
+        (tap_flags & TL_REQUIRES_PROTO_TREE) || postdissectors_want_fields() ||
+        have_custom_cols(&cf->cinfo));
 
     /* The protocol tree will be "visible", i.e., printed, only if we're
        printing packet details, which is true if we're printing stuff
@@ -3078,12 +3096,20 @@ load_cap_file(capture_file *cf, char *save_file, int out_file_type,
     cf->frames = new_frame_data_sequence();
 
     if (do_dissection) {
-       gboolean create_proto_tree = FALSE;
+      gboolean create_proto_tree;
 
-      /* If we're going to be applying a filter, we'll need to
-         create a protocol tree against which to apply the filter. */
-      if (cf->rfcode || cf->dfcode)
-        create_proto_tree = TRUE;
+      /*
+       * Determine whether we need to create a protocol tree.
+       * We do if:
+       *
+       *    we're going to apply a read filter;
+       *
+       *    we're going to apply a display filter;
+       *
+       *    a postdissector wants field values on the first pass.
+       */
+      create_proto_tree =
+        (cf->rfcode != NULL || cf->dfcode != NULL || postdissectors_want_fields());
 
       tshark_debug("tshark: create_proto_tree = %s", create_proto_tree ? "TRUE" : "FALSE");
 
@@ -3131,11 +3157,22 @@ load_cap_file(capture_file *cf, char *save_file, int out_file_type,
     if (do_dissection) {
       gboolean create_proto_tree;
 
-      if (cf->dfcode || print_details || filtering_tap_listeners ||
-         (tap_flags & TL_REQUIRES_PROTO_TREE) || have_custom_cols(&cf->cinfo))
-           create_proto_tree = TRUE;
-      else
-           create_proto_tree = FALSE;
+      /*
+       * Determine whether we need to create a protocol tree.
+       * We do if:
+       *
+       *    we're going to apply a display filter;
+       *
+       *    we're going to print the protocol tree;
+       *
+       *    one of the tap listeners requires a protocol tree;
+       *
+       *    we have custom columns (which require field values, which
+       *    currently requires that we build a protocol tree).
+       */
+      create_proto_tree =
+        (cf->dfcode || print_details || filtering_tap_listeners ||
+         (tap_flags & TL_REQUIRES_PROTO_TREE) || have_custom_cols(&cf->cinfo));
 
       tshark_debug("tshark: create_proto_tree = %s", create_proto_tree ? "TRUE" : "FALSE");
 
@@ -3257,11 +3294,29 @@ load_cap_file(capture_file *cf, char *save_file, int out_file_type,
     if (do_dissection) {
       gboolean create_proto_tree;
 
-      if (cf->rfcode || cf->dfcode || print_details || filtering_tap_listeners ||
-          (tap_flags & TL_REQUIRES_PROTO_TREE) || have_custom_cols(&cf->cinfo))
-        create_proto_tree = TRUE;
-      else
-        create_proto_tree = FALSE;
+      /*
+       * Determine whether we need to create a protocol tree.
+       * We do if:
+       *
+       *    we're going to apply a read filter;
+       *
+       *    we're going to apply a display filter;
+       *
+       *    we're going to print the protocol tree;
+       *
+       *    one of the tap listeners is going to apply a filter;
+       *
+       *    one of the tap listeners requires a protocol tree;
+       *
+       *    a postdissector wants field values on the first pass;
+       *
+       *    we have custom columns (which require field values, which
+       *    currently requires that we build a protocol tree).
+       */
+      create_proto_tree =
+        (cf->rfcode || cf->dfcode || print_details || filtering_tap_listeners ||
+          (tap_flags & TL_REQUIRES_PROTO_TREE) || postdissectors_want_fields() ||
+          have_custom_cols(&cf->cinfo))
 
       tshark_debug("tshark: create_proto_tree = %s", create_proto_tree ? "TRUE" : "FALSE");
 
index 76ffb8e6ec79b1c169c97f11e6ab10818a12e35a..2ea5d00a81fcf07c8464b4a515d2097917814a4c 100644 (file)
@@ -1148,6 +1148,16 @@ packet_list_dissect_and_cache_record(PacketList *packet_list, PacketListRecord *
                return; /* error reading the record */
        }
 
+       /*
+        * Determine whether we need to create a protocol tree.
+        * We do if:
+        *
+        *    we're going to apply a color filter to this packet;
+        *
+        *    we're need to fill in the columns and we have custom columns
+        *    (which require field values, which currently requires that
+        *    we build a protocol tree).
+        */
        create_proto_tree = (dissect_color && color_filters_used()) ||
                                                (dissect_columns && have_custom_cols(cinfo));
 
index 26a444e02b2e06658e03e7d32de413fbc549c9f5..bf6f8667023bbec94375b667e9b72aae954ffdf8 100644 (file)
@@ -153,6 +153,18 @@ void PacketListRecord::dissect(capture_file *cap_file, bool dissect_color)
         return;    /* error reading the record */
     }
 
+    /*
+     * Determine whether we need to create a protocol tree.
+     * We do if:
+     *
+     *    we're going to apply a color filter to this packet;
+     *
+     *    we're need to fill in the columns and we have custom columns
+     *    (which require field values, which currently requires that
+     *    we build a protocol tree).
+     *
+     *    XXX - field extractors?  (Not done for GTK+....)
+     */
     create_proto_tree = ((dissect_color && color_filters_used()) ||
                          (dissect_columns && (have_custom_cols(cinfo) ||
                                               have_field_extractors())));