packet-smb-direct.c: add support for reassembling of fragments
[metze/wireshark/wip.git] / tshark.c
index 80d6ce38894d5323104bdcebdb3bbd432c27d52f..c5f9aa4c563d70c9ccee0907a73afb58661568b0 100644 (file)
--- a/tshark.c
+++ b/tshark.c
@@ -3,8 +3,6 @@
  * Text-mode variant of Wireshark, along the lines of tcpdump and snoop,
  * by Gilbert Ramirez <gram@alumni.rice.edu> and Guy Harris <guy@alum.mit.edu>.
  *
- * $Id$
- *
  * Wireshark - Network traffic analyzer
  * By Gerald Combs <gerald@wireshark.org>
  * Copyright 1998 Gerald Combs
 #include <unistd.h>
 #endif
 
+#ifdef HAVE_GETOPT_H
+#include <getopt.h>
+#endif
+
 #include <errno.h>
 
 #ifdef HAVE_FCNTL_H
 #endif
 
 #include <glib.h>
+
+#include <epan/exceptions.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 <wsutil/filesystem.h>
+#include <wsutil/report_err.h>
 
 #include "globals.h"
 #include <epan/timestamp.h>
 #include <epan/packet.h>
+#ifdef HAVE_LUA
+#include <epan/wslua/init_wslua.h>
+#endif
 #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 "ui/util.h"
+#include "ui/ui_util.h"
 #include "clopts_common.h"
-#include "console_io.h"
 #include "cmdarg_err.h"
 #include "version_info.h"
-#include <epan/plugins.h>
 #include "register.h"
 #include <epan/epan_dissect.h>
 #include <epan/tap.h>
@@ -81,6 +91,8 @@
 #include <epan/timestamp.h>
 #include <epan/ex-opt.h>
 
+#include "capture_opts.h"
+
 #ifdef HAVE_LIBPCAP
 #include "capture_ui_utils.h"
 #include "capture_ifinfo.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"
+
+#ifdef HAVE_PLUGINS
+#include <wsutil/plugins.h>
+#endif
 
 /*
  * 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 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;
@@ -124,10 +141,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;
@@ -135,7 +155,7 @@ 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
 /*
@@ -144,6 +164,7 @@ static char *separator = "";
 static gboolean print_packet_counts;
 
 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,9 +184,9 @@ static void report_counts_siginfo(int);
 #endif /* HAVE_LIBPCAP */
 
 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);
+static gboolean process_packet(capture_file *cf, epan_dissect_t *edt, gint64 offset,
+    struct wtap_pkthdr *whdr, const guchar *pd,
+    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);
@@ -204,17 +225,17 @@ 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_SUBTYPES);
 
   fprintf(stderr, "tshark: The available capture file types for the \"-F\" flag are:\n");
-  for (i = 0; i < WTAP_NUM_FILE_TYPES; i++) {
+  for (i = 0; i < WTAP_NUM_FILE_TYPES_SUBTYPES; i++) {
     if (wtap_dump_can_open(i)) {
-      captypes[i].sstr = wtap_file_type_short_string(i);
-      captypes[i].lstr = wtap_file_type_string(i);
+      captypes[i].sstr = wtap_file_type_subtype_short_string(i);
+      captypes[i].lstr = wtap_file_type_subtype_string(i);
       list = g_slist_insert_sorted(list, &captypes[i], string_compare);
     }
   }
@@ -223,6 +244,28 @@ list_capture_types(void) {
   g_free(captypes);
 }
 
+static void
+list_read_capture_types(void) {
+  int                 i;
+  struct string_elem *captypes;
+  GSList             *list = NULL;
+  const char *magic = "Magic-value-based";
+  const char *heuristic = "Heuristics-based";
+
+  /* this is a hack, but WTAP_NUM_FILE_TYPES_SUBTYPES is always >= number of open routines so we're safe */
+  captypes = g_new(struct string_elem, WTAP_NUM_FILE_TYPES_SUBTYPES);
+
+  fprintf(stderr, "tshark: The available read file types for the \"-X read_format:\" option are:\n");
+  for (i = 0; open_routines[i].name != NULL; i++) {
+    captypes[i].sstr = open_routines[i].name;
+    captypes[i].lstr = (open_routines[i].type == OPEN_INFO_MAGIC) ? magic : heuristic;
+    list = g_slist_insert_sorted(list, &captypes[i], string_compare);
+  }
+  g_slist_foreach(list, string_elem_print, NULL);
+  g_slist_free(list);
+  g_free(captypes);
+}
+
 static void
 print_usage(gboolean print_ver)
 {
@@ -236,7 +279,7 @@ print_usage(gboolean print_ver)
         "See http://www.wireshark.org for more information.\n"
         "\n"
         "%s",
-         wireshark_svnversion, get_copyright_info());
+         wireshark_gitversion, get_copyright_info());
   } else {
     output = stderr;
   }
@@ -254,7 +297,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");
@@ -277,12 +320,14 @@ print_usage(gboolean print_ver)
 #endif
   /*fprintf(output, "\n");*/
   fprintf(output, "Input file:\n");
-  fprintf(output, "  -r <infile>              set the filename to read from (no pipes or stdin!)\n");
+  fprintf(output, "  -r <infile>              set the filename to read from (no stdin!)\n");
 
   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\n");
+  fprintf(output, "                           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);
@@ -301,12 +346,13 @@ 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,\n");
+  fprintf(output, "                           _ws.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");
@@ -315,14 +361,19 @@ 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");
   fprintf(output, "  -z <statistics>          various statistics, see the man page for details\n");
+  fprintf(output, "  --capture-comment <comment>\n");
+  fprintf(output, "                           add a capture comment to the newly created\n");
+  fprintf(output, "                           output file (only for pcapng)\n");
 
   fprintf(output, "\n");
   fprintf(output, "Miscellaneous:\n");
@@ -333,6 +384,14 @@ print_usage(gboolean print_ver)
   fprintf(output, "  -G [report]              dump one of several available reports and exit\n");
   fprintf(output, "                           default report=\"fields\"\n");
   fprintf(output, "                           use \"-G ?\" for more help\n");
+#ifdef __linux__
+    fprintf(output, "\n");
+    fprintf(output, "WARNING: dumpcap will enable kernel BPF JIT compiler if available.\n");
+    fprintf(output, "You might want to reset it\n");
+    fprintf(output, "By doing \"echo 0 > /proc/sys/net/core/bpf_jit_enable\"\n");
+    fprintf(output, "\n");
+#endif
+
 }
 
 static void
@@ -342,26 +401,25 @@ glossary_option_help(void)
 
   output = stdout;
 
-  fprintf(output, "TShark " VERSION "%s\n", wireshark_svnversion);
+  fprintf(output, "TShark " VERSION "%s\n", wireshark_gitversion);
 
   fprintf(output, "\n");
   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 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");
+  fprintf(output, "  -G column-formats        dump column format codes and exit\n");
   fprintf(output, "  -G decodes               dump \"layer type\"/\"decode as\" associations and exit\n");
+  fprintf(output, "  -G fields                dump fields glossary and exit\n");
+  fprintf(output, "  -G ftypes                dump field type basic and descriptive names\n");
   fprintf(output, "  -G heuristic-decodes     dump heuristic dissector tables\n");
+  fprintf(output, "  -G plugins               dump installed plugins 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, "\n");
   fprintf(output, "Preference reports:\n");
-  fprintf(output, "  -G defaultprefs          dump default preferences and exit\n");
   fprintf(output, "  -G currentprefs          dump current preferences and exit\n");
+  fprintf(output, "  -G defaultprefs          dump default preferences and exit\n");
   fprintf(output, "\n");
-
 }
 
 /*
@@ -388,9 +446,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);
 
@@ -434,9 +492,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);
 
@@ -509,7 +567,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;
@@ -518,6 +576,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 */
 
