Don't cast away constness (except in cases where an API makes that
[metze/wireshark/wip.git] / tshark.c
index 6b3827a439cf0a032b2eeb376318414295ac7eb4..0d48f1506bfe35ed8d96dcc9921594f4e6fe6b2d 100644 (file)
--- a/tshark.c
+++ b/tshark.c
  *
  * 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 <stdlib.h>
 #include <stdio.h>
 #endif
 
 #include <glib.h>
+#include <epan/epan-int.h>
 #include <epan/epan.h>
 #include <epan/filesystem.h>
+#include <wsutil/crash_info.h>
 #include <wsutil/privileges.h>
 #include <wsutil/file_util.h>
 
 #include <epan/timestamp.h>
 #include <epan/packet.h>
 #include "file.h"
-#include "disabled_protos.h"
+#include "frame_tvbuff.h"
+#include <epan/disabled_protos.h>
 #include <epan/prefs.h>
 #include <epan/column.h>
-#include "print.h"
+#include <epan/print.h>
 #include <epan/addr_resolv.h>
-#include "util.h"
+#include "ui/util.h"
 #include "clopts_common.h"
-#include "console_io.h"
 #include "cmdarg_err.h"
 #include "version_info.h"
 #include <epan/plugins.h>
 #include "capture-wpcap.h"
 #include <wsutil/unicode-utils.h>
 #endif /* _WIN32 */
+#include "capture_session.h"
 #include "capture_sync.h"
+#include "capture_opts.h"
 #endif /* HAVE_LIBPCAP */
 #include "log.h"
 #include <epan/funnel.h>
-#include "capture_opts.h"
 
 /*
  * This is the template for the decode as option; it is shared between the
 static const gchar decode_as_arg_template[] = "<layer_type>==<selector>,<decode_as_protocol>";
 
 static guint32 cum_bytes;
-static nstime_t first_ts;
-static nstime_t prev_dis_ts;
-static nstime_t prev_cap_ts;
+static const frame_data *ref;
+static frame_data ref_frame;
+static frame_data *prev_dis;
+static frame_data prev_dis_frame;
+static frame_data *prev_cap;
+static frame_data prev_cap_frame;
 
-static gboolean print_packet_info;      /* TRUE if we're to print packet information */
+static const char* prev_display_dissector_name = NULL;
 
 static gboolean perform_two_pass_analysis;
 
@@ -123,10 +127,13 @@ typedef enum {
 } output_action_e;
 
 static output_action_e output_action;
-static gboolean do_dissection;  /* TRUE if we have to dissect each packet */
-static gboolean verbose;
-static gboolean print_hex;
+static gboolean do_dissection;     /* TRUE if we have to dissect each packet */
+static gboolean print_packet_info; /* TRUE if we're to print packet information */
+static gint print_summary = -1;    /* TRUE if we're to print packet summary information */
+static gboolean print_details;     /* TRUE if we're to print packet details information */
+static gboolean print_hex;         /* TRUE if we're to print hex/ascci information */
 static gboolean line_buffered;
+static gboolean really_quiet = FALSE;
 
 static print_format_e print_format = PR_FMT_TEXT;
 static print_stream_t *print_stream;
@@ -134,15 +141,16 @@ static print_stream_t *print_stream;
 static output_fields_t* output_fields  = NULL;
 
 /* The line separator used between packets, changeable via the -S option */
-static char *separator = "";
+static const char *separator = "";
 
 #ifdef HAVE_LIBPCAP
 /*
  * TRUE if we're to print packet counts to keep track of captured packets.
  */
-static gboolean print_packet_counts;
+static gboolean print_packet_counts = TRUE;
 
 static capture_options global_capture_opts;
+static capture_session global_capture_session;
 
 #ifdef SIGINFO
 static gboolean infodelay;      /* if TRUE, don't print capture info in SIGINFO handler */
@@ -163,8 +171,8 @@ static void report_counts_siginfo(int);
 
 static int load_cap_file(capture_file *, char *, int, gboolean, int, gint64);
 static gboolean process_packet(capture_file *cf, gint64 offset,
-    const struct wtap_pkthdr *whdr, union wtap_pseudo_header *pseudo_header,
-    const guchar *pd, gboolean filtering_tap_listeners, guint tap_flags);
+    struct wtap_pkthdr *whdr, const guchar *pd,
+    gboolean filtering_tap_listeners, guint tap_flags);
 static void show_capture_file_io_error(const char *, int, gboolean);
 static void show_print_file_io_error(int err);
 static gboolean write_preamble(capture_file *cf);