@@ -612,10 +672,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;
 
@@ -712,7 +797,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:
@@ -747,7 +842,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;
   }
@@ -775,6 +870,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();
@@ -811,15 +907,21 @@ show_version(GString *comp_info_str, GString *runtime_info_str)
          "%s"
          "\n"
          "%s",
-         wireshark_svnversion, get_copyright_info(), comp_info_str->str,
+         wireshark_gitversion, get_copyright_info(), comp_info_str->str,
          runtime_info_str->str);
 }
 
 int
 main(int argc, char *argv[])
 {
+  GString             *comp_info_str;
+  GString             *runtime_info_str;
   char                *init_progfile_dir_error;
   int                  opt;
+  struct option     long_options[] = {
+    {(char *)"capture-comment", required_argument, NULL, LONGOPT_NUM_CAP_COMMENT },
+    {0, 0, 0, 0 }
+  };
   gboolean             arg_error = FALSE;
 
 #ifdef _WIN32
@@ -840,27 +942,28 @@ 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
   gboolean             quiet = FALSE;
 #ifdef PCAP_NG_DEFAULT
-  volatile int         out_file_type = WTAP_FILE_PCAPNG;
+  volatile int         out_file_type = WTAP_FILE_TYPE_SUBTYPE_PCAPNG;
 #else
-  volatile int         out_file_type = WTAP_FILE_PCAP;
+  volatile int         out_file_type = WTAP_FILE_TYPE_SUBTYPE_PCAP;
 #endif
   volatile gboolean    out_file_name_res = FALSE;
+  volatile int         in_file_type = WTAP_TYPE_AUTO;
   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;
 
@@ -885,12 +988,32 @@ main(int argc, char *argv[])
 #define OPTSTRING_I ""
 #endif
 
-#define OPTSTRING "2a:" OPTSTRING_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:"
+/* the leading - ensures that getopt() does not permute the argv[] entries
+   we have to make sure that the first getopt() preserves the content of argv[]
+   for the subsequent getopt_long() call */
+#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_gitversion, 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
@@ -927,6 +1050,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;
@@ -935,6 +1076,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;
 
@@ -952,38 +1102,55 @@ 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();
 
+  init_report_err(failure_message, open_failure_message, read_failure_message,
+                  write_failure_message);
+
 #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);
   timestamp_set_precision(TS_PREC_AUTO);
   timestamp_set_seconds_type(TS_SECONDS_DEFAULT);
 
+  init_open_routines();
+
+#ifdef HAVE_PLUGINS
+  /* Register all the plugin types we have. */
+  epan_register_plugin_types(); /* Types known to libwireshark */
+  wtap_register_plugin_types(); /* Types known to libwiretap */
+
+  /* Scan for plugins.  This does *not* call their registration routines;
+     that's done later. */
+  scan_plugins();
+
+  /* Register all libwiretap plugin modules. */
+  register_all_wiretap_modules();
+#endif
+
   /* Register all dissectors; we must do this before checking for the
      "-G" flag, as the "-G" flag dumps information registered by the
      dissectors, and we must do it before we read the preferences, in
      case any dissectors register preferences. */
-  epan_init(register_all_protocols, register_all_protocol_handoffs, NULL, NULL,
-            failure_message, open_failure_message, read_failure_message,
-            write_failure_message);
+  epan_init(register_all_protocols, register_all_protocol_handoffs, NULL, NULL);
 
   /* Register all tap listeners; we do this before we parse the arguments,
      as the "-z" argument can specify a registered tap. */
@@ -1008,37 +1175,42 @@ 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);
-      else if (strcmp(argv[2], "protocols") == 0)
-        proto_registrar_dump_protocols();
-      else if (strcmp(argv[2], "values") == 0)
-        proto_registrar_dump_values();
-      else if (strcmp(argv[2], "ftypes") == 0)
-        proto_registrar_dump_ftypes();
+      if (strcmp(argv[2], "column-formats") == 0)
+        column_dump_column_formats();
+      else if (strcmp(argv[2], "currentprefs") == 0) {
+        read_prefs(&gpf_open_errno, &gpf_read_errno, &gpf_path,
+            &pf_open_errno, &pf_read_errno, &pf_path);
+        write_prefs(NULL);
+      }
       else if (strcmp(argv[2], "decodes") == 0)
         dissector_dump_decodes();
-      else if (strcmp(argv[2], "heuristic-decodes") == 0)
-        dissector_dump_heur_decodes();
       else if (strcmp(argv[2], "defaultprefs") == 0)
         write_prefs(NULL);
-      else if (strcmp(argv[2], "plugins") == 0)
+      else if (strcmp(argv[2], "fields") == 0)
+        proto_registrar_dump_fields();
+      else if (strcmp(argv[2], "ftypes") == 0)
+        proto_registrar_dump_ftypes();
+      else if (strcmp(argv[2], "heuristic-decodes") == 0)
+        dissector_dump_heur_decodes();
+      else if (strcmp(argv[2], "plugins") == 0) {
+#ifdef HAVE_PLUGINS
         plugins_dump_all();
+#endif
+#ifdef HAVE_LUA
+        wslua_plugins_dump_all();
+#endif
+      }
+      else if (strcmp(argv[2], "protocols") == 0)
+        proto_registrar_dump_protocols();
+      else if (strcmp(argv[2], "values") == 0)
+        proto_registrar_dump_values();
       else if (strcmp(argv[2], "?") == 0)
         glossary_option_help();
       else if (strcmp(argv[2], "-?") == 0)
         glossary_option_help();
-      else if (strcmp(argv[2], "currentprefs") == 0) {
-        read_prefs(&gpf_open_errno, &gpf_read_errno, &gpf_path,
-            &pf_open_errno, &pf_read_errno, &pf_path);
-        write_prefs(NULL);
-      } else {
+      else {
         cmdarg_err("Invalid \"%s\" option for -G flag, enter -G ? for more help.", argv[2]);
         return 1;
       }
@@ -1112,7 +1284,7 @@ main(int argc, char *argv[])
   output_fields = output_fields_new();
 
   /* Now get our args */
-  while ((opt = getopt(argc, argv, optstring)) != -1) {
+  while ((opt = getopt_long(argc, argv, optstring, long_options, NULL)) != -1) {
     switch (opt) {
     case '2':        /* Perform two pass analysis */
       perform_two_pass_analysis = TRUE;
@@ -1121,6 +1293,7 @@ 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
@@ -1132,12 +1305,13 @@ main(int argc, char *argv[])
     case 's':        /* Set the snapshot (capture) length */
     case 'w':        /* Write to capture file x */
     case 'y':        /* Set the pcap data link type */
+    case  LONGOPT_NUM_CAP_COMMENT: /* add a capture comment */
 #if defined(_WIN32) || defined(HAVE_PCAP_CREATE)
     case 'B':        /* Buffer size */
 #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
@@ -1159,7 +1333,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:
@@ -1188,14 +1362,14 @@ 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;
       }
       break;
     case 'F':
-      out_file_type = wtap_short_string_to_file_type(optarg);
+      out_file_type = wtap_short_string_to_file_type_subtype(optarg);
       if (out_file_type < 0) {
         cmdarg_err("\"%s\" isn't a valid capture file type", optarg);
         list_capture_types();
@@ -1204,11 +1378,16 @@ 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\"; it must be one of:", optarg);
+        cmdarg_err_cont("\t'n' write network address resolution information (pcapng only)");
+        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;
@@ -1252,9 +1431,14 @@ main(int argc, char *argv[])
     case 'N':        /* Select what types of addresses/port #s to resolve */
       badopt = string_to_name_resolve(optarg, &gbl_resolv_flags);
       if (badopt != '\0') {
-        cmdarg_err("-N specifies unknown resolving option '%c';",
+        cmdarg_err("-N specifies unknown resolving option '%c'; valid options are:",
                    badopt);
-        cmdarg_err_cont( "           Valid options are 'm', 'n', 't', and 'C'");
+        cmdarg_err_cont("\t'C' to enable concurrent (asynchronous) DNS lookups\n"
+                        "\t'm' to enable MAC address resolution\n"
+                        "\t'n' to enable network address resolution\n"
+                        "\t'N' to enable using external resolvers (e.g., DNS)\n"
+                        "\t    for network address resolution\n"
+                        "\t't' to enable transport-layer port number resolution");
         return 1;
       }
       break;
@@ -1279,15 +1463,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;
@@ -1297,7 +1485,9 @@ main(int argc, char *argv[])
       else if (strcmp(optarg, "a") == 0)
         timestamp_set_type(TS_ABSOLUTE);
       else if (strcmp(optarg, "ad") == 0)
-        timestamp_set_type(TS_ABSOLUTE_WITH_DATE);
+        timestamp_set_type(TS_ABSOLUTE_WITH_YMD);
+      else if (strcmp(optarg, "adoy") == 0)
+        timestamp_set_type(TS_ABSOLUTE_WITH_YDOY);
       else if (strcmp(optarg, "d") == 0)
         timestamp_set_type(TS_DELTA);
       else if (strcmp(optarg, "dd") == 0)
@@ -1307,16 +1497,26 @@ main(int argc, char *argv[])
       else if (strcmp(optarg, "u") == 0)
         timestamp_set_type(TS_UTC);
       else if (strcmp(optarg, "ud") == 0)
-        timestamp_set_type(TS_UTC_WITH_DATE);
+        timestamp_set_type(TS_UTC_WITH_YMD);
+      else if (strcmp(optarg, "udoy") == 0)
+        timestamp_set_type(TS_UTC_WITH_YDOY);
       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("Invalid time stamp type \"%s\"; it must be one of:", optarg);
+        cmdarg_err_cont("\t\"a\"    for absolute\n"
+                        "\t\"ad\"   for absolute with YYYY-MM-DD date\n"
+                        "\t\"adoy\" for absolute with YYYY/DOY date\n"
+                        "\t\"d\"    for delta\n"
+                        "\t\"dd\"   for delta displayed\n"
+                        "\t\"e\"    for epoch\n"
+                        "\t\"r\"    for relative\n"
+                        "\t\"u\"    for absolute UTC\n"
+                        "\t\"ud\"   for absolute UTC with YYYY-MM-DD date\n"
+                        "\t\"udoy\" for absolute UTC with YYYY/DOY date");
         return 1;
       }
       break;
     case 'T':        /* printing Type */
+      print_packet_info = TRUE;
       if (strcmp(optarg, "text") == 0) {
         output_action = WRITE_TEXT;
         print_format = PR_FMT_TEXT;
@@ -1325,16 +1525,34 @@ 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\".");
+        cmdarg_err("Invalid -T parameter \"%s\"; it must be one of:", optarg);                   /* x */
+        cmdarg_err_cont("\t\"fields\" The values of fields specified with the -e option, in a form\n"
+                        "\t         specified by the -E option.\n"
+                        "\t\"pdml\"   Packet Details Markup Language, an XML-based format for the\n"
+                        "\t         details of a decoded packet. This information is equivalent to\n"
+                        "\t         the packet details printed with the -V flag.\n"
+                        "\t\"ps\"     PostScript for a human-readable one-line summary of each of\n"
+                        "\t         the packets, or a multi-line view of the details of each of\n"
+                        "\t         the packets, depending on whether the -V flag was specified.\n"
+                        "\t\"psml\"   Packet Summary Markup Language, an XML-based format for the\n"
+                        "\t         summary information of a decoded packet. This information is\n"
+                        "\t         equivalent to the information shown in the one-line summary\n"
+                        "\t         printed by default.\n"
+                        "\t\"text\"   Text of a human-readable one-line summary of each of the\n"
+                        "\t         packets, or a multi-line view of the details of each of the\n"
+                        "\t         packets, depending on whether the -V flag was specified.\n"
+                        "\t         This is the default.");
         return 1;
       }
       break;
@@ -1344,46 +1562,39 @@ main(int argc, char *argv[])
       else if (strcmp(optarg, "hms") == 0)
         timestamp_set_seconds_type(TS_SECONDS_HOUR_MIN_SEC);
       else {
-        cmdarg_err("Invalid seconds type \"%s\"", optarg);
-        cmdarg_err_cont("It must be \"s\" for seconds or \"hms\" for hours, minutes and seconds.");
+        cmdarg_err("Invalid seconds type \"%s\"; it must be one of:", optarg);
+        cmdarg_err_cont("\t\"s\"   for seconds\n"
+                        "\t\"hms\" for hours, minutes and seconds");
         return 1;
       }
       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;
     }
     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
@@ -1391,8 +1602,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.");
-        cmdarg_err_cont("  -z argument must be one of :");
+        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\"; it must be one of:", optarg);
         list_stat_cmd_args();
         return 1;
       }
@@ -1412,37 +1627,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);
@@ -1495,19 +1713,6 @@ main(int argc, char *argv[])
     return 1;
   }
 