@@ -203,11 +211,11 @@ string_elem_print(gpointer data, gpointer not_used _U_)
 
 static void
 list_capture_types(void) {
-  int i;
+  int                 i;
   struct string_elem *captypes;
-  GSList *list = NULL;
+  GSList             *list = NULL;
 
-  captypes = g_malloc(sizeof(struct string_elem) * WTAP_NUM_FILE_TYPES);
+  captypes = g_new(struct string_elem, WTAP_NUM_FILE_TYPES);
 
   fprintf(stderr, "tshark: The available capture file types for the \"-F\" flag are:\n");
   for (i = 0; i < WTAP_NUM_FILE_TYPES; i++) {
@@ -253,7 +261,7 @@ print_usage(gboolean print_ver)
   fprintf(output, "  -I                       capture in monitor mode, if available\n");
 #endif
 #if defined(_WIN32) || defined(HAVE_PCAP_CREATE)
-  fprintf(output, "  -B <buffer size>         size of kernel buffer (def: 1MB)\n");
+  fprintf(output, "  -B <buffer size>         size of kernel buffer (def: %dMB)\n", DEFAULT_CAPTURE_BUFFER_SIZE);
 #endif
   fprintf(output, "  -y <link type>           link layer type (def: first appropriate)\n");
   fprintf(output, "  -D                       print list of interfaces and exit\n");
@@ -270,7 +278,10 @@ print_usage(gboolean print_ver)
   fprintf(output, "                           filesize:NUM - switch to next file after NUM KB\n");
   fprintf(output, "                              files:NUM - ringbuffer: replace after NUM files\n");
 #endif  /* HAVE_LIBPCAP */
-
+#ifdef HAVE_PCAP_REMOTE
+  fprintf(output, "RPCAP options:\n");
+  fprintf(output, "  -A <user>:<password>     use RPCAP password authentication\n");
+#endif
   /*fprintf(output, "\n");*/
   fprintf(output, "Input file:\n");
   fprintf(output, "  -r <infile>              set the filename to read from (no pipes or stdin!)\n");
@@ -278,7 +289,8 @@ print_usage(gboolean print_ver)
   fprintf(output, "\n");
   fprintf(output, "Processing:\n");
   fprintf(output, "  -2                       perform a two-pass analysis\n");
-  fprintf(output, "  -R <read filter>         packet filter in Wireshark display filter syntax\n");
+  fprintf(output, "  -R <read filter>         packet Read filter in Wireshark display filter syntax\n");
+  fprintf(output, "  -Y <display filter>      packet displaY filter in Wireshark display filter syntax\n");
   fprintf(output, "  -n                       disable all name resolutions (def: all enabled)\n");
   fprintf(output, "  -N <name resolve flags>  enable specific name resolution(s): \"mntC\"\n");
   fprintf(output, "  -d %s ...\n", decode_as_arg_template);
@@ -297,12 +309,12 @@ print_usage(gboolean print_ver)
   fprintf(output, "  -V                       add output of packet tree        (Packet Details)\n");
   fprintf(output, "  -O <protocols>           Only show packet details of these protocols, comma\n");
   fprintf(output, "                           separated\n");
-  fprintf(output, "  -P                       print packets even when writing to a file\n");
+  fprintf(output, "  -P                       print packet summary even when writing to a file\n");
   fprintf(output, "  -S <separator>           the line separator to print between packets\n");
   fprintf(output, "  -x                       add output of hex and ASCII dump (Packet Bytes)\n");
   fprintf(output, "  -T pdml|ps|psml|text|fields\n");
   fprintf(output, "                           format of text output (def: text)\n");
-  fprintf(output, "  -e <field>               field to print if -Tfields selected (e.g. tcp.port);\n");
+  fprintf(output, "  -e <field>               field to print if -Tfields selected (e.g. tcp.port, col.Info);\n");
   fprintf(output, "                           this option can be repeated to print multiple fields\n");
   fprintf(output, "  -E<fieldsoption>=<value> set options for output when -Tfields selected:\n");
   fprintf(output, "     header=y|n            switch headers on and off\n");
@@ -311,10 +323,12 @@ print_usage(gboolean print_ver)
   fprintf(output, "     aggregator=,|/s|<char> select comma, space, printable character as\n");
   fprintf(output, "                           aggregator\n");
   fprintf(output, "     quote=d|s|n           select double, single, no quotes for values\n");
-  fprintf(output, "  -t ad|a|r|d|dd|e         output format of time stamps (def: r: rel. to first)\n");
+  fprintf(output, "  -t a|ad|d|dd|e|r|u|ud    output format of time stamps (def: r: rel. to first)\n");
   fprintf(output, "  -u s|hms                 output format of seconds (def: s: seconds)\n");
   fprintf(output, "  -l                       flush standard output after each packet\n");
   fprintf(output, "  -q                       be more quiet on stdout (e.g. when using statistics)\n");
+  fprintf(output, "  -Q                       only log true errors to stderr (quieter than -q)\n");
+  fprintf(output, "  -g                       enable group read access on the output file(s)\n");
   fprintf(output, "  -W n                     Save extra information in the file, if supported.\n");
   fprintf(output, "                           n = write network address resolution information\n");
   fprintf(output, "  -X <key>:<value>         eXtension options, see the man page for details\n");
@@ -344,9 +358,7 @@ glossary_option_help(void)
   fprintf(output, "Usage: tshark -G [report]\n");
   fprintf(output, "\n");
   fprintf(output, "Glossary table reports:\n");
-  fprintf(output, "  -G [fields]              dump glossary in original format and exit\n");
-  fprintf(output, "  -G fields2               dump glossary in format 2 and exit\n");
-  fprintf(output, "  -G fields3               dump glossary in format 3 and exit\n");
+  fprintf(output, "  -G fields                dump fields glossary and exit\n");
   fprintf(output, "  -G protocols             dump protocols in registration database and exit\n");
   fprintf(output, "  -G values                dump value, range, true/false strings and exit\n");
   fprintf(output, "  -G ftypes                dump field type basic and descriptive names\n");
@@ -357,7 +369,6 @@ glossary_option_help(void)
   fprintf(output, "  -G defaultprefs          dump default preferences and exit\n");
   fprintf(output, "  -G currentprefs          dump current preferences and exit\n");
   fprintf(output, "\n");
-
 }
 
 /*
@@ -369,7 +380,11 @@ static void
 display_dissector_table_names(const char *table_name, const char *ui_name,
                               gpointer output)
 {
-  fprintf((FILE *)output, "\t%s (%s)\n", table_name, ui_name);
+  if ((prev_display_dissector_name == NULL) ||
+      (strcmp(prev_display_dissector_name, table_name) != 0)) {
+     fprintf((FILE *)output, "\t%s (%s)\n", table_name, ui_name);
+     prev_display_dissector_name = table_name;
+  }
 }
 
 /*
@@ -380,9 +395,9 @@ display_dissector_table_names(const char *table_name, const char *ui_name,
 static void
 display_dissector_names(const gchar *table _U_, gpointer handle, gpointer output)
 {
-  int                proto_id;
-  const gchar*       proto_filter_name;
-  const gchar*       proto_ui_name;
+  int          proto_id;
+  const gchar *proto_filter_name;
+  const gchar *proto_ui_name;
 
   proto_id = dissector_handle_get_protocol_index((dissector_handle_t)handle);
 
@@ -392,9 +407,13 @@ display_dissector_names(const gchar *table _U_, gpointer handle, gpointer output
     g_assert(proto_filter_name != NULL);
     g_assert(proto_ui_name != NULL);
 
-    fprintf((FILE *)output, "\t%s (%s)\n",
-            proto_filter_name,
-            proto_ui_name);
+    if ((prev_display_dissector_name == NULL) ||
+        (strcmp(prev_display_dissector_name, proto_filter_name) != 0)) {
+      fprintf((FILE *)output, "\t%s (%s)\n",
+              proto_filter_name,
+              proto_ui_name);
+       prev_display_dissector_name = proto_filter_name;
+    }
   }
 }
 
@@ -422,9 +441,9 @@ static void
 find_protocol_name_func(const gchar *table _U_, gpointer handle, gpointer user_data)
 
 {
-  int                         proto_id;
-  const gchar                *protocol_filter_name;
-  protocol_name_search_t      search_info;
+  int                     proto_id;
+  const gchar            *protocol_filter_name;
+  protocol_name_search_t  search_info;
 
   g_assert(handle);
 
@@ -445,6 +464,16 @@ find_protocol_name_func(const gchar *table _U_, gpointer handle, gpointer user_d
   }
 }
 
+/*
+ * Allow dissector key names to be sorted alphabetically
+ */
+
+static gint
+compare_dissector_key_name(gconstpointer dissector_a, gconstpointer dissector_b)
+{
+  return strcmp((const char*)dissector_a, (const char*)dissector_b);
+}
+
 /*
  * Print all layer type names supported.
  * We send the output to the stream described by the handle output.
@@ -454,7 +483,8 @@ static void
 fprint_all_layer_types(FILE *output)
 
 {
-  dissector_all_tables_foreach_table(display_dissector_table_names, (gpointer)output);
+  prev_display_dissector_name = NULL;
+  dissector_all_tables_foreach_table(display_dissector_table_names, (gpointer)output, (GCompareFunc)compare_dissector_key_name);
 }
 
 /*
@@ -467,6 +497,7 @@ static void
 fprint_all_protocols_for_layer_types(FILE *output, gchar *table_name)
 
 {
+  prev_display_dissector_name = NULL;
   dissector_table_foreach_handle(table_name,
                                  display_dissector_names,
                                  (gpointer)output);
@@ -485,7 +516,7 @@ static gboolean
 add_decode_as(const gchar *cl_param)
 {
   gchar                        *table_name;
-  guint32                       selector;
+  guint32                       selector, selector2;
   gchar                        *decoded_param;
   gchar                        *remaining_param;
   gchar                        *selector_str;
@@ -494,6 +525,8 @@ add_decode_as(const gchar *cl_param)
   dissector_table_t             table_matching;
   ftenum_t                      dissector_table_selector_type;
   struct protocol_name_search   user_protocol_name;
+  guint64                       i;
+  char                          op;
 
   /* The following code will allocate and copy the command-line options in a string pointed by decoded_param */
 
@@ -588,10 +621,35 @@ add_decode_as(const gchar *cl_param)
     /* The selector for this table is an unsigned number.  Parse it as such.
        There's no need to remove leading and trailing spaces from the
        selector number string, because sscanf will do that for us. */
-    if ( sscanf(selector_str, "%u", &selector) != 1 ) {
-      cmdarg_err("Invalid selector number \"%s\"", selector_str);
-      g_free(decoded_param);
-      return FALSE;
+    switch (sscanf(selector_str, "%u%c%u", &selector, &op, &selector2)) {
+      case 1:
+        op = '\0';
+        break;
+      case 3:
+        if (op != ':' && op != '-') {
+            cmdarg_err("Invalid selector numeric range \"%s\"", selector_str);
+            g_free(decoded_param);
+            return FALSE;
+        }
+        if (op == ':') {
+            if ((selector2 == 0) || ((guint64)selector + selector2 - 1) > G_MAXUINT32) {
+                cmdarg_err("Invalid selector numeric range \"%s\"", selector_str);
+                g_free(decoded_param);
+                return FALSE;
+            }
+        }
+        else if (selector2 < selector) {
+            /* We could swap them for the user, but maybe it's better to call
+             * this out as an error in case it's not what was intended? */
+            cmdarg_err("Invalid selector numeric range \"%s\"", selector_str);
+            g_free(decoded_param);
+            return FALSE;
+        }
+        break;
+      default:
+        cmdarg_err("Invalid selector number \"%s\"", selector_str);
+        g_free(decoded_param);
+        return FALSE;
     }
     break;
 
@@ -688,7 +746,17 @@ add_decode_as(const gchar *cl_param)
   case FT_UINT24:
   case FT_UINT32:
     /* The selector for this table is an unsigned number. */
-    dissector_change_uint(table_name, selector, dissector_matching);
+    if (op == '\0') {
+      dissector_change_uint(table_name, selector, dissector_matching);
+    } else if (op == ':') {
+      for (i = selector; i < (guint64)selector + selector2; i++) {
+        dissector_change_uint(table_name, (guint32)i, dissector_matching);
+      }
+    } else { /* op == '-' */
+      for (i = selector; i <= selector2; i++) {
+        dissector_change_uint(table_name, (guint32)i, dissector_matching);
+      }
+    }
     break;
 
   case FT_STRING:
@@ -723,7 +791,7 @@ tshark_log_handler (const gchar *log_domain, GLogLevelFlags log_level,
            ERROR and CRITICAL level messages so the current code is a behavioral
            change.  The current behavior is the same as in Wireshark.
   */
-  if((log_level & G_LOG_LEVEL_MASK & prefs.console_log_level) == 0 &&
+  if ((log_level & G_LOG_LEVEL_MASK & prefs.console_log_level) == 0 &&
      prefs.console_log_level != 0) {
     return;
   }
@@ -751,6 +819,7 @@ output_file_description(const char *fname)
 static void
 print_current_user(void) {
   gchar *cur_user, *cur_group;
+
   if (started_with_special_privs()) {
     cur_user = get_cur_username();
     cur_group = get_cur_groupname();
@@ -794,6 +863,8 @@ show_version(GString *comp_info_str, GString *runtime_info_str)
 int
 main(int argc, char *argv[])
 {
+  GString             *comp_info_str;
+  GString             *runtime_info_str;
   char                *init_progfile_dir_error;
   int                  opt;
   gboolean             arg_error = FALSE;
@@ -816,8 +887,6 @@ main(int argc, char *argv[])
   int                  status;
   GList               *if_list;
   gchar               *err_str;
-  guint                i;
-  interface_options    interface_opts;
 #else
   gboolean             capture_option_specified = FALSE;
 #endif
@@ -830,16 +899,23 @@ main(int argc, char *argv[])
   volatile gboolean    out_file_name_res = FALSE;
   gchar               *volatile cf_name = NULL;
   gchar               *rfilter = NULL;
+  gchar               *dfilter = NULL;
 #ifdef HAVE_PCAP_OPEN_DEAD
   struct bpf_program   fcode;
 #endif
   dfilter_t           *rfcode = NULL;
+  dfilter_t           *dfcode = NULL;
   e_prefs             *prefs_p;
   char                 badopt;
-  GLogLevelFlags       log_flags;
+  int                  log_flags;
   int                  optind_initial;
   gchar               *output_only = NULL;
 
+#ifdef HAVE_PCAP_REMOTE
+#define OPTSTRING_A "A:"
+#else
+#define OPTSTRING_A ""
+#endif
 #ifdef HAVE_LIBPCAP
 #if defined(_WIN32) || defined(HAVE_PCAP_CREATE)
 #define OPTSTRING_B "B:"
@@ -856,12 +932,29 @@ main(int argc, char *argv[])
 #define OPTSTRING_I ""
 #endif
 
-#define OPTSTRING "2a:A:b:" OPTSTRING_B "c:C:d:De:E:f:F:G:hH:i:" OPTSTRING_I "K:lLnN:o:O:pPqr:R:s:S:t:T:u:vVw:W:xX:y:z:"
+#define OPTSTRING "2a:" OPTSTRING_A "b:" OPTSTRING_B "c:C:d:De:E:f:F:gG:hH:i:" OPTSTRING_I "K:lLnN:o:O:pPqQr:R:s:S:t:T:u:vVw:W:xX:y:Y:z:"
 
   static const char    optstring[] = OPTSTRING;
 
+  /* Assemble the compile-time version information string */
+  comp_info_str = g_string_new("Compiled ");
+  get_compiled_version_info(comp_info_str, NULL, epan_get_compiled_version_info);
+
+  /* Assemble the run-time version information string */
+  runtime_info_str = g_string_new("Running ");
+  get_runtime_version_info(runtime_info_str, NULL);
+
+  /* Add it to the information to be reported on a crash. */
+  ws_add_crash_info("TShark " VERSION "%s\n"
+         "\n"
+         "%s"
+         "\n"
+         "%s",
+      wireshark_svnversion, comp_info_str->str, runtime_info_str->str);
+
 #ifdef _WIN32
   arg_list_utf_16to8(argc, argv);
+  create_app_running_mutex();
 #if !GLIB_CHECK_VERSION(2,31,0)
   g_thread_init(NULL);
 #endif
@@ -898,6 +991,24 @@ main(int argc, char *argv[])
         return 1;
       }
       break;
+    case 'P':        /* Print packet summary info even when writing to a file */
+      print_packet_info = TRUE;
+      print_summary = TRUE;
+      break;
+    case 'O':        /* Only output these protocols */
+      output_only = g_strdup(optarg);
+      /* FALLTHROUGH */
+    case 'V':        /* Verbose */
+      print_details = TRUE;
+      print_packet_info = TRUE;
+      break;
+    case 'x':        /* Print packet data in hex (and ASCII) */
+      print_hex = TRUE;
+      /*  The user asked for hex output, so let's ensure they get it,
+       *  even if they're writing to a file.
+       */
+      print_packet_info = TRUE;
+      break;
     case 'X':
       ex_opt_add(optarg);
       break;
@@ -906,6 +1017,15 @@ main(int argc, char *argv[])
     }
   }
 
+  /*
+   * Print packet summary information is the default, unless either -V or -x
+   * were specified and -P was not.  Note that this is new behavior, which
+   * allows for the possibility of printing only hex/ascii output without
+   * necessarily requiring that either the summary or details be printed too.
+   */
+  if (print_summary == -1)
+    print_summary = (print_details || print_hex) ? FALSE : TRUE;
+
   optind = optind_initial;
   opterr = 1;
 
@@ -923,25 +1043,26 @@ main(int argc, char *argv[])
                     G_LOG_FLAG_FATAL|G_LOG_FLAG_RECURSION;
 
   g_log_set_handler(NULL,
-                    log_flags,
+                    (GLogLevelFlags)log_flags,
                     tshark_log_handler, NULL /* user_data */);
   g_log_set_handler(LOG_DOMAIN_MAIN,
-                    log_flags,
+                    (GLogLevelFlags)log_flags,
                     tshark_log_handler, NULL /* user_data */);
 
 #ifdef HAVE_LIBPCAP
   g_log_set_handler(LOG_DOMAIN_CAPTURE,
-                    log_flags,
+                    (GLogLevelFlags)log_flags,
                     tshark_log_handler, NULL /* user_data */);
   g_log_set_handler(LOG_DOMAIN_CAPTURE_CHILD,
-                    log_flags,
+                    (GLogLevelFlags)log_flags,
                     tshark_log_handler, NULL /* user_data */);
 #endif
 
   initialize_funnel_ops();
 
 #ifdef HAVE_LIBPCAP
-  capture_opts_init(&global_capture_opts, &cfile);
+  capture_opts_init(&global_capture_opts);
+  capture_session_init(&global_capture_session, (void *)&cfile);
 #endif
 
   timestamp_set_type(TS_RELATIVE);
@@ -967,10 +1088,6 @@ main(int argc, char *argv[])
 #endif
   register_all_tap_listeners();
 
-  /* Now register the preferences for any non-dissector modules.
-     We must do that before we read the preferences as well. */
-  prefs_register_modules();
-
   /* If invoked with the "-G" flag, we dump out information based on
      the argument to the "-G" flag; if no argument is specified,
      for backwards compatibility we dump out a glossary of display
@@ -983,14 +1100,10 @@ main(int argc, char *argv[])
     proto_initialize_all_prefixes();
 
     if (argc == 2)
-      proto_registrar_dump_fields(1);
+      proto_registrar_dump_fields();
     else {
       if (strcmp(argv[2], "fields") == 0)
-        proto_registrar_dump_fields(1);
-      else if (strcmp(argv[2], "fields2") == 0)
-        proto_registrar_dump_fields(2);
-      else if (strcmp(argv[2], "fields3") == 0)
-        proto_registrar_dump_fields(3);
+        proto_registrar_dump_fields();
       else if (strcmp(argv[2], "protocols") == 0)
         proto_registrar_dump_protocols();
       else if (strcmp(argv[2], "values") == 0)
@@ -1049,9 +1162,6 @@ main(int argc, char *argv[])
     pf_path = NULL;
   }
 
-  /* Set the name resolution code's flags from the preferences. */
-  gbl_resolv_flags = prefs_p->name_resolve;
-
   /* Read the disabled protocols file. */
   read_disabled_protos_list(&gdp_path, &gdp_open_errno, &gdp_read_errno,
                             &dp_path, &dp_open_errno, &dp_read_errno);
@@ -1099,8 +1209,12 @@ main(int argc, char *argv[])
     case 'b':        /* Ringbuffer option */
     case 'c':        /* Capture x packets */
     case 'f':        /* capture filter */
+    case 'g':        /* enable group read access on file(s) */
     case 'i':        /* Use interface x */
     case 'p':        /* Don't capture in promiscuous mode */
+#ifdef HAVE_PCAP_REMOTE
+    case 'A':        /* Authentication */
+#endif
 #ifdef HAVE_PCAP_CREATE
     case 'I':        /* Capture in monitor mode, if available */
 #endif
@@ -1112,7 +1226,7 @@ main(int argc, char *argv[])
 #endif /* _WIN32 or HAVE_PCAP_CREATE */
 #ifdef HAVE_LIBPCAP
       status = capture_opts_add_opt(&global_capture_opts, opt, optarg, &start_capture);
-      if(status != 0) {
+      if (status != 0) {
         return status;
       }
 #else
@@ -1134,7 +1248,7 @@ main(int argc, char *argv[])
 #endif
     case 'D':        /* Print a list of capture devices and exit */
 #ifdef HAVE_LIBPCAP
-      if_list = capture_interface_list(&err, &err_str);
+      if_list = capture_interface_list(&err, &err_str,NULL);
       if (if_list == NULL) {
         switch (err) {
         case CANT_GET_INTERFACE_LIST:
@@ -1163,7 +1277,7 @@ main(int argc, char *argv[])
       break;
     case 'E':
       /* Field option */
-      if(!output_fields_set_option(output_fields, optarg)) {
+      if (!output_fields_set_option(output_fields, optarg)) {
         cmdarg_err("\"%s\" is not a valid field output option=value pair.", optarg);
         output_fields_list_options(stderr);
         return 1;
@@ -1179,11 +1293,15 @@ main(int argc, char *argv[])
       break;
     case 'W':        /* Select extra information to save in our capture file */
       /* This is patterned after the -N flag which may not be the best idea. */
-      if (strchr(optarg, 'n'))
+      if (strchr(optarg, 'n')) {
         out_file_name_res = TRUE;
+      } else {
+        cmdarg_err("Invalid -W argument \"%s\"", optarg);
+        return 1;
+      }
       break;
     case 'H':        /* Read address to name mappings from a hosts file */
-      if (! read_hosts_file(optarg))
+      if (! add_hosts_file(optarg))
       {
         cmdarg_err("Can't read host entries from \"%s\"", optarg);
         return 1;
@@ -1219,11 +1337,12 @@ main(int argc, char *argv[])
 #endif
       break;
     case 'n':        /* No name resolution */
-      gbl_resolv_flags = RESOLV_NONE;
+      gbl_resolv_flags.mac_name = FALSE;
+      gbl_resolv_flags.network_name = FALSE;
+      gbl_resolv_flags.transport_name = FALSE;
+      gbl_resolv_flags.concurrent_dns = FALSE;
       break;
     case 'N':        /* Select what types of addresses/port #s to resolve */
-      if (gbl_resolv_flags == RESOLV_ALL)
-        gbl_resolv_flags = RESOLV_NONE;
       badopt = string_to_name_resolve(optarg, &gbl_resolv_flags);
       if (badopt != '\0') {
         cmdarg_err("-N specifies unknown resolving option '%c';",
@@ -1253,15 +1372,19 @@ main(int argc, char *argv[])
     case 'q':        /* Quiet */
       quiet = TRUE;
       break;
+    case 'Q':        /* Really quiet */
+      quiet = TRUE;
+      really_quiet = TRUE;
+      break;
     case 'r':        /* Read capture file x */
       cf_name = g_strdup(optarg);
       break;
     case 'R':        /* Read file filter */
       rfilter = optarg;
       break;
-    case 'P':        /* Print packets even when writing to a file */
-      print_packet_info = TRUE;
-      break;
+    case 'P':
+        /* already processed; just ignore it now */
+        break;
     case 'S':        /* Set the line Separator to be printed between packets */
       separator = strdup(optarg);
       break;
@@ -1285,8 +1408,9 @@ main(int argc, char *argv[])
       else {
         cmdarg_err("Invalid time stamp type \"%s\"",
                    optarg);
-        cmdarg_err_cont("It must be \"r\" for relative, \"a\" for absolute,");
-        cmdarg_err_cont("\"ad\" for absolute with date, or \"d\" for delta.");
+        cmdarg_err_cont("It must be \"a\" for absolute, \"ad\" for absolute with date, \"d\" for delta,");
+        cmdarg_err_cont("\"dd\" for delta displayed, \"e\" for epoch, \"r\" for relative, \"u\" for UTC, ");
+        cmdarg_err_cont("or \"ud\" for UTC with date.");
         return 1;
       }
       break;
@@ -1299,13 +1423,16 @@ main(int argc, char *argv[])
         print_format = PR_FMT_PS;
       } else if (strcmp(optarg, "pdml") == 0) {
         output_action = WRITE_XML;
-        verbose = TRUE;
+        print_details = TRUE;   /* Need details */
+        print_summary = FALSE;  /* Don't allow summary */
       } else if (strcmp(optarg, "psml") == 0) {
         output_action = WRITE_XML;
-        verbose = FALSE;
-      } else if(strcmp(optarg, "fields") == 0) {
+        print_details = FALSE;  /* Don't allow details */
+        print_summary = TRUE;   /* Need summary */
+      } else if (strcmp(optarg, "fields") == 0) {
         output_action = WRITE_FIELDS;
-        verbose = TRUE; /* Need full tree info */
+        print_details = TRUE;   /* Need full tree info */
+        print_summary = FALSE;  /* Don't allow summary */
       } else {
         cmdarg_err("Invalid -T parameter.");
         cmdarg_err_cont("It must be \"ps\", \"text\", \"pdml\", \"psml\" or \"fields\".");
@@ -1325,40 +1452,31 @@ main(int argc, char *argv[])
       break;
     case 'v':         /* Show version and exit */
     {
-      GString             *comp_info_str;
-      GString             *runtime_info_str;
-      /* Assemble the compile-time version information string */
-      comp_info_str = g_string_new("Compiled ");
-      get_compiled_version_info(comp_info_str, NULL, epan_get_compiled_version_info);
-
-      /* Assemble the run-time version information string */
-      runtime_info_str = g_string_new("Running ");
-      get_runtime_version_info(runtime_info_str, NULL);
       show_version(comp_info_str, runtime_info_str);
       g_string_free(comp_info_str, TRUE);
       g_string_free(runtime_info_str, TRUE);
+      /* We don't really have to cleanup here, but it's a convenient way to test
+       * start-up and shut-down of the epan library without any UI-specific
+       * cruft getting in the way. Makes the results of running
+       * $ ./tools/valgrind-wireshark -n
+       * much more useful. */
+      epan_cleanup();
       return 0;
-      break;
     }
     case 'O':        /* Only output these protocols */
-      output_only = g_strdup(optarg);
-      /* FALLTHROUGH */
+      /* already processed; just ignore it now */
+      break;
     case 'V':        /* Verbose */
-      verbose = TRUE;
-      /*  The user asked for a verbose output, so let's ensure they get it,
-       *  even if they're writing to a file.
-       */
-      print_packet_info = TRUE;
+      /* already processed; just ignore it now */
       break;
     case 'x':        /* Print packet data in hex (and ASCII) */
-      print_hex = TRUE;
-      /*  The user asked for hex output, so let's ensure they get it,
-       *  even if they're writing to a file.
-       */
-      print_packet_info = TRUE;
+      /* already processed; just ignore it now */
       break;
     case 'X':
       break;
+    case 'Y':
+      dfilter = optarg;
+      break;
     case 'z':
       /* We won't call the init function for the stat this soon
          as it would disallow MATE's fields (which are registered
@@ -1366,7 +1484,12 @@ main(int argc, char *argv[])
          part of a tap filter.  Instead, we just add the argument
          to a list of stat arguments. */
       if (!process_stat_cmd_arg(optarg)) {
-        cmdarg_err("invalid -z argument.");
+        if (strcmp("help", optarg)==0) {
+          fprintf(stderr, "tshark: The available statistics for the \"-z\" option are:\n");
+          list_stat_cmd_args();
+          return 0;
+        }
+        cmdarg_err("Invalid -z argument \"%s\".", optarg);
         cmdarg_err_cont("  -z argument must be one of :");
         list_stat_cmd_args();
         return 1;
@@ -1387,37 +1510,40 @@ main(int argc, char *argv[])
   }
 
   /* If we specified output fields, but not the output field type... */
-  if(WRITE_FIELDS != output_action && 0 != output_fields_num_fields(output_fields)) {
+  if (WRITE_FIELDS != output_action && 0 != output_fields_num_fields(output_fields)) {
         cmdarg_err("Output fields were specified with \"-e\", "
             "but \"-Tfields\" was not specified.");
         return 1;
-  } else if(WRITE_FIELDS == output_action && 0 == output_fields_num_fields(output_fields)) {
+  } else if (WRITE_FIELDS == output_action && 0 == output_fields_num_fields(output_fields)) {
         cmdarg_err("\"-Tfields\" was specified, but no fields were "
                     "specified with \"-e\".");
 
         return 1;
   }
 
-  /* If no capture filter or read filter has been specified, and there are
+  /* If no capture filter or display filter has been specified, and there are
      still command-line arguments, treat them as the tokens of a capture
-     filter (if no "-r" flag was specified) or a read filter (if a "-r"
+     filter (if no "-r" flag was specified) or a display filter (if a "-r"
      flag was specified. */
   if (optind < argc) {
     if (cf_name != NULL) {
-      if (rfilter != NULL) {
-        cmdarg_err("Read filters were specified both with \"-R\" "
+      if (dfilter != NULL) {
+        cmdarg_err("Display filters were specified both with \"-d\" "
             "and with additional command-line arguments.");
         return 1;
       }
-      rfilter = get_args_as_string(argc, argv, optind);
+      dfilter = get_args_as_string(argc, argv, optind);
     } else {
 #ifdef HAVE_LIBPCAP
+      guint i;
+
       if (global_capture_opts.default_options.cfilter) {
         cmdarg_err("A default capture filter was specified both with \"-f\""
             " and with additional command-line arguments.");
         return 1;
       }
       for (i = 0; i < global_capture_opts.ifaces->len; i++) {
+        interface_options interface_opts;
         interface_opts = g_array_index(global_capture_opts.ifaces, interface_options, i);
         if (interface_opts.cfilter == NULL) {
           interface_opts.cfilter = get_args_as_string(argc, argv, optind);
@@ -1493,7 +1619,7 @@ main(int argc, char *argv[])
   if (output_only != NULL) {
     char *ps;
 
-    if (!verbose) {
+    if (!print_details) {
       cmdarg_err("-O requires -V");
       return 1;
     }
@@ -1504,6 +1630,11 @@ main(int argc, char *argv[])
     }
   }
 
+  if (rfilter != NULL && !perform_two_pass_analysis) {
+    /* Just a warning, so we don't return */
+    cmdarg_err("-R without -2 is deprecated. For single-pass filtering use -Y.");
+  }
+
 #ifdef HAVE_LIBPCAP
   if (list_link_layer_types) {
     /* We're supposed to list the link-layer types for an interface;
@@ -1588,12 +1719,16 @@ main(int argc, char *argv[])
             return 1;
           }
         }
-        /* Currently, we don't support read filters when capturing
+        /* Currently, we don't support read or display filters when capturing
            and saving the packets. */
         if (rfilter != NULL) {
           cmdarg_err("Read filters aren't supported when capturing and saving the captured packets.");
           return 1;
         }
+        if (dfilter != NULL) {
+          cmdarg_err("Display filters aren't supported when capturing and saving the captured packets.");
+          return 1;
+        }
       } else {
         /* They didn't specify a "-w" flag, so we won't be saving to a
            capture file.  Check for options that only make sense if
@@ -1669,7 +1804,7 @@ main(int argc, char *argv[])
         if (pc != NULL) {
           if (pcap_compile(pc, &fcode, rfilter, 0, 0) != -1) {
             cmdarg_err_cont(
-              "  Note: That display filter code looks like a valid capture filter;");
+              "  Note: That read filter code looks like a valid capture filter;");
             cmdarg_err_cont(
               "        maybe you mixed them up?");
           }
@@ -1682,6 +1817,31 @@ main(int argc, char *argv[])
   }
   cfile.rfcode = rfcode;
 
+  if (dfilter != NULL) {
+    if (!dfilter_compile(dfilter, &dfcode)) {
+      cmdarg_err("%s", dfilter_error_msg);
+      epan_cleanup();
+#ifdef HAVE_PCAP_OPEN_DEAD
+      {
+        pcap_t *pc;
+
+        pc = pcap_open_dead(DLT_EN10MB, MIN_PACKET_SIZE);
+        if (pc != NULL) {
+          if (pcap_compile(pc, &fcode, dfilter, 0, 0) != -1) {
+            cmdarg_err_cont(
+              "  Note: That display filter code looks like a valid capture filter;");
+            cmdarg_err_cont(
+              "        maybe you mixed them up?");
+          }
+          pcap_close(pc);
+        }
+      }
+#endif
+      return 2;
+    }
+  }
+  cfile.dfcode = dfcode;
+
   if (print_packet_info) {
     /* If we're printing as text or PostScript, we have
        to create a print stream. */
@@ -1708,8 +1868,10 @@ main(int argc, char *argv[])
 
         we're using a read filter on the packets;
 
+        we're using a display filter on the packets;
+
         we're using any taps that need dissection. */
-  do_dissection = print_packet_info || rfcode || tap_listeners_require_dissection();
+  do_dissection = print_packet_info || rfcode || dfcode || tap_listeners_require_dissection();
 
   if (cf_name) {
     /*
@@ -1782,37 +1944,37 @@ main(int argc, char *argv[])
     }
   } else {
     /* No capture file specified, so we're supposed to do a live capture
-       (or get a list of link-layer types for a live capture device);
+       or get a list of link-layer types for a live capture device;
        do we have support for live captures? */
 #ifdef HAVE_LIBPCAP
-    /* trim the interface name and exit if that failed */
-    if (!capture_opts_trim_iface(&global_capture_opts,
-        (prefs_p->capture_device) ? get_if_name(prefs_p->capture_device) : NULL)) {
-        return 2;
-    }
+    /* if no interface was specified, pick a default */
+    exit_status = capture_opts_default_iface_if_necessary(&global_capture_opts,
+        ((prefs_p->capture_device) && (*prefs_p->capture_device != '\0')) ? get_if_name(prefs_p->capture_device) : NULL);
+    if (exit_status != 0)
+        return exit_status;
 
     /* if requested, list the link layer types and exit */
     if (list_link_layer_types) {
         guint i;
-        interface_options interface_opts;
 
         /* Get the list of link-layer types for the capture devices. */
         for (i = 0; i < global_capture_opts.ifaces->len; i++) {
-            if_capabilities_t *caps;
-
-            interface_opts = g_array_index(global_capture_opts.ifaces, interface_options, i);
-            caps = capture_get_if_capabilities(interface_opts.name, interface_opts.monitor_mode, &err_str);
-            if (caps == NULL) {
-                cmdarg_err("%s", err_str);
-                g_free(err_str);
-                return 2;
-            }
-            if (caps->data_link_types == NULL) {
-                cmdarg_err("The capture device \"%s\" has no data link types.", interface_opts.name);
-                return 2;
-            }
-            capture_opts_print_if_capabilities(caps, interface_opts.name, interface_opts.monitor_mode);
-            free_if_capabilities(caps);
+          interface_options  interface_opts;
+          if_capabilities_t *caps;
+
+          interface_opts = g_array_index(global_capture_opts.ifaces, interface_options, i);
+          caps = capture_get_if_capabilities(interface_opts.name, interface_opts.monitor_mode, &err_str, NULL);
+          if (caps == NULL) {
+            cmdarg_err("%s", err_str);
+            g_free(err_str);
+            return 2;
+          }
+          if (caps->data_link_types == NULL) {
+            cmdarg_err("The capture device \"%s\" has no data link types.", interface_opts.name);
+            return 2;
+          }
+          capture_opts_print_if_capabilities(caps, interface_opts.name, interface_opts.monitor_mode);
+          free_if_capabilities(caps);
         }
         return 0;
     }
@@ -1850,7 +2012,7 @@ main(int argc, char *argv[])
      * Instead, pass on the exit status from the capture child.
      */
     capture();
-    exit_status = global_capture_opts.fork_child_status;
+    exit_status = global_capture_session.fork_child_status;
 
     if (print_packet_info) {
       if (!write_finale()) {
@@ -1897,13 +2059,13 @@ main(int argc, char *argv[])
 typedef gboolean (*pipe_input_cb_t) (gint source, gpointer user_data);
 
 typedef struct pipe_input_tag {
-  gint                source;
-  gpointer            user_data;
-  int                 *child_process;
-  pipe_input_cb_t     input_cb;
-  guint               pipe_input_id;
+  gint             source;
+  gpointer         user_data;
+  int             *child_process;
+  pipe_input_cb_t  input_cb;
+  guint            pipe_input_id;
 #ifdef _WIN32
-  GMutex              *callback_running;
+  GMutex          *callback_running;
 #endif
 } pipe_input_t;
 
@@ -1915,12 +2077,12 @@ static pipe_input_t pipe_input;
 static gint
 pipe_timer_cb(gpointer data)
 {
-  HANDLE handle;
-  DWORD avail = 0;
-  gboolean result, result1;
-  DWORD childstatus;
+  HANDLE        handle;
+  DWORD         avail        = 0;
+  gboolean      result;
+  DWORD         childstatus;
   pipe_input_t *pipe_input_p = data;
-  gint iterations = 0;
+  gint          iterations   = 0;
 
   g_mutex_lock (pipe_input_p->callback_running);
 
@@ -1934,8 +2096,8 @@ pipe_timer_cb(gpointer data)
     result = PeekNamedPipe(handle, NULL, 0, NULL, &avail, NULL);
 
     /* Get the child process exit status */
-    result1 = GetExitCodeProcess((HANDLE)*(pipe_input_p->child_process),
-                                 &childstatus);
+    GetExitCodeProcess((HANDLE)*(pipe_input_p->child_process),
+                       &childstatus);
 
     /* If the Peek returned an error, or there are bytes to be read
        or the childwatcher thread has terminated then call the normal
@@ -1997,19 +2159,53 @@ pipe_input_set_handler(gint source, gpointer user_data, int *child_process, pipe
 #endif
 }
 
+const nstime_t *
+tshark_get_frame_ts(void *data, guint32 frame_num)
+{
+  capture_file *cf = (capture_file *) data;
+
+  if (ref && ref->num == frame_num)
+    return &ref->abs_ts;
+
+  if (prev_dis && prev_dis->num == frame_num)
+    return &prev_dis->abs_ts;
+
+  if (prev_cap && prev_cap->num == frame_num)
+    return &prev_cap->abs_ts;
+
+  if (cf->frames) {
+     frame_data *fd = frame_data_sequence_find(cf->frames, frame_num);
+
+     return (fd) ? &fd->abs_ts : NULL;
+  }
+
+  return NULL;
+}
+
+epan_t *
+tshark_epan_new(capture_file *cf)
+{
+  epan_t *epan = epan_new();
+
+  epan->data = cf;
+  epan->get_frame_ts = tshark_get_frame_ts;
+  epan->get_interface_name = cap_file_get_interface_name;
+
+  return epan;
+}
 
 #ifdef HAVE_LIBPCAP
 static gboolean
 capture(void)
 {
-  gboolean ret;
-  guint i;
-  GString *str = g_string_new("");
+  gboolean          ret;
+  guint             i;
+  GString          *str = g_string_new("");
 #ifdef USE_TSHARK_SELECT
-  fd_set readfds;
+  fd_set            readfds;
 #endif
 #ifndef _WIN32
-  struct sigaction action, oldaction;
+  struct sigaction  action, oldaction;
 #endif
 
   /*
@@ -2036,10 +2232,9 @@ capture(void)
   relinquish_special_privs_perm();
   print_current_user();
 
-  /* Cleanup all data structures used for dissection. */
-  cleanup_dissection();
-  /* Initialize all data structures used for dissection. */
-  init_dissection();
+  /* Create new dissection section. */
+  epan_free(cfile.epan);
+  cfile.epan = tshark_epan_new(&cfile);
 
 #ifdef _WIN32
   /* Catch a CTRL+C event and, if we get it, clean up and exit. */
@@ -2054,6 +2249,7 @@ capture(void)
      the capture child to finish; it will report that it finished,
      or will exit abnormally, so  we'll stop reading from the sync
      pipe, pick up the exit status, and quit. */
+  memset(&action, 0, sizeof(action));
   action.sa_handler = capture_cleanup;
   action.sa_flags = SA_RESTART;
   sigemptyset(&action.sa_mask);
@@ -2076,7 +2272,7 @@ capture(void)
 #endif /* SIGINFO */
 #endif /* _WIN32 */
 
-  global_capture_opts.state = CAPTURE_PREPARING;
+  global_capture_session.state = CAPTURE_PREPARING;
 
   /* Let the user know which interfaces were chosen. */
   for (i = 0; i < global_capture_opts.ifaces->len; i++) {
@@ -2105,15 +2301,17 @@ capture(void)
               g_string_append_printf(str, "and ");
           }
       }
-      g_string_append_printf(str, "%s", interface_opts.descr);
+      g_string_append_printf(str, "'%s'", interface_opts.descr);
     }
   } else {
     g_string_append_printf(str, "%u interfaces", global_capture_opts.ifaces->len);
   }
-  fprintf(stderr, "Capturing on %s\n", str->str);
+  if (really_quiet == FALSE)
+    fprintf(stderr, "Capturing on %s\n", str->str);
+  fflush(stderr);
   g_string_free(str, TRUE);
 
-  ret = sync_pipe_start(&global_capture_opts);
+  ret = sync_pipe_start(&global_capture_opts, &global_capture_session, NULL);
 
   if (!ret)
     return FALSE;
@@ -2180,16 +2378,9 @@ capture(void)
   return TRUE;
 }
 
-
-/* XXX - move the call to main_window_update() out of capture_sync.c */
-/* dummy for capture_sync.c to make linker happy */
-void main_window_update(void)
-{
-}
-
 /* capture child detected an error */
 void
-capture_input_error_message(capture_options *capture_opts _U_, char *error_msg, char *secondary_error_msg)
+capture_input_error_message(capture_session *cap_session _U_, char *error_msg, char *secondary_error_msg)
 {
   cmdarg_err("%s", error_msg);
   cmdarg_err_cont("%s", secondary_error_msg);
@@ -2198,10 +2389,11 @@ capture_input_error_message(capture_options *capture_opts _U_, char *error_msg,
 
 /* capture child detected an capture filter related error */
 void
-capture_input_cfilter_error_message(capture_options *capture_opts, guint i, char *error_message)
+capture_input_cfilter_error_message(capture_session *cap_session, guint i, char *error_message)
 {
-  dfilter_t   *rfcode = NULL;
-  interface_options interface_opts;
+  capture_options *capture_opts = cap_session->capture_opts;
+  dfilter_t         *rfcode = NULL;
+  interface_options  interface_opts;
 
   g_assert(i < capture_opts->ifaces->len);
   interface_opts = g_array_index(capture_opts->ifaces, interface_options, i);
@@ -2232,27 +2424,28 @@ capture_input_cfilter_error_message(capture_options *capture_opts, guint i, char
 
 /* capture child tells us we have a new (or the first) capture file */
 gboolean
-capture_input_new_file(capture_options *capture_opts, gchar *new_file)
+capture_input_new_file(capture_session *cap_session, gchar *new_file)
 {
+  capture_options *capture_opts = cap_session->capture_opts;
   gboolean is_tempfile;
-  int  err;
+  int      err;
 
-  if(capture_opts->state == CAPTURE_PREPARING) {
+  if (cap_session->state == CAPTURE_PREPARING) {
     g_log(LOG_DOMAIN_CAPTURE, G_LOG_LEVEL_MESSAGE, "Capture started!");
   }
   g_log(LOG_DOMAIN_CAPTURE, G_LOG_LEVEL_MESSAGE, "File: \"%s\"", new_file);
 
-  g_assert(capture_opts->state == CAPTURE_PREPARING || capture_opts->state == CAPTURE_RUNNING);
+  g_assert(cap_session->state == CAPTURE_PREPARING || cap_session->state == CAPTURE_RUNNING);
 
   /* free the old filename */
   if (capture_opts->save_file != NULL) {
 
     /* we start a new capture file, close the old one (if we had one before) */
-    if( ((capture_file *) capture_opts->cf)->state != FILE_CLOSED) {
-      if ( ((capture_file *) capture_opts->cf)->wth != NULL) {
-        wtap_close(((capture_file *) capture_opts->cf)->wth);
+    if ( ((capture_file *) cap_session->cf)->state != FILE_CLOSED) {
+      if ( ((capture_file *) cap_session->cf)->wth != NULL) {
+        wtap_close(((capture_file *) cap_session->cf)->wth);
       }
-      ((capture_file *) capture_opts->cf)->state = FILE_CLOSED;
+      ((capture_file *) cap_session->cf)->state = FILE_CLOSED;
     }
 
     g_free(capture_opts->save_file);
@@ -2266,9 +2459,9 @@ capture_input_new_file(capture_options *capture_opts, gchar *new_file)
   capture_opts->save_file = g_strdup(new_file);
 
   /* if we are in real-time mode, open the new file now */
-  if(do_dissection) {
+  if (do_dissection) {
     /* Attempt to open the capture file and set up to read from it. */
-    switch(cf_open(capture_opts->cf, capture_opts->save_file, is_tempfile, &err)) {
+    switch(cf_open((capture_file *)cap_session->cf, capture_opts->save_file, is_tempfile, &err)) {
     case CF_OK:
       break;
     case CF_ERROR:
@@ -2280,7 +2473,7 @@ capture_input_new_file(capture_options *capture_opts, gchar *new_file)
     }
   }
 
-  capture_opts->state = CAPTURE_RUNNING;
+  cap_session->state = CAPTURE_RUNNING;
 
   return TRUE;
 }
@@ -2288,15 +2481,15 @@ capture_input_new_file(capture_options *capture_opts, gchar *new_file)
 
 /* capture child tells us we have new packets to read */
 void
-capture_input_new_packets(capture_options *capture_opts, int to_read)
+capture_input_new_packets(capture_session *cap_session, int to_read)
 {
-  gboolean     ret;
-  int          err;
+  gboolean      ret;
+  int           err;
   gchar        *err_info;
-  gint64       data_offset;
-  capture_file *cf = capture_opts->cf;
-  gboolean filtering_tap_listeners;
-  guint tap_flags;
+  gint64        data_offset;
+  capture_file *cf = (capture_file *)cap_session->cf;
+  gboolean      filtering_tap_listeners;
+  guint         tap_flags;
 
 #ifdef SIGINFO
   /*
@@ -2313,18 +2506,18 @@ capture_input_new_packets(capture_options *capture_opts, int to_read)
   /* Get the union of the flags for all tap listeners. */
   tap_flags = union_of_tap_listener_flags();
 
-  if(do_dissection) {
+  if (do_dissection) {
     while (to_read-- && cf->wth) {
       wtap_cleareof(cf->wth);
       ret = wtap_read(cf->wth, &err, &err_info, &data_offset);
-      if(ret == FALSE) {
+      if (ret == FALSE) {
         /* read from file failed, tell the capture child to stop */
-        sync_pipe_stop(capture_opts);
+        sync_pipe_stop(cap_session);
         wtap_close(cf->wth);
         cf->wth = NULL;
       } else {
         ret = process_packet(cf, data_offset, wtap_phdr(cf->wth),
-                             wtap_pseudoheader(cf->wth), wtap_buf_ptr(cf->wth),
+                             wtap_buf_ptr(cf->wth),
                              filtering_tap_listeners, tap_flags);
       }
       if (ret != FALSE) {
@@ -2366,10 +2559,10 @@ capture_input_new_packets(capture_options *capture_opts, int to_read)
 static void
 report_counts(void)
 {
-  if (!print_packet_counts) {
+  if ((print_packet_counts == FALSE) && (really_quiet == FALSE)) {
     /* Report the count only if we aren't printing a packet count
        as packets arrive. */
-    fprintf(stderr, "%u packet%s captured\n", packet_count,
+      fprintf(stderr, "%u packet%s captured\n", packet_count,
             plurality(packet_count, "", "s"));
   }
 #ifdef SIGINFO
@@ -2396,7 +2589,7 @@ report_counts_siginfo(int signum _U_)
 
 /* capture child detected any packet drops? */
 void
-capture_input_drops(capture_options *capture_opts _U_, guint32 dropped)
+capture_input_drops(capture_session *cap_session _U_, guint32 dropped)
 {
   if (print_packet_counts) {
     /* We're printing packet counts to stderr.
@@ -2417,17 +2610,19 @@ capture_input_drops(capture_options *capture_opts _U_, guint32 dropped)
  * do the required cleanup.
  */
 void
-capture_input_closed(capture_options *capture_opts, gchar *msg)
+capture_input_closed(capture_session *cap_session, gchar *msg)
 {
+  capture_file *cf = (capture_file *) cap_session->cf;
+
   if (msg != NULL)
     fprintf(stderr, "tshark: %s\n", msg);
 
   report_counts();
 
-  if(capture_opts->cf != NULL && ((capture_file *) capture_opts->cf)->wth != NULL) {
-    wtap_close(((capture_file *) capture_opts->cf)->wth);
-    if(((capture_file *) capture_opts->cf)->user_saved == FALSE) {
-      ws_unlink(((capture_file *) capture_opts->cf)->filename);
+  if (cf != NULL && cf->wth != NULL) {
+    wtap_close(cf->wth);
+    if (cf->is_tempfile) {
+      ws_unlink(cf->filename);
     }
   }
 #ifdef USE_BROKEN_G_MAIN_LOOP
@@ -2467,7 +2662,7 @@ capture_cleanup(DWORD ctrltype _U_)
      building it with Cygwin may make the problem go away). */
 
   /* tell the capture child to stop */
-  sync_pipe_stop(&global_capture_opts);
+  sync_pipe_stop(&global_capture_session);
 
   /* don't stop our own loop already here, otherwise status messages and
    * cleanup wouldn't be done properly. The child will indicate the stop of
@@ -2480,7 +2675,7 @@ static void
 capture_cleanup(int signum _U_)
 {
   /* tell the capture child to stop */
-  sync_pipe_stop(&global_capture_opts);
+  sync_pipe_stop(&global_capture_session);
 
   /* don't stop our own loop already here, otherwise status messages and
    * cleanup wouldn't be done properly. The child will indicate the stop of
@@ -2491,13 +2686,14 @@ capture_cleanup(int signum _U_)
 
 static gboolean
 process_packet_first_pass(capture_file *cf,
-               gint64 offset, const struct wtap_pkthdr *whdr,
-               union wtap_pseudo_header *pseudo_header, const guchar *pd)
+               gint64 offset, struct wtap_pkthdr *whdr,
+               const guchar *pd)
 {
-  frame_data fdlocal;
-  guint32 framenum;
+  frame_data     fdlocal;
+  guint32        framenum;
+  gboolean       create_proto_tree = FALSE;
   epan_dissect_t edt;
-  gboolean passed;
+  gboolean       passed;
 
   /* The frame number of this packet is one more than the count of
      frames in this packet. */
@@ -2511,18 +2707,22 @@ process_packet_first_pass(capture_file *cf,
   frame_data_init(&fdlocal, framenum, whdr, offset, cum_bytes);
 
   /* If we're going to print packet information, or we're going to
-     run a read filter, or we're going to process taps, set up to
+     run a read filter, or display filter, or we're going to process taps, set up to
      do a dissection and do so. */
   if (do_dissection) {
-    if (gbl_resolv_flags)
+    if (gbl_resolv_flags.mac_name || gbl_resolv_flags.network_name ||
+        gbl_resolv_flags.transport_name || gbl_resolv_flags.concurrent_dns)
       /* Grab any resolved addresses */
-      host_name_lookup_process(NULL);
+      host_name_lookup_process();
 
-    /* The protocol tree will be "visible", i.e., printed, only if we're
-       printing packet details, which is true if we're printing stuff
-       ("print_packet_info" is true) and we're in verbose mode ("verbose"
-       is true). */
-    epan_dissect_init(&edt, FALSE, 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)
+      create_proto_tree = TRUE;
+
+    /* We're not going to display the protocol tree on this pass,
+       so it's not going to be "visible". */
+    epan_dissect_init(&edt, cf->epan, create_proto_tree, FALSE);
 
     /* If we're running a read filter, prime the epan_dissect_t with that
        filter. */
@@ -2530,9 +2730,13 @@ process_packet_first_pass(capture_file *cf,
       epan_dissect_prime_dfilter(&edt, cf->rfcode);
 
     frame_data_set_before_dissect(&fdlocal, &cf->elapsed_time,
-                                  &first_ts, &prev_dis_ts, &prev_cap_ts);
+                                  &ref, prev_dis);
+    if (ref == &fdlocal) {
+      ref_frame = fdlocal;
+      ref = &ref_frame;
+    }
 
-    epan_dissect_run(&edt, pseudo_header, pd, &fdlocal, NULL);
+    epan_dissect_run(&edt, whdr, frame_tvbuff_new(&fdlocal, pd), &fdlocal, NULL);
 
     /* Run the read filter if we have one. */
     if (cf->rfcode)
@@ -2540,9 +2744,22 @@ process_packet_first_pass(capture_file *cf,
   }
 
   if (passed) {
-    frame_data_set_after_dissect(&fdlocal, &cum_bytes, &prev_dis_ts);
-    frame_data_sequence_add(cf->frames, &fdlocal);
+    frame_data_set_after_dissect(&fdlocal, &cum_bytes);
+    prev_cap = prev_dis = frame_data_sequence_add(cf->frames, &fdlocal);
+
+    /* If we're not doing dissection then there won't be any dependent frames.
+     * More importantly, edt.pi.dependent_frames won't be initialized because
+     * epan hasn't been initialized.
+     */
+    if (do_dissection) {
+      g_slist_foreach(edt.pi.dependent_frames, find_and_mark_frame_depended_upon, cf->frames);
+    }
+
     cf->count++;
+  } else {
+    /* if we don't add it to the frame_data_sequence, clean it up right now
+     * to avoid leaks */
+    frame_data_destroy(&fdlocal);
   }
 
   if (do_dissection)
@@ -2553,13 +2770,13 @@ process_packet_first_pass(capture_file *cf,
 
 static gboolean
 process_packet_second_pass(capture_file *cf, frame_data *fdata,
-               union wtap_pseudo_header *pseudo_header, const guchar *pd,
+               struct wtap_pkthdr *phdr, Buffer *buf,
                gboolean filtering_tap_listeners, guint tap_flags)
 {
-  gboolean create_proto_tree;
-  column_info *cinfo;
-  epan_dissect_t edt;
-  gboolean passed;
+  gboolean        create_proto_tree;
+  column_info    *cinfo;
+  epan_dissect_t  edt;
+  gboolean        passed;
 
   /* If we're not running a display filter and we're not printing any
      packet information, we don't need to do a dissection. This means
@@ -2570,11 +2787,12 @@ process_packet_second_pass(capture_file *cf, frame_data *fdata,
      run a read filter, or we're going to process taps, set up to
      do a dissection and do so. */
   if (do_dissection) {
-    if (gbl_resolv_flags)
+    if (gbl_resolv_flags.mac_name || gbl_resolv_flags.network_name ||
+        gbl_resolv_flags.transport_name || gbl_resolv_flags.concurrent_dns)
       /* Grab any resolved addresses */
-      host_name_lookup_process(NULL);
+      host_name_lookup_process();
 
-    if (cf->rfcode || verbose || filtering_tap_listeners ||
+    if (cf->dfcode || print_details || filtering_tap_listeners ||
         (tap_flags & TL_REQUIRES_PROTO_TREE) || have_custom_cols(&cf->cinfo))
       create_proto_tree = TRUE;
     else
@@ -2582,42 +2800,44 @@ process_packet_second_pass(capture_file *cf, frame_data *fdata,
 
     /* The protocol tree will be "visible", i.e., printed, only if we're
        printing packet details, which is true if we're printing stuff
-       ("print_packet_info" is true) and we're in verbose mode ("verbose"
-       is true). */
-    epan_dissect_init(&edt, create_proto_tree, print_packet_info && verbose);
+       ("print_packet_info" is true) and we're in verbose mode
+       ("packet_details" is true). */
+    epan_dissect_init(&edt, cf->epan, create_proto_tree, print_packet_info && print_details);
 
-    /* If we're running a read filter, prime the epan_dissect_t with that
+    /* If we're running a display filter, prime the epan_dissect_t with that
        filter. */
-    if (cf->rfcode)
-      epan_dissect_prime_dfilter(&edt, cf->rfcode);
+    if (cf->dfcode)
+      epan_dissect_prime_dfilter(&edt, cf->dfcode);
 
     col_custom_prime_edt(&edt, &cf->cinfo);
 
-    tap_queue_init(&edt);
-
     /* We only need the columns if either
-
          1) some tap needs the columns
-
        or
-
          2) we're printing packet info but we're *not* verbose; in verbose
-            mode, we print the protocol tree, not the protocol summary. */
-    if ((tap_flags & TL_REQUIRES_COLUMNS) || (print_packet_info && !verbose))
+            mode, we print the protocol tree, not the protocol summary.
+     */
+    if ((tap_flags & TL_REQUIRES_COLUMNS) || (print_packet_info && print_summary))
       cinfo = &cf->cinfo;
     else
       cinfo = NULL;
 
-    epan_dissect_run(&edt, pseudo_header, pd, fdata, cinfo);
+    frame_data_set_before_dissect(fdata, &cf->elapsed_time,
+                                  &ref, prev_dis);
+    if (ref == fdata) {
+      ref_frame = *fdata;
+      ref = &ref_frame;
+    }
 
-    tap_push_tapped_queue(&edt);
+    epan_dissect_run_with_taps(&edt, phdr, frame_tvbuff_new_buffer(fdata, buf), fdata, cinfo);
 
-    /* Run the read filter if we have one. */
-    if (cf->rfcode)
-      passed = dfilter_apply_edt(cf->rfcode, &edt);
+    /* Run the read/display filter if we have one. */
+    if (cf->dfcode)
+      passed = dfilter_apply_edt(cf->dfcode, &edt);
   }
 
   if (passed) {
+    frame_data_set_after_dissect(fdata, &cum_bytes);
     /* Process this packet. */
     if (print_packet_info) {
       /* We're printing packet information; print the information for
@@ -2655,12 +2875,14 @@ process_packet_second_pass(capture_file *cf, frame_data *fdata,
         exit(2);
       }
     }
+    prev_dis = fdata;
   }
+  prev_cap = fdata;
 
   if (do_dissection) {
     epan_dissect_cleanup(&edt);
   }
-  return passed;
+  return passed || fdata->flags.dependent_of_displayed;
 }
 
 static int
@@ -2672,14 +2894,24 @@ load_cap_file(capture_file *cf, char *save_file, int out_file_type,
   wtap_dumper *pdh;
   guint32      framenum;
   int          err;
-  gchar        *err_info = NULL;
+  gchar       *err_info = NULL;
   gint64       data_offset;
-  char         *save_file_string = NULL;
+  char        *save_file_string = NULL;
   gboolean     filtering_tap_listeners;
   guint        tap_flags;
+  wtapng_section_t            *shb_hdr;
+  wtapng_iface_descriptions_t *idb_inf;
+  char         appname[100];
+  Buffer       buf;
 
+  shb_hdr = wtap_file_get_shb_info(cf->wth);
+  idb_inf = wtap_file_get_idb_info(cf->wth);
 #ifdef PCAP_NG_DEFAULT
-  linktype = WTAP_ENCAP_PER_PACKET;
+  if (idb_inf->number_of_interfaces > 1) {
+    linktype = WTAP_ENCAP_PER_PACKET;
+  } else {
+    linktype = wtap_file_encap(cf->wth);
+  }
 #else
   linktype = wtap_file_encap(cf->wth);
 #endif
@@ -2693,8 +2925,21 @@ load_cap_file(capture_file *cf, char *save_file, int out_file_type,
       /* Snapshot length of input file not known. */
       snapshot_length = WTAP_MAX_PACKET_SIZE;
     }
-    pdh = wtap_dump_open(save_file, out_file_type, linktype, snapshot_length,
-                         FALSE /* compressed */, &err);
+    /* If we don't have an application name add Tshark */
+    if (shb_hdr->shb_user_appl == NULL) {
+        g_snprintf(appname, sizeof(appname), "TShark " VERSION "%s", wireshark_svnversion);
+        shb_hdr->shb_user_appl = appname;
+    }
+
+    if (linktype != WTAP_ENCAP_PER_PACKET && out_file_type == WTAP_FILE_PCAP)
+        pdh = wtap_dump_open(save_file, out_file_type, linktype,
+            snapshot_length, FALSE /* compressed */, &err);
+    else
+        pdh = wtap_dump_open_ng(save_file, out_file_type, linktype,
+            snapshot_length, FALSE /* compressed */, shb_hdr, idb_inf, &err);
+
+    g_free(idb_inf);
+    idb_inf = NULL;
 
     if (pdh == NULL) {
       /* We couldn't set up to write to the capture file. */
@@ -2760,13 +3005,13 @@ load_cap_file(capture_file *cf, char *save_file, int out_file_type,
 
     while (wtap_read(cf->wth, &err, &err_info, &data_offset)) {
       if (process_packet_first_pass(cf, data_offset, wtap_phdr(cf->wth),
-                         wtap_pseudoheader(cf->wth), wtap_buf_ptr(cf->wth))) {
+                         wtap_buf_ptr(cf->wth))) {
         /* Stop reading if we have the maximum number of packets;
          * When the -c option has not been used, max_packet_count
          * starts at 0, which practically means, never stop reading.
          * (unless we roll over max_packet_count ?)
          */
-        if( (--max_packet_count == 0) || (max_byte_count != 0 && data_offset >= max_byte_count)) {
+        if ( (--max_packet_count == 0) || (max_byte_count != 0 && data_offset >= max_byte_count)) {
           err = 0; /* This is not an error */
           break;
         }
@@ -2782,20 +3027,20 @@ load_cap_file(capture_file *cf, char *save_file, int out_file_type,
 
     max_packet_count = old_max_packet_count;
 
+    prev_dis = NULL;
+    prev_cap = NULL;
+    buffer_init(&buf, 1500);
     for (framenum = 1; err == 0 && framenum <= cf->count; framenum++) {
       fdata = frame_data_sequence_find(cf->frames, framenum);
-      if (wtap_seek_read(cf->wth, fdata->file_off, &cf->pseudo_header,
-          cf->pd, fdata->cap_len, &err, &err_info)) {
-        if (process_packet_second_pass(cf, fdata,
-                           &cf->pseudo_header, cf->pd,
-                           filtering_tap_listeners, tap_flags)) {
+      if (wtap_seek_read(cf->wth, fdata->file_off, &cf->phdr,
+          &buf, fdata->cap_len, &err, &err_info)) {
+        if (process_packet_second_pass(cf, fdata, &cf->phdr, &buf,
+                                       filtering_tap_listeners, tap_flags)) {
           /* Either there's no read filtering or this packet passed the
              filter, so, if we're writing to a capture file, write
              this packet out. */
           if (pdh != NULL) {
-            if (!wtap_dump(pdh, wtap_phdr(cf->wth),
-                           wtap_pseudoheader(cf->wth), wtap_buf_ptr(cf->wth),
-                           &err)) {
+            if (!wtap_dump(pdh, &cf->phdr, buffer_start_ptr(&cf->buf), &err)) {
               /* Error writing to a capture file */
               switch (err) {
 
@@ -2818,6 +3063,7 @@ load_cap_file(capture_file *cf, char *save_file, int out_file_type,
                 break;
               }
               wtap_dump_close(pdh, &err);
+              g_free(shb_hdr);
               exit(2);
             }
           }
@@ -2826,13 +3072,14 @@ load_cap_file(capture_file *cf, char *save_file, int out_file_type,
            * starts at 0, which practically means, never stop reading.
            * (unless we roll over max_packet_count ?)
            */
-          if( (--max_packet_count == 0) || (max_byte_count != 0 && data_offset >= max_byte_count)) {
+          if ( (--max_packet_count == 0) || (max_byte_count != 0 && data_offset >= max_byte_count)) {
             err = 0; /* This is not an error */
             break;
           }
         }
       }
     }
+    buffer_free(&buf);
   }
   else {
     framenum = 0;
@@ -2840,15 +3087,13 @@ load_cap_file(capture_file *cf, char *save_file, int out_file_type,
       framenum++;
 
       if (process_packet(cf, data_offset, wtap_phdr(cf->wth),
-                         wtap_pseudoheader(cf->wth), wtap_buf_ptr(cf->wth),
+                         wtap_buf_ptr(cf->wth),
                          filtering_tap_listeners, tap_flags)) {
         /* Either there's no read filtering or this packet passed the
            filter, so, if we're writing to a capture file, write
            this packet out. */
         if (pdh != NULL) {
-          if (!wtap_dump(pdh, wtap_phdr(cf->wth),
-                         wtap_pseudoheader(cf->wth), wtap_buf_ptr(cf->wth),
-                         &err)) {
+          if (!wtap_dump(pdh, wtap_phdr(cf->wth), wtap_buf_ptr(cf->wth), &err)) {
             /* Error writing to a capture file */
             switch (err) {
 
@@ -2868,6 +3113,7 @@ load_cap_file(capture_file *cf, char *save_file, int out_file_type,
               break;
             }
             wtap_dump_close(pdh, &err);
+            g_free(shb_hdr);
             exit(2);
           }
         }
@@ -2876,7 +3122,7 @@ load_cap_file(capture_file *cf, char *save_file, int out_file_type,
          * starts at 0, which practically means, never stop reading.
          * (unless we roll over max_packet_count ?)
          */
-        if( (--max_packet_count == 0) || (max_byte_count != 0 && data_offset >= max_byte_count)) {
+        if ( (--max_packet_count == 0) || (max_byte_count != 0 && data_offset >= max_byte_count)) {
           err = 0; /* This is not an error */
           break;
         }
@@ -2974,20 +3220,21 @@ out:
   cf->wth = NULL;
 
   g_free(save_file_string);
+  g_free(shb_hdr);
 
   return err;
 }
 
 static gboolean
-process_packet(capture_file *cf, gint64 offset, const struct wtap_pkthdr *whdr,
-               union wtap_pseudo_header *pseudo_header, const guchar *pd,
+process_packet(capture_file *cf, gint64 offset, struct wtap_pkthdr *whdr,
+               const guchar *pd,
                gboolean filtering_tap_listeners, guint tap_flags)
 {
-  frame_data fdata;
-  gboolean create_proto_tree;
-  column_info *cinfo;
-  epan_dissect_t edt;
-  gboolean passed;
+  frame_data      fdata;
+  gboolean        create_proto_tree;
+  column_info    *cinfo;
+  epan_dissect_t  edt;
+  gboolean        passed;
 
   /* Count this packet. */
   cf->count++;
@@ -3003,11 +3250,12 @@ process_packet(capture_file *cf, gint64 offset, const struct wtap_pkthdr *whdr,
      run a read filter, or we're going to process taps, set up to
      do a dissection and do so. */
   if (do_dissection) {
-    if (print_packet_info && gbl_resolv_flags)
+    if (print_packet_info && (gbl_resolv_flags.mac_name || gbl_resolv_flags.network_name ||
+        gbl_resolv_flags.transport_name || gbl_resolv_flags.concurrent_dns))
       /* Grab any resolved addresses */
-      host_name_lookup_process(NULL);
+      host_name_lookup_process();
 
-    if (cf->rfcode || verbose || filtering_tap_listeners ||
+    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
@@ -3015,46 +3263,49 @@ process_packet(capture_file *cf, gint64 offset, const struct wtap_pkthdr *whdr,
 
     /* The protocol tree will be "visible", i.e., printed, only if we're
        printing packet details, which is true if we're printing stuff
-       ("print_packet_info" is true) and we're in verbose mode ("verbose"
-       is true). */
-    epan_dissect_init(&edt, create_proto_tree, print_packet_info && verbose);
+       ("print_packet_info" is true) and we're in verbose mode
+       ("packet_details" is true). */
+    epan_dissect_init(&edt, cf->epan, create_proto_tree, print_packet_info && print_details);
 
-    /* If we're running a read filter, prime the epan_dissect_t with that
+    /* If we're running a filter, prime the epan_dissect_t with that
        filter. */
     if (cf->rfcode)
       epan_dissect_prime_dfilter(&edt, cf->rfcode);
+    if (cf->dfcode)
+      epan_dissect_prime_dfilter(&edt, cf->dfcode);
 
     col_custom_prime_edt(&edt, &cf->cinfo);
 
-    tap_queue_init(&edt);
-
     /* We only need the columns if either
-
          1) some tap needs the columns
-
        or
-
          2) we're printing packet info but we're *not* verbose; in verbose
-            mode, we print the protocol tree, not the protocol summary. */
-    if ((tap_flags & TL_REQUIRES_COLUMNS) || (print_packet_info && !verbose))
+            mode, we print the protocol tree, not the protocol summary.
+       or
+         3) there is a column mapped as an individual field */
+    if ((tap_flags & TL_REQUIRES_COLUMNS) || (print_packet_info && print_summary) || output_fields_has_cols(output_fields))
       cinfo = &cf->cinfo;
     else
       cinfo = NULL;
 
     frame_data_set_before_dissect(&fdata, &cf->elapsed_time,
-                                  &first_ts, &prev_dis_ts, &prev_cap_ts);
-
-    epan_dissect_run(&edt, pseudo_header, pd, &fdata, cinfo);
+                                  &ref, prev_dis);
+    if (ref == &fdata) {
+      ref_frame = fdata;
+      ref = &ref_frame;
+    }
 
-    tap_push_tapped_queue(&edt);
+    epan_dissect_run_with_taps(&edt, whdr, frame_tvbuff_new(&fdata, pd), &fdata, cinfo);
 
-    /* Run the read filter if we have one. */
+    /* Run the filters if we have them. */
     if (cf->rfcode)
       passed = dfilter_apply_edt(cf->rfcode, &edt);
+    if (passed && cf->dfcode)
+      passed = dfilter_apply_edt(cf->dfcode, &edt);
   }
 
   if (passed) {
-    frame_data_set_after_dissect(&fdata, &cum_bytes, &prev_dis_ts);
+    frame_data_set_after_dissect(&fdata, &cum_bytes);
 
     /* Process this packet. */
     if (print_packet_info) {
@@ -3093,11 +3344,18 @@ process_packet(capture_file *cf, gint64 offset, const struct wtap_pkthdr *whdr,
         exit(2);
       }
     }
+
+    /* this must be set after print_packet() [bug #8160] */
+    prev_dis_frame = fdata;
+    prev_dis = &prev_dis_frame;
   }
 
+  prev_cap_frame = fdata;
+  prev_cap = &prev_cap_frame;
+
   if (do_dissection) {
     epan_dissect_cleanup(&edt);
-    frame_data_cleanup(&fdata);
+    frame_data_destroy(&fdata);
   }
   return passed;
 }
@@ -3108,10 +3366,10 @@ write_preamble(capture_file *cf)
   switch (output_action) {
 
   case WRITE_TEXT:
-    return print_preamble(print_stream, cf ? cf->filename : NULL);
+    return print_preamble(print_stream, cf ? cf->filename : NULL, wireshark_svnversion);
 
   case WRITE_XML:
-    if (verbose)
+    if (print_details)
       write_pdml_preamble(stdout, cf ? cf->filename : NULL);
     else
       write_psml_preamble(stdout);
@@ -3130,20 +3388,20 @@ write_preamble(capture_file *cf)
 static char *
 get_line_buf(size_t len)
 {
-  static char *line_bufp = NULL;
-  static size_t line_buf_len = 256;
-  size_t new_line_buf_len;
+  static char   *line_bufp    = NULL;
+  static size_t  line_buf_len = 256;
+  size_t         new_line_buf_len;
 
   for (new_line_buf_len = line_buf_len; len > new_line_buf_len;
        new_line_buf_len *= 2)
     ;
   if (line_bufp == NULL) {
     line_buf_len = new_line_buf_len;
-    line_bufp = g_malloc(line_buf_len + 1);
+    line_bufp = (char *)g_malloc(line_buf_len + 1);
   } else {
     if (new_line_buf_len > line_buf_len) {
       line_buf_len = new_line_buf_len;
-      line_bufp = g_realloc(line_bufp, line_buf_len + 1);
+      line_bufp = (char *)g_realloc(line_bufp, line_buf_len + 1);
     }
   }
   return line_bufp;
@@ -3152,10 +3410,10 @@ get_line_buf(size_t len)
 static gboolean
 print_columns(capture_file *cf)
 {
-  char *line_bufp;
-  int i;
-  size_t buf_offset;
-  size_t column_len;
+  char   *line_bufp;
+  int     i;
+  size_t  buf_offset;
+  size_t  column_len;
 
   line_bufp = get_line_buf(256);
   buf_offset = 0;
@@ -3385,29 +3643,50 @@ print_columns(capture_file *cf)
 static gboolean
 print_packet(capture_file *cf, epan_dissect_t *edt)
 {
-  print_args_t  print_args;
+  print_args_t print_args;
+
+  if (print_summary || output_fields_has_cols(output_fields)) {
+    /* Just fill in the columns. */
+    epan_dissect_fill_in_columns(edt, FALSE, TRUE);
+
+    if (print_summary) {
+      /* Now print them. */
+      switch (output_action) {
 
-  if (verbose) {
+      case WRITE_TEXT:
+        if (!print_columns(cf))
+          return FALSE;
+        break;
+
+      case WRITE_XML:
+        proto_tree_write_psml(edt, stdout);
+        return !ferror(stdout);
+      case WRITE_FIELDS: /*No non-verbose "fields" format */
+        g_assert_not_reached();
+        break;
+      }
+    }
+  }
+  if (print_details) {
     /* Print the information in the protocol tree. */
     switch (output_action) {
 
     case WRITE_TEXT:
+      /* Only initialize the fields that are actually used in proto_tree_print.
+       * This is particularly important for .range, as that's heap memory which
+       * we would otherwise have to g_free().
       print_args.to_file = TRUE;
       print_args.format = print_format;
-      print_args.print_summary = !verbose;
-      print_args.print_hex = verbose && print_hex;
+      print_args.print_summary = print_summary;
       print_args.print_formfeed = FALSE;
-      print_args.print_dissections = verbose ? print_dissections_expanded : print_dissections_none;
-
-      /* init the packet range */
-      packet_range_init(&print_args.range);
+      packet_range_init(&print_args.range, &cfile);
+      */
+      print_args.print_hex = print_hex;
+      print_args.print_dissections = print_details ? print_dissections_expanded : print_dissections_none;
 
       if (!proto_tree_print(&print_args, edt, print_stream))
         return FALSE;
       if (!print_hex) {
-        /* "print_hex_data()" will put out a leading blank line, as well
-         as a trailing one; print one here, to separate the packets,
-         only if "print_hex_data()" won't be called. */
         if (!print_line(print_stream, 0, separator))
           return FALSE;
       }
@@ -3418,34 +3697,19 @@ print_packet(capture_file *cf, epan_dissect_t *edt)
       printf("\n");
       return !ferror(stdout);
     case WRITE_FIELDS:
-      proto_tree_write_fields(output_fields, edt, stdout);
+      proto_tree_write_fields(output_fields, edt, &cf->cinfo, stdout);
       printf("\n");
       return !ferror(stdout);
     }
-  } else {
-    /* Just fill in the columns. */
-    epan_dissect_fill_in_columns(edt, FALSE, TRUE);
-
-    /* Now print them. */
-    switch (output_action) {
-
-    case WRITE_TEXT:
-        if (!print_columns(cf))
-          return FALSE;
-        break;
-
-    case WRITE_XML:
-        proto_tree_write_psml(edt, stdout);
-        return !ferror(stdout);
-    case WRITE_FIELDS: /*No non-verbose "fields" format */
-        g_assert_not_reached();
-        break;
-    }
   }
   if (print_hex) {
+    if (print_summary || print_details) {
+      if (!print_line(print_stream, 0, ""))
+        return FALSE;
+    }
     if (!print_hex_data(print_stream, edt))
       return FALSE;
-    if (!print_line(print_stream, 0, ""))
+    if (!print_line(print_stream, 0, separator))
       return FALSE;
   }
   return TRUE;
@@ -3460,7 +3724,7 @@ write_finale(void)
     return print_finale(print_stream);
 
   case WRITE_XML:
-    if (verbose)
+    if (print_details)
       write_pdml_finale(stdout);
     else
       write_psml_finale(stdout);
@@ -3479,9 +3743,9 @@ write_finale(void)
 cf_status_t
 cf_open(capture_file *cf, const char *fname, gboolean is_tempfile, int *err)
 {
-  wtap       *wth;
-  gchar       *err_info;
-  char        err_msg[2048+1];
+  wtap  *wth;
+  gchar *err_info;
+  char   err_msg[2048+1];
 
   wth = wtap_open_offline(fname, err, &err_info, perform_two_pass_analysis);
   if (wth == NULL)
@@ -3489,10 +3753,9 @@ cf_open(capture_file *cf, const char *fname, gboolean is_tempfile, int *err)
 
   /* The open succeeded.  Fill in the information for this file. */
 
-  /* Cleanup all data structures used for dissection. */
-  cleanup_dissection();
-  /* Initialize all data structures used for dissection. */
-  init_dissection();
+  /* Create new epan session for dissection. */
+  epan_free(cf->epan);
+  cf->epan = tshark_epan_new(cf);
 
   cf->wth = wth;
   cf->f_datalen = 0; /* not used, but set it anyway */
@@ -3505,8 +3768,8 @@ cf_open(capture_file *cf, const char *fname, gboolean is_tempfile, int *err)
   /* Indicate whether it's a permanent or temporary file. */
   cf->is_tempfile = is_tempfile;
 
-  /* If it's a temporary capture buffer file, mark it as not saved. */
-  cf->user_saved = !is_tempfile;
+  /* No user changes yet. */
+  cf->unsaved_changes = FALSE;
 
   cf->cd_t      = wtap_file_type(cf->wth);
   cf->count     = 0;
@@ -3520,9 +3783,9 @@ cf_open(capture_file *cf, const char *fname, gboolean is_tempfile, int *err)
   } else
     cf->has_snap = TRUE;
   nstime_set_zero(&cf->elapsed_time);
-  nstime_set_unset(&first_ts);
-  nstime_set_unset(&prev_dis_ts);
-  nstime_set_unset(&prev_cap_ts);
+  ref = NULL;
+  prev_dis = NULL;
+  prev_cap = NULL;
 
   cf->state = FILE_READ_IN_PROGRESS;
 
@@ -3773,26 +4036,6 @@ write_failure_message(const char *filename, int err)
           filename, g_strerror(err));
 }
 
-/*
- * Print to the standard error.  This is a command-line tool, so there's
- * no need to pop up a console.
- */
-void
-vfprintf_stderr(const char *fmt, va_list ap)
-{
-  vfprintf(stderr, fmt, ap);
-}
-
-void
-fprintf_stderr(const char *fmt, ...)
-{
-  va_list ap;
-
-  va_start(ap, fmt);
-  vfprintf_stderr(fmt, ap);
-  va_end(ap);
-}
-
 /*
  * Report an error in command-line arguments.
  */
@@ -3819,3 +4062,17 @@ cmdarg_err_cont(const char *fmt, ...)
   fprintf(stderr, "\n");
   va_end(ap);
 }
+
+
+/*
+ * Editor modelines  -  http://www.wireshark.org/tools/modelines.html
+ *
+ * Local variables:
+ * c-basic-offset: 2
+ * tab-width: 8
+ * indent-tabs-mode: nil
+ * End:
+ *
+ * vi: set shiftwidth=2 tabstop=8 expandtab:
+ * :indentSize=2:tabSize=8:noTabs=true:
+ */