-  /* We don't support capture filters when reading from a capture file
-     (the BPF compiler doesn't support all link-layer types that we
-     support in capture files we read). */
-#ifdef HAVE_LIBPCAP
-  if (cf_name != NULL) {
-    if (global_capture_opts.default_options.cfilter) {
-      cmdarg_err("Only read filters, not capture filters, "
-          "can be specified when reading a capture file.");
-      return 1;
-    }
-  }
-#endif
-
   if (print_hex) {
     if (output_action != WRITE_TEXT) {
       cmdarg_err("Raw packet hex data can only be printed as text or PostScript");
@@ -1518,7 +1723,7 @@ main(int argc, char *argv[])
   if (output_only != NULL) {
     char *ps;
 
-    if (!verbose) {
+    if (!print_details) {
       cmdarg_err("-O requires -V");
       return 1;
     }
@@ -1529,6 +1734,11 @@ main(int argc, char *argv[])
     }
   }
 
+  if (rfilter != NULL && !perform_two_pass_analysis) {
+    cmdarg_err("-R without -2 is deprecated. For single-pass filtering use -Y.");
+    return 1;
+  }
+
 #ifdef HAVE_LIBPCAP
   if (list_link_layer_types) {
     /* We're supposed to list the link-layer types for an interface;
@@ -1549,6 +1759,15 @@ main(int argc, char *argv[])
        * "-r" was specified, so we're reading a capture file.
        * Capture options don't apply here.
        */
+
+      /* We don't support capture filters when reading from a capture file
+         (the BPF compiler doesn't support all link-layer types that we
+         support in capture files we read). */
+      if (global_capture_opts.default_options.cfilter) {
+        cmdarg_err("Only read filters, not capture filters, "
+          "can be specified when reading a capture file.");
+        return 1;
+      }
       if (global_capture_opts.multi_files_on) {
         cmdarg_err("Multiple capture files requested, but "
                    "a capture isn't being done.");
@@ -1569,6 +1788,12 @@ main(int argc, char *argv[])
           "a capture isn't being done.");
         return 1;
       }
+      if (global_capture_opts.capture_comment) {
+        cmdarg_err("A capture comment was specified, but "
+          "a capture isn't being done.\nThere's no support for adding "
+          "a capture comment to an existing capture file.");
+        return 1;
+      }
 
       /* Note: TShark now allows the restriction of a _read_ file by packet count
        * and byte count as well as a write file. Other autostop options remain valid
@@ -1583,14 +1808,28 @@ main(int argc, char *argv[])
       /*
        * "-r" wasn't specified, so we're doing a live capture.
        */
+      if (perform_two_pass_analysis) {
+        /* Two-pass analysis doesn't work with live capture since it requires us
+         * to buffer packets until we've read all of them, but a live capture
+         * has no useful/meaningful definition of "all" */
+        cmdarg_err("Live captures do not support two-pass analysis.");
+        return 1;
+      }
+
       if (global_capture_opts.saving_to_file) {
         /* They specified a "-w" flag, so we'll be saving to a capture file. */
 
         /* When capturing, we only support writing pcap or pcap-ng format. */
-        if (out_file_type != WTAP_FILE_PCAP && out_file_type != WTAP_FILE_PCAPNG) {
+        if (out_file_type != WTAP_FILE_TYPE_SUBTYPE_PCAP &&
+            out_file_type != WTAP_FILE_TYPE_SUBTYPE_PCAPNG) {
           cmdarg_err("Live captures can only be saved in libpcap format.");
           return 1;
         }
+        if (global_capture_opts.capture_comment &&
+            out_file_type != WTAP_FILE_TYPE_SUBTYPE_PCAPNG) {
+          cmdarg_err("A capture comment can only be written to a pcapng file.");
+          return 1;
+        }
         if (global_capture_opts.multi_files_on) {
           /* Multiple-file mode doesn't work under certain conditions:
              a) it doesn't work if you're writing to the standard output;
@@ -1613,12 +1852,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
@@ -1633,6 +1876,11 @@ main(int argc, char *argv[])
             "the capture isn't being saved to a file.");
           return 1;
         }
+        if (global_capture_opts.capture_comment) {
+          cmdarg_err("A capture comment was specified, but "
+            "the capture isn't being saved to a file.");
+          return 1;
+        }
       }
     }
   }
@@ -1669,6 +1917,16 @@ main(int argc, char *argv[])
   }
 #endif
 
+  if (ex_opt_count("read_format") > 0) {
+    const gchar* name = ex_opt_get_next("read_format");
+    in_file_type = open_info_name_to_type(name);
+    if (in_file_type == WTAP_TYPE_AUTO) {
+      cmdarg_err("\"%s\" isn't a valid read file format type", name? name : "");
+      list_read_capture_types();
+      return 1;
+    }
+  }
+
   /* disabled protocols as per configuration file */
   if (gdp_path == NULL && dp_path == NULL) {
     set_disabled_protos_list();
@@ -1694,8 +1952,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;");
-            cmdarg_err_cont(
+              "  Note: That read filter code looks like a valid capture filter;\n"
               "        maybe you mixed them up?");
           }
           pcap_close(pc);
@@ -1707,6 +1964,30 @@ 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;\n"
+              "        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. */
@@ -1733,8 +2014,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) {
     /*
@@ -1749,7 +2032,7 @@ main(int argc, char *argv[])
     relinquish_special_privs_perm();
     print_current_user();
 
-    if (cf_open(&cfile, cf_name, FALSE, &err) != CF_OK) {
+    if (cf_open(&cfile, cf_name, in_file_type, FALSE, &err) != CF_OK) {
       epan_cleanup();
       return 2;
     }
@@ -1807,58 +2090,78 @@ 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) && (*prefs_p->capture_device != '\0')) ? 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;
     }
 
+    /*
+     * If the standard error isn't a terminal, don't print packet counts,
+     * as they won't show up on the user's terminal and they'll get in
+     * the way of error messages in the file (to which we assume the
+     * standard error was redirected; if it's redirected to the null
+     * device, there's no point in printing packet counts anyway).
+     *
+     * Otherwise, if we're printing packet information and the standard
+     * output is a terminal (which we assume means the standard output and
+     * error are going to the same terminal), don't print packet counts,
+     * as they'll get in the way of the packet information.
+     *
+     * Otherwise, if the user specified -q, don't print packet counts.
+     *
+     * Otherwise, print packet counts.
+     *
+     * XXX - what if the user wants to do a live capture, doesn't want
+     * to save it to a file, doesn't want information printed for each
+     * packet, does want some "-z" statistic, and wants packet counts
+     * so they know whether they're seeing any packets?  -q will
+     * suppress the information printed for each packet, but it'll
+     * also suppress the packet counts.
+     */
+    if (!isatty(fileno(stderr)))
+      print_packet_counts = FALSE;
+    else if (print_packet_info && isatty(fileno(stdout)))
+      print_packet_counts = FALSE;
+    else if (quiet)
+      print_packet_counts = FALSE;
+    else
+      print_packet_counts = TRUE;
+
     if (print_packet_info) {
       if (!write_preamble(NULL)) {
         show_print_file_io_error(errno);
         return 2;
       }
-    } else if (!quiet) {
-      /*
-       * We're not printing information for each packet, and the user
-       * didn't ask us not to print a count of packets as they arrive,
-       * so print that count so the user knows that packets are arriving.
-       *
-       * XXX - what if the user wants to do a live capture, doesn't want
-       * to save it to a file, doesn't want information printed for each
-       * packet, does want some "-z" statistic, and wants packet counts
-       * so they know whether they're seeing any packets?
-       */
-      print_packet_counts = TRUE;
     }
 
     /* For now, assume libpcap gives microsecond precision. */
@@ -1875,7 +2178,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()) {
@@ -1899,6 +2202,7 @@ main(int argc, char *argv[])
 
   draw_tap_listeners(TRUE);
   funnel_dump_all_text_windows();
+  epan_free(cfile.epan);
   epan_cleanup();
 
   output_fields_free(output_fields);
@@ -1917,18 +2221,14 @@ main(int argc, char *argv[])
   guint32 packet_count = 0;
 
 
-/* XXX - move to the right position / file */
-/* read from a pipe (callback) */
-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;
 
@@ -1940,12 +2240,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);
 
@@ -1959,8 +2259,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
@@ -2022,19 +2322,54 @@ pipe_input_set_handler(gint source, gpointer user_data, int *child_process, pipe
 #endif
 }
 
+static 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;
+}
+
+static 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;
+  epan->get_user_comment = NULL;
+
+  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
 
   /*
@@ -2061,10 +2396,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. */
@@ -2102,7 +2436,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++) {
@@ -2114,10 +2448,11 @@ capture(void)
     g_array_insert_val(global_capture_opts.ifaces, i, interface_opts);
   }
 #ifdef _WIN32
-  if (global_capture_opts.ifaces->len < 2) {
+  if (global_capture_opts.ifaces->len < 2)
 #else
-  if (global_capture_opts.ifaces->len < 4) {
+  if (global_capture_opts.ifaces->len < 4)
 #endif
+  {
     for (i = 0; i < global_capture_opts.ifaces->len; i++) {
       interface_options interface_opts;
 
@@ -2131,15 +2466,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;
@@ -2206,16 +2543,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);
@@ -2224,17 +2554,18 @@ 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);
 
   if (dfilter_compile(interface_opts.cfilter, &rfcode) && rfcode != NULL) {
     cmdarg_err(
-      "Invalid capture filter \"%s\" for interface %s!\n"
+      "Invalid capture filter \"%s\" for interface '%s'!\n"
       "\n"
       "That string looks like a valid display filter; however, it isn't a valid\n"
       "capture filter (%s).\n"
@@ -2247,7 +2578,7 @@ capture_input_cfilter_error_message(capture_options *capture_opts, guint i, char
     dfilter_free(rfcode);
   } else {
     cmdarg_err(
-      "Invalid capture filter \"%s\" for interface %s!\n"
+      "Invalid capture filter \"%s\" for interface '%s'!\n"
       "\n"
       "That string isn't a valid capture filter (%s).\n"
       "See the User's Guide for a description of the capture filter syntax.",
@@ -2258,27 +2589,29 @@ 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 *) cap_session->cf)->wth = NULL;
       }
-      ((capture_file *) capture_opts->cf)->state = FILE_CLOSED;
+      ((capture_file *) cap_session->cf)->state = FILE_CLOSED;
     }
 
     g_free(capture_opts->save_file);
@@ -2292,9 +2625,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, WTAP_TYPE_AUTO, is_tempfile, &err)) {
     case CF_OK:
       break;
     case CF_ERROR:
@@ -2306,7 +2639,7 @@ capture_input_new_file(capture_options *capture_opts, gchar *new_file)
     }
   }
 
-  capture_opts->state = CAPTURE_RUNNING;
+  cap_session->state = CAPTURE_RUNNING;
 
   return TRUE;
 }
@@ -2314,15 +2647,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
   /*
@@ -2339,25 +2672,43 @@ 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) {
+    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;
+
+    /* 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
+       ("packet_details" is true). */
+    edt = epan_dissect_new(cf->epan, create_proto_tree, print_packet_info && print_details);
+
     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),
-                             filtering_tap_listeners, tap_flags);
+        ret = process_packet(cf, edt, data_offset, wtap_phdr(cf->wth),
+                             wtap_buf_ptr(cf->wth),
+                             tap_flags);
       }
       if (ret != FALSE) {
         /* packet successfully read and gone through the "Read Filter" */
         packet_count++;
       }
     }
+
+    epan_dissect_free(edt);
+
   } else {
     /*
      * Dumpcap's doing all the work; we're not doing any dissection.
@@ -2392,10 +2743,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
@@ -2422,7 +2773,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.
@@ -2443,18 +2794,18 @@ 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 *) capture_opts->cf;
+  capture_file *cf = (capture_file *) cap_session->cf;
 
   if (msg != NULL)
     fprintf(stderr, "tshark: %s\n", msg);
 
   report_counts();
 
-  if(cf != NULL && cf->wth != NULL) {
+  if (cf != NULL && cf->wth != NULL) {
     wtap_close(cf->wth);
-    if(cf->is_tempfile) {
+    if (cf->is_tempfile) {
       ws_unlink(cf->filename);
     }
   }
@@ -2495,7 +2846,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
@@ -2508,7 +2859,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
@@ -2518,15 +2869,13 @@ capture_cleanup(int signum _U_)
 #endif /* HAVE_LIBPCAP */
 
 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)
+process_packet_first_pass(capture_file *cf, epan_dissect_t *edt,
+               gint64 offset, struct wtap_pkthdr *whdr,
+               const guchar *pd)
 {
-  frame_data fdlocal;
-  guint32 framenum;
-  gboolean create_proto_tree = FALSE;
-  epan_dissect_t edt;
-  gboolean passed;
+  frame_data     fdlocal;
+  guint32        framenum;
+  gboolean       passed;
 
   /* The frame number of this packet is one more than the count of
      frames in this packet. */
@@ -2540,64 +2889,65 @@ 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.mac_name || gbl_resolv_flags.network_name || 
+  if (edt) {
+    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();
 
-    /* If we're going to be applying a read 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, create_proto_tree, FALSE);
-
     /* If we're running a read filter, prime the epan_dissect_t with that
        filter. */
     if (cf->rfcode)
-      epan_dissect_prime_dfilter(&edt, cf->rfcode);
+      epan_dissect_prime_dfilter(edt, cf->rfcode);
 
     frame_data_set_before_dissect(&fdlocal, &cf->elapsed_time,
-                                  &first_ts, prev_dis, prev_cap);
+                                  &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)
-      passed = dfilter_apply_edt(cf->rfcode, &edt);
+      passed = dfilter_apply_edt(cf->rfcode, edt);
   }
 
   if (passed) {
     frame_data_set_after_dissect(&fdlocal, &cum_bytes);
-    prev_dis_frame = fdlocal;
-    prev_dis = &prev_dis_frame;
-    frame_data_sequence_add(cf->frames, &fdlocal);
+    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 (edt) {
+      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);
   }
 
-  prev_cap_frame = fdlocal;
-  prev_cap = &prev_cap_frame;
-
-  if (do_dissection)
-    epan_dissect_cleanup(&edt);
+  if (edt)
+    epan_dissect_reset(edt);
 
   return passed;
 }
 
 static gboolean
-process_packet_second_pass(capture_file *cf, frame_data *fdata,
-               union wtap_pseudo_header *pseudo_header, const guchar *pd,
-               gboolean filtering_tap_listeners, guint tap_flags)
+process_packet_second_pass(capture_file *cf, epan_dissect_t *edt, frame_data *fdata,
+               struct wtap_pkthdr *phdr, Buffer *buf,
+               guint tap_flags)
 {
-  gboolean create_proto_tree;
-  column_info *cinfo;
-  epan_dissect_t edt;
-  gboolean passed;
+  column_info    *cinfo;
+  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
@@ -2607,64 +2957,51 @@ process_packet_second_pass(capture_file *cf, frame_data *fdata,
   /* 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
      do a dissection and do so. */
-  if (do_dissection) {
-    if (gbl_resolv_flags.mac_name || gbl_resolv_flags.network_name || 
+  if (edt) {
+    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();
 
-    if (cf->rfcode || verbose || filtering_tap_listeners ||
-        (tap_flags & TL_REQUIRES_PROTO_TREE) || have_custom_cols(&cf->cinfo))
-      create_proto_tree = TRUE;
-    else
-      create_proto_tree = FALSE;
-
-    /* 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);
-
-    /* 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);
-
-    col_custom_prime_edt(&edt, &cf->cinfo);
+    if (cf->dfcode)
+      epan_dissect_prime_dfilter(edt, cf->dfcode);
 
-    tap_queue_init(&edt);
+    col_custom_prime_edt(edt, &cf->cinfo);
 
     /* 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
          this packet. */
-      if (do_dissection)
-        print_packet(cf, &edt);
-      else
-        print_packet(cf, NULL);
+      print_packet(cf, edt);
 
       /* The ANSI C standard does not appear to *require* that a line-buffered
          stream be flushed to the host environment whenever a newline is
@@ -2694,12 +3031,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);
+  if (edt) {
+    epan_dissect_reset(edt);
   }
-  return passed;
+  return passed || fdata->flags.dependent_of_displayed;
 }
 
 static int
@@ -2711,19 +3050,22 @@ 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_section_t            *shb_hdr;
   wtapng_iface_descriptions_t *idb_inf;
   char         appname[100];
+  struct wtap_pkthdr phdr;
+  Buffer       buf;
+  epan_dissect_t *edt = NULL;
 
   shb_hdr = wtap_file_get_shb_info(cf->wth);
   idb_inf = wtap_file_get_idb_info(cf->wth);
 #ifdef PCAP_NG_DEFAULT
-  if (idb_inf->number_of_interfaces > 0) {
+  if (idb_inf->number_of_interfaces > 1) {
     linktype = WTAP_ENCAP_PER_PACKET;
   } else {
     linktype = wtap_file_encap(cf->wth);
@@ -2742,13 +3084,18 @@ load_cap_file(capture_file *cf, char *save_file, int out_file_type,
       snapshot_length = WTAP_MAX_PACKET_SIZE;
     }
     /* 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);
+    if (shb_hdr->shb_user_appl == NULL) {
+        g_snprintf(appname, sizeof(appname), "TShark " VERSION "%s", wireshark_gitversion);
         shb_hdr->shb_user_appl = appname;
     }
 
-    pdh = wtap_dump_open_ng(save_file, out_file_type, linktype, snapshot_length,
-        FALSE /* compressed */, shb_hdr, idb_inf, &err);
+    if (linktype != WTAP_ENCAP_PER_PACKET &&
+        out_file_type == WTAP_FILE_TYPE_SUBTYPE_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;
@@ -2764,7 +3111,7 @@ load_cap_file(capture_file *cf, char *save_file, int out_file_type,
       case WTAP_ERR_UNSUPPORTED_ENCAP:
       case WTAP_ERR_ENCAP_PER_PACKET_UNSUPPORTED:
         cmdarg_err("The capture file being read can't be written as a "
-          "\"%s\" file.", wtap_file_type_short_string(out_file_type));
+          "\"%s\" file.", wtap_file_type_subtype_short_string(out_file_type));
         break;
 
       case WTAP_ERR_CANT_OPEN:
@@ -2792,13 +3139,15 @@ load_cap_file(capture_file *cf, char *save_file, int out_file_type,
         goto out;
       }
     }
+    g_free(idb_inf);
+    idb_inf = NULL;
     pdh = NULL;
   }
 
   if (pdh && out_file_name_res) {
     if (!wtap_dump_set_addrinfo_list(pdh, get_addrinfo_list())) {
       cmdarg_err("The file format \"%s\" doesn't support name resolution information.",
-                 wtap_file_type_short_string(out_file_type));
+                 wtap_file_type_subtype_short_string(out_file_type));
     }
   }
 
@@ -2810,26 +3159,43 @@ load_cap_file(capture_file *cf, char *save_file, int out_file_type,
 
   if (perform_two_pass_analysis) {
     frame_data *fdata;
-    int old_max_packet_count = max_packet_count;
 
     /* Allocate a frame_data_sequence for all the frames. */
     cf->frames = new_frame_data_sequence();
 
+    if (do_dissection) {
+       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)
+        create_proto_tree = TRUE;
+
+      /* We're not going to display the protocol tree on this pass,
+         so it's not going to be "visible". */
+      edt = epan_dissect_new(cf->epan, create_proto_tree, FALSE);
+    }
+
     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))) {
+      if (process_packet_first_pass(cf, edt, data_offset, wtap_phdr(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;
         }
       }
     }
 
+    if (edt) {
+      epan_dissect_free(edt);
+      edt = NULL;
+    }
+
     /* Close the sequential I/O side, to free up memory it requires. */
     wtap_sequential_close(cf->wth);
 
@@ -2837,29 +3203,45 @@ load_cap_file(capture_file *cf, char *save_file, int out_file_type,
      * don't need after the sequential run-through of the packets. */
     postseq_cleanup_all_protocols();
 
-    max_packet_count = old_max_packet_count;
+    prev_dis = NULL;
+    prev_cap = NULL;
+    buffer_init(&buf, 1500);
+
+    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;
+
+      /* 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
+         ("packet_details" is true). */
+      edt = epan_dissect_new(cf->epan, create_proto_tree, print_packet_info && print_details);
+    }
 
     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, &phdr, &buf, &err,
+                         &err_info)) {
+        if (process_packet_second_pass(cf, edt, fdata, &phdr, &buf,
+                                       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, &phdr, buffer_start_ptr(&buf), &err)) {
               /* Error writing to a capture file */
               switch (err) {
 
               case WTAP_ERR_UNSUPPORTED_ENCAP:
                 /*
-                 * This is a problem with the particular frame we're writing;
-                 * note that, and give the frame number.
+                 * This is a problem with the particular frame we're writing
+                 * and the file type and subtype we're writing; note that,
+                 * and report the frame number and file type/subtype.
                  *
                  * XXX - framenum is not necessarily the frame number in
                  * the input file if there was a read filter.
@@ -2867,7 +3249,22 @@ load_cap_file(capture_file *cf, char *save_file, int out_file_type,
                 fprintf(stderr,
                         "Frame %u of \"%s\" has a network type that can't be saved in a \"%s\" file.\n",
                         framenum, cf->filename,
-                        wtap_file_type_short_string(out_file_type));
+                        wtap_file_type_subtype_short_string(out_file_type));
+                break;
+
+              case WTAP_ERR_PACKET_TOO_LARGE:
+                /*
+                 * This is a problem with the particular frame we're writing
+                 * and the file type and subtype we're writing; note that,
+                 * and report the frame number and file type/subtype.
+                 *
+                 * XXX - framenum is not necessarily the frame number in
+                 * the input file if there was a read filter.
+                 */
+                fprintf(stderr,
+                        "Frame %u of \"%s\" is too large for a \"%s\" file.\n",
+                        framenum, cf->filename,
+                        wtap_file_type_subtype_short_string(out_file_type));
                 break;
 
               default:
@@ -2879,46 +3276,72 @@ load_cap_file(capture_file *cf, char *save_file, int out_file_type,
               exit(2);
             }
           }
-          /* 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)) {
-            err = 0; /* This is not an error */
-            break;
-          }
         }
       }
     }
+
+    if (edt) {
+      epan_dissect_free(edt);
+      edt = NULL;
+    }
+
+    buffer_free(&buf);
   }
   else {
     framenum = 0;
+
+    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;
+
+      /* 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
+         ("packet_details" is true). */
+      edt = epan_dissect_new(cf->epan, create_proto_tree, print_packet_info && print_details);
+    }
+
     while (wtap_read(cf->wth, &err, &err_info, &data_offset)) {
       framenum++;
 
-      if (process_packet(cf, data_offset, wtap_phdr(cf->wth),
-                         wtap_pseudoheader(cf->wth), wtap_buf_ptr(cf->wth),
-                         filtering_tap_listeners, tap_flags)) {
+      if (process_packet(cf, edt, data_offset, wtap_phdr(cf->wth),
+                         wtap_buf_ptr(cf->wth),
+                         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) {
 
             case WTAP_ERR_UNSUPPORTED_ENCAP:
               /*
-               * This is a problem with the particular frame we're writing;
-               * note that, and give the frame number.
+               * This is a problem with the particular frame we're writing
+               * and the file type and subtype we're writing; note that,
+               * and report the frame number and file type/subtype.
                */
               fprintf(stderr,
                       "Frame %u of \"%s\" has a network type that can't be saved in a \"%s\" file.\n",
                       framenum, cf->filename,
-                      wtap_file_type_short_string(out_file_type));
+                      wtap_file_type_subtype_short_string(out_file_type));
+              break;
+
+            case WTAP_ERR_PACKET_TOO_LARGE:
+              /*
+               * This is a problem with the particular frame we're writing
+               * and the file type and subtype we're writing; note that,
+               * and report the frame number and file type/subtype.
+               */
+              fprintf(stderr,
+                      "Frame %u of \"%s\" is too large for a \"%s\" file.\n",
+                      framenum, cf->filename,
+                      wtap_file_type_subtype_short_string(out_file_type));
               break;
 
             default:
@@ -2930,16 +3353,21 @@ load_cap_file(capture_file *cf, char *save_file, int out_file_type,
             exit(2);
           }
         }
-        /* 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)) {
-          err = 0; /* This is not an error */
-          break;
-        }
       }
+      /* 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)) {
+        err = 0; /* This is not an error */
+        break;
+      }
+    }
+
+    if (edt) {
+      epan_dissect_free(edt);
+      edt = NULL;
     }
   }
 
@@ -3039,15 +3467,12 @@ out:
 }
 
 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)
+process_packet(capture_file *cf, epan_dissect_t *edt, gint64 offset, struct wtap_pkthdr *whdr,
+               const guchar *pd, guint tap_flags)
 {
-  frame_data fdata;
-  gboolean create_proto_tree;
-  column_info *cinfo;
-  epan_dissect_t edt;
-  gboolean passed;
+  frame_data      fdata;
+  column_info    *cinfo;
+  gboolean        passed;
 
   /* Count this packet. */
   cf->count++;
@@ -3062,71 +3487,53 @@ process_packet(capture_file *cf, gint64 offset, const struct wtap_pkthdr *whdr,
   /* 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
      do a dissection and do so. */
-  if (do_dissection) {
-    if (print_packet_info && (gbl_resolv_flags.mac_name || gbl_resolv_flags.network_name || 
+  if (edt) {
+    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();
 
-    if (cf->rfcode || verbose || filtering_tap_listeners ||
-        (tap_flags & TL_REQUIRES_PROTO_TREE) || have_custom_cols(&cf->cinfo))
-      create_proto_tree = TRUE;
-    else
-      create_proto_tree = FALSE;
-
-    /* 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);
-
-    /* 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);
-
-    col_custom_prime_edt(&edt, &cf->cinfo);
+    if (cf->dfcode)
+      epan_dissect_prime_dfilter(edt, cf->dfcode);
 
-    tap_queue_init(&edt);
+    col_custom_prime_edt(edt, &cf->cinfo);
 
     /* 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, prev_cap);
-
-    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. */
-    if (cf->rfcode)
-      passed = dfilter_apply_edt(cf->rfcode, &edt);
+    /* Run the filter if we have it. */
+    if (cf->dfcode)
+      passed = dfilter_apply_edt(cf->dfcode, edt);
   }
 
   if (passed) {
     frame_data_set_after_dissect(&fdata, &cum_bytes);
-    prev_dis_frame = fdata;
-    prev_dis = &prev_dis_frame;
 
     /* Process this packet. */
     if (print_packet_info) {
       /* We're printing packet information; print the information for
          this packet. */
-      if (do_dissection)
-        print_packet(cf, &edt);
-      else
-        print_packet(cf, NULL);
+      print_packet(cf, edt);
 
       /* The ANSI C standard does not appear to *require* that a line-buffered
          stream be flushed to the host environment whenever a newline is
@@ -3156,14 +3563,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);
+  if (edt) {
+    epan_dissect_reset(edt);
+    frame_data_destroy(&fdata);
   }
   return passed;
 }
@@ -3174,10 +3585,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_gitversion);
 
   case WRITE_XML:
-    if (verbose)
+    if (print_details)
       write_pdml_preamble(stdout, cf ? cf->filename : NULL);
     else
       write_psml_preamble(stdout);
@@ -3196,32 +3607,63 @@ 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;
 }
 
+static inline void
+put_string(char *dest, const char *str, size_t str_len)
+{
+  memcpy(dest, str, str_len);
+  dest[str_len] = '\0';
+}
+
+static inline void
+put_spaces_string(char *dest, const char *str, size_t str_len, size_t str_with_spaces)
+{
+  size_t i;
+
+  for (i = str_len; i < str_with_spaces; i++)
+    *dest++ = ' ';
+
+  put_string(dest, str, str_len);
+}
+
+static inline void
+put_string_spaces(char *dest, const char *str, size_t str_len, size_t str_with_spaces)
+{
+  size_t i;
+
+  memcpy(dest, str, str_len);
+  for (i = str_len; i < str_with_spaces; i++)
+    dest[i] = ' ';
+
+  dest[str_with_spaces] = '\0';
+}
+
 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;
+  size_t  col_len;
 
   line_bufp = get_line_buf(256);
   buf_offset = 0;
@@ -3232,39 +3674,26 @@ print_columns(capture_file *cf)
       continue;
     switch (cf->cinfo.col_fmt[i]) {
     case COL_NUMBER:
-#ifdef HAVE_LIBPCAP
-      /*
-       * Don't print this if we're doing a live capture from a network
-       * interface - if we're doing a live capture, you won't be
-       * able to look at the capture in the future (it's not being
-       * saved anywhere), so the frame numbers are unlikely to be
-       * useful.
-       *
-       * (XXX - it might be nice to be able to save and print at
-       * the same time, sort of like an "Update list of packets
-       * in real time" capture in Wireshark.)
-       */
-      if (global_capture_opts.ifaces->len > 0)
-        continue;
-#endif
-      column_len = strlen(cf->cinfo.col_data[i]);
+      column_len = col_len = strlen(cf->cinfo.col_data[i]);
       if (column_len < 3)
         column_len = 3;
       line_bufp = get_line_buf(buf_offset + column_len);
-      g_snprintf(line_bufp + buf_offset, (int)column_len + 1, "%3s", cf->cinfo.col_data[i]);
+      put_spaces_string(line_bufp + buf_offset, cf->cinfo.col_data[i], col_len, column_len);
       break;
 
     case COL_CLS_TIME:
     case COL_REL_TIME:
     case COL_ABS_TIME:
-    case COL_ABS_DATE_TIME:
+    case COL_ABS_YMD_TIME:  /* XXX - wider */
+    case COL_ABS_YDOY_TIME: /* XXX - wider */
     case COL_UTC_TIME:
-    case COL_UTC_DATE_TIME: /* XXX - wider */
-      column_len = strlen(cf->cinfo.col_data[i]);
+    case COL_UTC_YMD_TIME:  /* XXX - wider */
+    case COL_UTC_YDOY_TIME: /* XXX - wider */
+      column_len = col_len = strlen(cf->cinfo.col_data[i]);
       if (column_len < 10)
         column_len = 10;
       line_bufp = get_line_buf(buf_offset + column_len);
-      g_snprintf(line_bufp + buf_offset, (int)column_len + 1, "%10s", cf->cinfo.col_data[i]);
+      put_spaces_string(line_bufp + buf_offset, cf->cinfo.col_data[i], col_len, column_len);
       break;
 
     case COL_DEF_SRC:
@@ -3276,11 +3705,11 @@ print_columns(capture_file *cf)
     case COL_DEF_NET_SRC:
     case COL_RES_NET_SRC:
     case COL_UNRES_NET_SRC:
-      column_len = strlen(cf->cinfo.col_data[i]);
+      column_len = col_len = strlen(cf->cinfo.col_data[i]);
       if (column_len < 12)
         column_len = 12;
       line_bufp = get_line_buf(buf_offset + column_len);
-      g_snprintf(line_bufp + buf_offset, (int)column_len + 1, "%12s", cf->cinfo.col_data[i]);
+      put_spaces_string(line_bufp + buf_offset, cf->cinfo.col_data[i], col_len, column_len);
       break;
 
     case COL_DEF_DST:
@@ -3292,17 +3721,17 @@ print_columns(capture_file *cf)
     case COL_DEF_NET_DST:
     case COL_RES_NET_DST:
     case COL_UNRES_NET_DST:
-      column_len = strlen(cf->cinfo.col_data[i]);
+      column_len = col_len = strlen(cf->cinfo.col_data[i]);
       if (column_len < 12)
         column_len = 12;
       line_bufp = get_line_buf(buf_offset + column_len);
-      g_snprintf(line_bufp + buf_offset, (int)column_len + 1, "%-12s", cf->cinfo.col_data[i]);
+      put_string_spaces(line_bufp + buf_offset, cf->cinfo.col_data[i], col_len, column_len);
       break;
 
     default:
       column_len = strlen(cf->cinfo.col_data[i]);
       line_bufp = get_line_buf(buf_offset + column_len);
-      g_strlcat(line_bufp + buf_offset, cf->cinfo.col_data[i], column_len + 1);
+      put_string(line_bufp + buf_offset, cf->cinfo.col_data[i], column_len);
       break;
     }
     buf_offset += column_len;
@@ -3332,12 +3761,12 @@ print_columns(capture_file *cf)
         case COL_DEF_DST:
         case COL_RES_DST:
         case COL_UNRES_DST:
-          g_strlcat(line_bufp + buf_offset, " -> ", 5);
+          put_string(line_bufp + buf_offset, " -> ", 4);
           buf_offset += 4;
           break;
 
         default:
-          g_strlcat(line_bufp + buf_offset, " ", 5);
+          put_string(line_bufp + buf_offset, " ", 1);
           buf_offset += 1;
           break;
         }
@@ -3351,12 +3780,12 @@ print_columns(capture_file *cf)
         case COL_DEF_DL_DST:
         case COL_RES_DL_DST:
         case COL_UNRES_DL_DST:
-          g_strlcat(line_bufp + buf_offset, " -> ", 5);
+          put_string(line_bufp + buf_offset, " -> ", 4);
           buf_offset += 4;
           break;
 
         default:
-          g_strlcat(line_bufp + buf_offset, " ", 5);
+          put_string(line_bufp + buf_offset, " ", 1);
           buf_offset += 1;
           break;
         }
@@ -3370,12 +3799,12 @@ print_columns(capture_file *cf)
         case COL_DEF_NET_DST:
         case COL_RES_NET_DST:
         case COL_UNRES_NET_DST:
-          g_strlcat(line_bufp + buf_offset, " -> ", 5);
+          put_string(line_bufp + buf_offset, " -> ", 4);
           buf_offset += 4;
           break;
 
         default:
-          g_strlcat(line_bufp + buf_offset, " ", 5);
+          put_string(line_bufp + buf_offset, " ", 1);
           buf_offset += 1;
           break;
         }
@@ -3389,12 +3818,12 @@ print_columns(capture_file *cf)
         case COL_DEF_SRC:
         case COL_RES_SRC:
         case COL_UNRES_SRC:
-          g_strlcat(line_bufp + buf_offset, " <- ", 5);
+          put_string(line_bufp + buf_offset, " <- ", 4);
           buf_offset += 4;
           break;
 
         default:
-          g_strlcat(line_bufp + buf_offset, " ", 5);
+          put_string(line_bufp + buf_offset, " ", 1);
           buf_offset += 1;
           break;
         }
@@ -3408,12 +3837,12 @@ print_columns(capture_file *cf)
         case COL_DEF_DL_SRC:
         case COL_RES_DL_SRC:
         case COL_UNRES_DL_SRC:
-          g_strlcat(line_bufp + buf_offset, " <- ", 5);
+          put_string(line_bufp + buf_offset, " <- ", 4);
           buf_offset += 4;
           break;
 
         default:
-          g_strlcat(line_bufp + buf_offset, " ", 5);
+          put_string(line_bufp + buf_offset, " ", 1);
           buf_offset += 1;
           break;
         }
@@ -3427,19 +3856,19 @@ print_columns(capture_file *cf)
         case COL_DEF_NET_SRC:
         case COL_RES_NET_SRC:
         case COL_UNRES_NET_SRC:
-          g_strlcat(line_bufp + buf_offset, " <- ", 5);
+          put_string(line_bufp + buf_offset, " <- ", 4);
           buf_offset += 4;
           break;
 
         default:
-          g_strlcat(line_bufp + buf_offset, " ", 5);
+          put_string(line_bufp + buf_offset, " ", 1);
           buf_offset += 1;
           break;
         }
         break;
 
       default:
-        g_strlcat(line_bufp + buf_offset, " ", 5);
+        put_string(line_bufp + buf_offset, " ", 1);
         buf_offset += 1;
         break;
       }
@@ -3451,9 +3880,31 @@ 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) {
+
+      case WRITE_TEXT:
+        if (!print_columns(cf))
+          return FALSE;
+        break;
 
-  if (verbose) {
+      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) {
 
@@ -3463,19 +3914,16 @@ print_packet(capture_file *cf, epan_dissect_t *edt)
        * 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_summary = print_summary;
       print_args.print_formfeed = FALSE;
-      packet_range_init(&print_args.range);
+      packet_range_init(&print_args.range, &cfile);
       */
-      print_args.print_hex = verbose && print_hex;
-      print_args.print_dissections = verbose ? print_dissections_expanded : print_dissections_none;
+      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;
       }
@@ -3486,34 +3934,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;
@@ -3528,7 +3961,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);
@@ -3545,22 +3978,21 @@ write_finale(void)
 }
 
 cf_status_t
-cf_open(capture_file *cf, const char *fname, gboolean is_tempfile, int *err)
+cf_open(capture_file *cf, const char *fname, unsigned int type, 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);
+  wth = wtap_open_offline(fname, type, err, &err_info, perform_two_pass_analysis);
   if (wth == NULL)
     goto fail;
 
   /* 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 */
@@ -3576,7 +4008,7 @@ cf_open(capture_file *cf, const char *fname, gboolean is_tempfile, int *err)
   /* No user changes yet. */
   cf->unsaved_changes = FALSE;
 
-  cf->cd_t      = wtap_file_type(cf->wth);
+  cf->cd_t      = wtap_file_type_subtype(cf->wth);
   cf->count     = 0;
   cf->drops_known = FALSE;
   cf->drops     = 0;
@@ -3588,7 +4020,7 @@ 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);
+  ref = NULL;
   prev_dis = NULL;
   prev_cap = NULL;
 
@@ -3714,7 +4146,7 @@ cf_open_error_message(int err, gchar *err_info, gboolean for_writing,
       /* Seen only when opening a capture file for writing. */
       g_snprintf(errmsg_errno, sizeof(errmsg_errno),
                  "The file \"%%s\" is a pipe, and \"%s\" capture files can't be "
-                 "written to a pipe.", wtap_file_type_short_string(file_type));
+                 "written to a pipe.", wtap_file_type_subtype_short_string(file_type));
       errmsg = errmsg_errno;
       break;
 
@@ -3727,7 +4159,7 @@ cf_open_error_message(int err, gchar *err_info, gboolean for_writing,
       if (for_writing) {
         g_snprintf(errmsg_errno, sizeof(errmsg_errno),
                    "TShark can't save this capture as a \"%s\" file.",
-                   wtap_file_type_short_string(file_type));
+                   wtap_file_type_subtype_short_string(file_type));
       } else {
         g_snprintf(errmsg_errno, sizeof(errmsg_errno),
                  "The file \"%%s\" is a capture for a network type that TShark doesn't support.\n"
@@ -3741,7 +4173,7 @@ cf_open_error_message(int err, gchar *err_info, gboolean for_writing,
       if (for_writing) {
         g_snprintf(errmsg_errno, sizeof(errmsg_errno),
                    "TShark can't save this capture as a \"%s\" file.",
-                   wtap_file_type_short_string(file_type));
+                   wtap_file_type_subtype_short_string(file_type));
         errmsg = errmsg_errno;
       } else
         errmsg = "The file \"%s\" is a capture for a network type that TShark doesn't support.";
@@ -3841,26 +4273,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.
  */
@@ -3887,3 +4299,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:
+ */