From Harald Welte:
[obnox/wireshark/wip.git] / tshark.c
index 5032086ba33072850296ca821b99356949e57937..296ab4a5ff7c3123c3435f144de8515ba32a8f96 100644 (file)
--- a/tshark.c
+++ b/tshark.c
 # include <sys/stat.h>
 #endif
 
-#ifdef NEED_STRERROR_H
-#include "wsutil/strerror.h"
-#endif
-
-#ifdef HAVE_GETOPT_H
-#include <getopt.h>
-#else
+#ifndef HAVE_GETOPT
 #include "wsutil/wsgetopt.h"
 #endif
 
 #include "capture-pcap-util.h"
 #ifdef _WIN32
 #include "capture-wpcap.h"
-#include "capture_errs.h"
+#include <wsutil/unicode-utils.h>
 #endif /* _WIN32 */
 #include "capture_sync.h"
 #endif /* HAVE_LIBPCAP */
 #include "log.h"
 #include <epan/funnel.h>
-
+#include "capture_opts.h"
 
 /*
  * This is the template for the decode as option; it is shared between the
@@ -139,13 +133,15 @@ 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 = "";
+
 #ifdef HAVE_LIBPCAP
 /*
  * TRUE if we're to print packet counts to keep track of captured packets.
  */
 static gboolean print_packet_counts;
 
-
 static capture_options global_capture_opts;
 
 #ifdef SIGINFO
@@ -165,7 +161,7 @@ static void report_counts_siginfo(int);
 #endif /* _WIN32 */
 #endif /* HAVE_LIBPCAP */
 
-static int load_cap_file(capture_file *, char *, int, int, gint64);
+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);
@@ -185,21 +181,45 @@ static void write_failure_message(const char *filename, int err);
 
 capture_file cfile;
 
-void
-cf_mark_frame(capture_file *cf _U_, frame_data *frame _U_)
+struct string_elem {
+  const char *sstr;   /* The short string */
+  const char *lstr;   /* The long string */
+};
+
+static gint
+string_compare(gconstpointer a, gconstpointer b)
+{
+  return strcmp(((const struct string_elem *)a)->sstr,
+                ((const struct string_elem *)b)->sstr);
+}
+
+static void
+string_elem_print(gpointer data, gpointer not_used _U_)
 {
-  g_assert_not_reached();
+  fprintf(stderr, "    %s - %s\n",
+          ((struct string_elem *)data)->sstr,
+          ((struct string_elem *)data)->lstr);
 }
 
-static void list_capture_types(void) {
+static void
+list_capture_types(void) {
   int i;
+  struct string_elem *captypes;
+  GSList *list = NULL;
 
-  fprintf(stderr, "editcap: The available capture file types for \"F\":\n");
+  captypes = g_malloc(sizeof(struct string_elem) * WTAP_NUM_FILE_TYPES);
+
+  fprintf(stderr, "tshark: The available capture file types for the \"-F\" flag are:\n");
   for (i = 0; i < WTAP_NUM_FILE_TYPES; i++) {
-    if (wtap_dump_can_open(i))
-      fprintf(stderr, "    %s - %s\n",
-              wtap_file_type_short_string(i), wtap_file_type_string(i));
+    if (wtap_dump_can_open(i)) {
+      captypes[i].sstr = wtap_file_type_short_string(i);
+      captypes[i].lstr = wtap_file_type_string(i);
+      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
@@ -257,22 +277,28 @@ print_usage(gboolean print_ver)
 
   fprintf(output, "\n");
   fprintf(output, "Processing:\n");
+  fprintf(output, "  -2                       perform a two-pass analysis\n");
   fprintf(output, "  -R <read filter>         packet filter in Wireshark display filter syntax\n");
   fprintf(output, "  -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);
   fprintf(output, "                           \"Decode As\", see the man page for details\n");
   fprintf(output, "                           Example: tcp.port==8888,http\n");
+  fprintf(output, "  -H <hosts file>          read a list of entries from a hosts file, which will\n");
+  fprintf(output, "                           then be written to a capture file. (Implies -W n)\n");
 
   /*fprintf(output, "\n");*/
   fprintf(output, "Output:\n");
   fprintf(output, "  -w <outfile|->           write packets to a pcap-format file named \"outfile\"\n");
   fprintf(output, "                           (or to the standard output for \"-\")\n");
   fprintf(output, "  -C <config profile>      start with specified configuration profile\n");
-  fprintf(output, "  -F <output file type>    set the output file type, default is libpcap\n");
+  fprintf(output, "  -F <output file type>    set the output file type, default is pcapng\n");
   fprintf(output, "                           an empty \"-F\" option will list the file types\n");
   fprintf(output, "  -V                       add output of packet tree        (Packet Details)\n");
-  fprintf(output, "  -S                       display packets even when writing to a file\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, "  -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");
@@ -282,12 +308,15 @@ print_usage(gboolean print_ver)
   fprintf(output, "     header=y|n            switch headers on and off\n");
   fprintf(output, "     separator=/t|/s|<char> select tab, space, printable character as separator\n");
   fprintf(output, "     occurrence=f|l|a      print first, last or all occurrences of each field\n");
-  fprintf(output, "     aggregator=,|/s|<char> select comma, space, printable character as aggregator\n");
+  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, "  -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, "  -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");
 
@@ -320,7 +349,9 @@ glossary_option_help(void)
   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 decodes               dump \"layer type\"/\"decode as\" associations and exit\n");
+  fprintf(output, "  -G heuristic-decodes     dump heuristic dissector tables\n");
   fprintf(output, "\n");
   fprintf(output, "Preference reports:\n");
   fprintf(output, "  -G defaultprefs          dump default preferences and exit\n");
@@ -566,7 +597,6 @@ add_decode_as(const gchar *cl_param)
 
   case FT_STRING:
   case FT_STRINGZ:
-  case FT_EBCDIC:
     /* The selector for this table is a string. */
     break;
 
@@ -663,7 +693,6 @@ add_decode_as(const gchar *cl_param)
 
   case FT_STRING:
   case FT_STRINGZ:
-  case FT_EBCDIC:
     /* The selector for this table is a string. */
     dissector_change_string(table_name, selector_str, dissector_matching);
     break;
@@ -673,7 +702,7 @@ add_decode_as(const gchar *cl_param)
        than the ones listed above. */
     g_assert_not_reached();
   }
-  g_free(decoded_param); /* "Decode As" rule has been succesfully added */
+  g_free(decoded_param); /* "Decode As" rule has been successfully added */
   return TRUE;
 }
 
@@ -727,12 +756,16 @@ print_current_user(void) {
     cur_group = get_cur_groupname();
     fprintf(stderr, "Running as user \"%s\" and group \"%s\".",
       cur_user, cur_group);
-    g_free(cur_user);
-    g_free(cur_group);
     if (running_with_special_privs()) {
-      fprintf(stderr, " This could be dangerous.");
+      fprintf(stderr, "Running as user \"%s\" and group \"%s\". This could be dangerous.\n",
+         cur_user, cur_group);
     }
-    fprintf(stderr, "\n");
+    else {
+      fprintf(stdout, "Running as user \"%s\" and group \"%s\".",
+         cur_user, cur_group);
+    }
+    g_free(cur_user);
+    g_free(cur_group);
   }
 }
 
@@ -780,19 +813,27 @@ main(int argc, char *argv[])
   int                  gdp_open_errno, gdp_read_errno;
   int                  dp_open_errno, dp_read_errno;
   int                  err;
-  int                  exit_status = 0;
+  volatile int         exit_status = 0;
 #ifdef HAVE_LIBPCAP
   gboolean             list_link_layer_types = FALSE;
   gboolean             start_capture = FALSE;
   int                  status;
   GList               *if_list;
   gchar               *err_str;
+  guint                i;
+  interface_options    interface_opts;
 #else
   gboolean             capture_option_specified = FALSE;
 #endif
   gboolean             quiet = FALSE;
-  int                  out_file_type = WTAP_FILE_PCAP;
-  gchar               *cf_name = NULL, *rfilter = NULL;
+#ifdef PCAP_NG_DEFAULT
+  volatile int         out_file_type = WTAP_FILE_PCAPNG;
+#else
+  volatile int         out_file_type = WTAP_FILE_PCAP;
+#endif
+  volatile gboolean    out_file_name_res = FALSE;
+  gchar               *volatile cf_name = NULL;
+  gchar               *rfilter = NULL;
 #ifdef HAVE_PCAP_OPEN_DEAD
   struct bpf_program   fcode;
 #endif
@@ -801,6 +842,7 @@ main(int argc, char *argv[])
   char                 badopt;
   GLogLevelFlags       log_flags;
   int                  optind_initial;
+  gchar               *output_only = NULL;
 
 #ifdef HAVE_LIBPCAP
 #if defined(_WIN32) || defined(HAVE_PCAP_CREATE)
@@ -818,10 +860,17 @@ main(int argc, char *argv[])
 #define OPTSTRING_I ""
 #endif
 
-#define OPTSTRING "a:b:" OPTSTRING_B "c:C:d:De:E:f:F:G:hi:" OPTSTRING_I "K:lLnN:o:pPqr:R:s:St:T:u:vVw:xX:y:z:"
+#define OPTSTRING "2a:A:b:" OPTSTRING_B "c:C:d:De:E:f:F:G:hH:i:" OPTSTRING_I "K:lLnN:o:O:pPqr:R:s:S:t:T:u:vVw:W:xX:y:z:"
 
   static const char    optstring[] = OPTSTRING;
 
+#ifdef _WIN32
+  arg_list_utf_16to8(argc, argv);
+#if !GLIB_CHECK_VERSION(2,31,0)
+  g_thread_init(NULL);
+#endif
+#endif /* _WIN32 */
+
   /*
    * Get credential information for later use.
    */
@@ -846,7 +895,7 @@ main(int argc, char *argv[])
   while ((opt = getopt(argc, argv, optstring)) != -1) {
     switch (opt) {
     case 'C':        /* Configuration Profile */
-      if (profile_exists (optarg)) {
+      if (profile_exists (optarg, FALSE)) {
         set_profile_name (optarg);
       } else {
         cmdarg_err("Configuration Profile \"%s\" does not exist", optarg);
@@ -950,10 +999,16 @@ main(int argc, char *argv[])
         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();
       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)
+        plugins_dump_all();
       else if (strcmp(argv[2], "?") == 0)
         glossary_option_help();
       else if (strcmp(argv[2], "-?") == 0)
@@ -978,21 +1033,21 @@ main(int argc, char *argv[])
   if (gpf_path != NULL) {
     if (gpf_open_errno != 0) {
       cmdarg_err("Can't open global preferences file \"%s\": %s.",
-              pf_path, strerror(gpf_open_errno));
+              pf_path, g_strerror(gpf_open_errno));
     }
     if (gpf_read_errno != 0) {
       cmdarg_err("I/O error reading global preferences file \"%s\": %s.",
-              pf_path, strerror(gpf_read_errno));
+              pf_path, g_strerror(gpf_read_errno));
     }
   }
   if (pf_path != NULL) {
     if (pf_open_errno != 0) {
       cmdarg_err("Can't open your preferences file \"%s\": %s.", pf_path,
-              strerror(pf_open_errno));
+              g_strerror(pf_open_errno));
     }
     if (pf_read_errno != 0) {
       cmdarg_err("I/O error reading your preferences file \"%s\": %s.",
-              pf_path, strerror(pf_read_errno));
+              pf_path, g_strerror(pf_read_errno));
     }
     g_free(pf_path);
     pf_path = NULL;
@@ -1007,11 +1062,11 @@ main(int argc, char *argv[])
   if (gdp_path != NULL) {
     if (gdp_open_errno != 0) {
       cmdarg_err("Could not open global disabled protocols file\n\"%s\": %s.",
-                 gdp_path, strerror(gdp_open_errno));
+                 gdp_path, g_strerror(gdp_open_errno));
     }
     if (gdp_read_errno != 0) {
       cmdarg_err("I/O error reading global disabled protocols file\n\"%s\": %s.",
-                 gdp_path, strerror(gdp_read_errno));
+                 gdp_path, g_strerror(gdp_read_errno));
     }
     g_free(gdp_path);
   }
@@ -1019,12 +1074,12 @@ main(int argc, char *argv[])
     if (dp_open_errno != 0) {
       cmdarg_err(
         "Could not open your disabled protocols file\n\"%s\": %s.", dp_path,
-        strerror(dp_open_errno));
+        g_strerror(dp_open_errno));
     }
     if (dp_read_errno != 0) {
       cmdarg_err(
         "I/O error reading your disabled protocols file\n\"%s\": %s.", dp_path,
-        strerror(dp_read_errno));
+        g_strerror(dp_read_errno));
     }
     g_free(dp_path);
   }
@@ -1041,274 +1096,297 @@ main(int argc, char *argv[])
   /* Now get our args */
   while ((opt = getopt(argc, argv, optstring)) != -1) {
     switch (opt) {
-      case 'a':        /* autostop criteria */
-      case 'b':        /* Ringbuffer option */
-      case 'c':        /* Capture x packets */
-      case 'f':        /* capture filter */
-      case 'i':        /* Use interface x */
-      case 'p':        /* Don't capture in promiscuous mode */
+    case '2':        /* Perform two pass analysis */
+      perform_two_pass_analysis = TRUE;
+      break;
+    case 'a':        /* autostop criteria */
+    case 'b':        /* Ringbuffer option */
+    case 'c':        /* Capture x packets */
+    case 'f':        /* capture filter */
+    case 'i':        /* Use interface x */
+    case 'p':        /* Don't capture in promiscuous mode */
 #ifdef HAVE_PCAP_CREATE
-      case 'I':        /* Capture in monitor mode, if available */
+    case 'I':        /* Capture in monitor mode, if available */
 #endif
-      case 's':        /* Set the snapshot (capture) length */
-      case 'w':        /* Write to capture file x */
-      case 'y':        /* Set the pcap data link type */
+    case 's':        /* Set the snapshot (capture) length */
+    case 'w':        /* Write to capture file x */
+    case 'y':        /* Set the pcap data link type */
 #if defined(_WIN32) || defined(HAVE_PCAP_CREATE)
-      case 'B':        /* Buffer size */
+    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) {
-            return status;
-        }
+      status = capture_opts_add_opt(&global_capture_opts, opt, optarg, &start_capture);
+      if(status != 0) {
+        return status;
+      }
 #else
-        capture_option_specified = TRUE;
-        arg_error = TRUE;
+      capture_option_specified = TRUE;
+      arg_error = TRUE;
 #endif
-        break;
-      case 'C':
-        /* Configuration profile settings were already processed just ignore them this time*/
-        break;
-      case 'd':        /* Decode as rule */
-        if (!add_decode_as(optarg))
-          return 1;
-        break;
+      break;
+    case 'C':
+      /* Configuration profile settings were already processed just ignore them this time*/
+      break;
+    case 'd':        /* Decode as rule */
+      if (!add_decode_as(optarg))
+        return 1;
+      break;
 #if defined(HAVE_HEIMDAL_KERBEROS) || defined(HAVE_MIT_KERBEROS)
-      case 'K':        /* Kerberos keytab file */
-        read_keytab_file(optarg);
-        break;
+    case 'K':        /* Kerberos keytab file */
+      read_keytab_file(optarg);
+      break;
 #endif
-      case 'D':        /* Print a list of capture devices and exit */
+    case 'D':        /* Print a list of capture devices and exit */
 #ifdef HAVE_LIBPCAP
-        if_list = capture_interface_list(&err, &err_str);
-        if (if_list == NULL) {
-          switch (err) {
-          case CANT_GET_INTERFACE_LIST:
-            cmdarg_err("%s", err_str);
-            g_free(err_str);
-            break;
+      if_list = capture_interface_list(&err, &err_str);
+      if (if_list == NULL) {
+        switch (err) {
+        case CANT_GET_INTERFACE_LIST:
+        case DONT_HAVE_PCAP:
+          cmdarg_err("%s", err_str);
+          g_free(err_str);
+          break;
 
-          case NO_INTERFACES_FOUND:
-            cmdarg_err("There are no interfaces on which a capture can be done");
-            break;
-          }
-          return 2;
+        case NO_INTERFACES_FOUND:
+          cmdarg_err("There are no interfaces on which a capture can be done");
+          break;
         }
-        capture_opts_print_interfaces(if_list);
-        free_interface_list(if_list);
-        return 0;
+        return 2;
+      }
+      capture_opts_print_interfaces(if_list);
+      free_interface_list(if_list);
+      return 0;
 #else
-        capture_option_specified = TRUE;
-        arg_error = TRUE;
+      capture_option_specified = TRUE;
+      arg_error = TRUE;
 #endif
-        break;
-      case 'e':
-        /* Field entry */
-        output_fields_add(output_fields, optarg);
-        break;
-      case 'E':
-        /* Field option */
-        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);
-        if (out_file_type < 0) {
-          cmdarg_err("\"%s\" isn't a valid capture file type", optarg);
-          list_capture_types();
-          return 1;
-        }
-        break;
-      case 'h':        /* Print help and exit */
-        print_usage(TRUE);
-        return 0;
-        break;
-      case 'l':        /* "Line-buffer" standard output */
-        /* This isn't line-buffering, strictly speaking, it's just
-           flushing the standard output after the information for
-           each packet is printed; however, that should be good
-           enough for all the purposes to which "-l" is put (and
-           is probably actually better for "-V", as it does fewer
-           writes).
-
-           See the comment in "process_packet()" for an explanation of
-           why we do that, and why we don't just use "setvbuf()" to
-           make the standard output line-buffered (short version: in
-           Windows, "line-buffered" is the same as "fully-buffered",
-           and the output buffer is only flushed when it fills up). */
-        line_buffered = TRUE;
-        break;
-      case 'L':        /* Print list of link-layer types and exit */
+      break;
+    case 'e':
+      /* Field entry */
+      output_fields_add(output_fields, optarg);
+      break;
+    case 'E':
+      /* Field option */
+      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);
+      if (out_file_type < 0) {
+        cmdarg_err("\"%s\" isn't a valid capture file type", optarg);
+        list_capture_types();
+        return 1;
+      }
+      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'))
+        out_file_name_res = TRUE;
+      break;
+    case 'H':        /* Read address to name mappings from a hosts file */
+      if (! read_hosts_file(optarg))
+      {
+        cmdarg_err("Can't read host entries from \"%s\"", optarg);
+        return 1;
+      }
+      out_file_name_res = TRUE;
+      break;
+
+    case 'h':        /* Print help and exit */
+      print_usage(TRUE);
+      return 0;
+      break;
+    case 'l':        /* "Line-buffer" standard output */
+      /* This isn't line-buffering, strictly speaking, it's just
+         flushing the standard output after the information for
+         each packet is printed; however, that should be good
+         enough for all the purposes to which "-l" is put (and
+         is probably actually better for "-V", as it does fewer
+         writes).
+
+         See the comment in "process_packet()" for an explanation of
+         why we do that, and why we don't just use "setvbuf()" to
+         make the standard output line-buffered (short version: in
+         Windows, "line-buffered" is the same as "fully-buffered",
+         and the output buffer is only flushed when it fills up). */
+      line_buffered = TRUE;
+      break;
+    case 'L':        /* Print list of link-layer types and exit */
 #ifdef HAVE_LIBPCAP
-        list_link_layer_types = TRUE;
+      list_link_layer_types = TRUE;
 #else
-        capture_option_specified = TRUE;
-        arg_error = TRUE;
-#endif
-        break;
-#if GLIB_CHECK_VERSION(2,10,0)
-      case 'P':        /* Perform two pass analysis */
-        perform_two_pass_analysis = TRUE;
-        break;
+      capture_option_specified = TRUE;
+      arg_error = TRUE;
 #endif
-      case 'n':        /* No name resolution */
+      break;
+    case 'n':        /* No name resolution */
+      gbl_resolv_flags = RESOLV_NONE;
+      break;
+    case 'N':        /* Select what types of addresses/port #s to resolve */
+      if (gbl_resolv_flags == RESOLV_ALL)
         gbl_resolv_flags = RESOLV_NONE;
-        break;
-      case 'N':        /* Select what types of addresses/port #s to resolve */
-        if (gbl_resolv_flags == RESOLV_ALL)
-          gbl_resolv_flags = RESOLV_NONE;
-        badopt = string_to_name_resolve(optarg, &gbl_resolv_flags);
-        if (badopt != '\0') {
-          cmdarg_err("-N specifies unknown resolving option '%c';",
-                     badopt);
-          cmdarg_err_cont( "           Valid options are 'm', 'n', 't', and 'C'");
-          return 1;
-        }
-        break;
-      case 'o':        /* Override preference from command line */
-        switch (prefs_set_pref(optarg)) {
-
-        case PREFS_SET_OK:
-          break;
-
-        case PREFS_SET_SYNTAX_ERR:
-          cmdarg_err("Invalid -o flag \"%s\"", optarg);
-          return 1;
-          break;
+      badopt = string_to_name_resolve(optarg, &gbl_resolv_flags);
+      if (badopt != '\0') {
+        cmdarg_err("-N specifies unknown resolving option '%c';",
+                   badopt);
+        cmdarg_err_cont( "           Valid options are 'm', 'n', 't', and 'C'");
+        return 1;
+      }
+      break;
+    case 'o':        /* Override preference from command line */
+      switch (prefs_set_pref(optarg)) {
 
-        case PREFS_SET_NO_SUCH_PREF:
-        case PREFS_SET_OBSOLETE:
-          cmdarg_err("-o flag \"%s\" specifies unknown preference", optarg);
-          return 1;
-          break;
-        }
-        break;
-      case 'q':        /* Quiet */
-        quiet = TRUE;
-        break;
-      case 'r':        /* Read capture file x */
-        cf_name = g_strdup(optarg);
-        break;
-      case 'R':        /* Read file filter */
-        rfilter = optarg;
-        break;
-      case 'S':        /* show packets in real time */
-        print_packet_info = TRUE;
+      case PREFS_SET_OK:
         break;
-      case 't':        /* Time stamp type */
-        if (strcmp(optarg, "r") == 0)
-          timestamp_set_type(TS_RELATIVE);
-        else if (strcmp(optarg, "a") == 0)
-          timestamp_set_type(TS_ABSOLUTE);
-        else if (strcmp(optarg, "ad") == 0)
-          timestamp_set_type(TS_ABSOLUTE_WITH_DATE);
-        else if (strcmp(optarg, "d") == 0)
-          timestamp_set_type(TS_DELTA);
-        else if (strcmp(optarg, "dd") == 0)
-          timestamp_set_type(TS_DELTA_DIS);
-        else if (strcmp(optarg, "e") == 0)
-          timestamp_set_type(TS_EPOCH);
-        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.");
-          return 1;
-        }
-        break;
-      case 'T':        /* printing Type */
-        if (strcmp(optarg, "text") == 0) {
-          output_action = WRITE_TEXT;
-          print_format = PR_FMT_TEXT;
-        } else if (strcmp(optarg, "ps") == 0) {
-          output_action = WRITE_TEXT;
-          print_format = PR_FMT_PS;
-        } else if (strcmp(optarg, "pdml") == 0) {
-          output_action = WRITE_XML;
-          verbose = TRUE;
-        } else if (strcmp(optarg, "psml") == 0) {
-          output_action = WRITE_XML;
-          verbose = FALSE;
-        } else if(strcmp(optarg, "fields") == 0) {
-          output_action = WRITE_FIELDS;
-          verbose = TRUE; /* Need full tree info */
-        } else {
-          cmdarg_err("Invalid -T parameter.");
-          cmdarg_err_cont("It must be \"ps\", \"text\", \"pdml\", \"psml\" or \"fields\".");
-          return 1;
-        }
-        break;
-      case 'u':        /* Seconds type */
-        if (strcmp(optarg, "s") == 0)
-          timestamp_set_seconds_type(TS_SECONDS_DEFAULT);
-        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.");
-          return 1;
-        }
+
+      case PREFS_SET_SYNTAX_ERR:
+        cmdarg_err("Invalid -o flag \"%s\"", optarg);
+        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);
-        return 0;
+
+      case PREFS_SET_NO_SUCH_PREF:
+      case PREFS_SET_OBSOLETE:
+        cmdarg_err("-o flag \"%s\" specifies unknown preference", optarg);
+        return 1;
         break;
       }
-      case 'V':        /* Verbose */
+      break;
+    case 'q':        /* Quiet */
+      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 'S':        /* Set the line Separator to be printed between packets */
+      separator = strdup(optarg);
+      break;
+    case 't':        /* Time stamp type */
+      if (strcmp(optarg, "r") == 0)
+        timestamp_set_type(TS_RELATIVE);
+      else if (strcmp(optarg, "a") == 0)
+        timestamp_set_type(TS_ABSOLUTE);
+      else if (strcmp(optarg, "ad") == 0)
+        timestamp_set_type(TS_ABSOLUTE_WITH_DATE);
+      else if (strcmp(optarg, "d") == 0)
+        timestamp_set_type(TS_DELTA);
+      else if (strcmp(optarg, "dd") == 0)
+        timestamp_set_type(TS_DELTA_DIS);
+      else if (strcmp(optarg, "e") == 0)
+        timestamp_set_type(TS_EPOCH);
+      else if (strcmp(optarg, "u") == 0)
+        timestamp_set_type(TS_UTC);
+      else if (strcmp(optarg, "ud") == 0)
+        timestamp_set_type(TS_UTC_WITH_DATE);
+      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.");
+        return 1;
+      }
+      break;
+    case 'T':        /* printing Type */
+      if (strcmp(optarg, "text") == 0) {
+        output_action = WRITE_TEXT;
+        print_format = PR_FMT_TEXT;
+      } else if (strcmp(optarg, "ps") == 0) {
+        output_action = WRITE_TEXT;
+        print_format = PR_FMT_PS;
+      } else if (strcmp(optarg, "pdml") == 0) {
+        output_action = WRITE_XML;
         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;
-        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':
-        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
-           by the preferences set callback) from being used as
-           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 :");
-          list_stat_cmd_args();
-          return 1;
-        }
-        break;
-      default:
-      case '?':        /* Bad flag - print usage message */
-        switch(optopt) {
-        case 'F':
-          list_capture_types();
-          break;
-        default:
-          print_usage(TRUE);
-        }
+      } else if (strcmp(optarg, "psml") == 0) {
+        output_action = WRITE_XML;
+        verbose = FALSE;
+      } else if(strcmp(optarg, "fields") == 0) {
+        output_action = WRITE_FIELDS;
+        verbose = TRUE; /* Need full tree info */
+      } else {
+        cmdarg_err("Invalid -T parameter.");
+        cmdarg_err_cont("It must be \"ps\", \"text\", \"pdml\", \"psml\" or \"fields\".");
+        return 1;
+      }
+      break;
+    case 'u':        /* Seconds type */
+      if (strcmp(optarg, "s") == 0)
+        timestamp_set_seconds_type(TS_SECONDS_DEFAULT);
+      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.");
+        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);
+      return 0;
+      break;
+    }
+    case 'O':        /* Only output these protocols */
+      output_only = g_strdup(optarg);
+      /* FALLTHROUGH */
+    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;
+      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':
+      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
+         by the preferences set callback) from being used as
+         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 :");
+        list_stat_cmd_args();
         return 1;
+      }
+      break;
+    default:
+    case '?':        /* Bad flag - print usage message */
+      switch(optopt) {
+      case 'F':
+        list_capture_types();
         break;
+      default:
+        print_usage(TRUE);
+      }
+      return 1;
+      break;
     }
   }
 
@@ -1332,19 +1410,30 @@ main(int argc, char *argv[])
     if (cf_name != NULL) {
       if (rfilter != NULL) {
         cmdarg_err("Read filters were specified both with \"-R\" "
-            "and with additional command-line arguments");
+            "and with additional command-line arguments.");
         return 1;
       }
       rfilter = get_args_as_string(argc, argv, optind);
     } else {
 #ifdef HAVE_LIBPCAP
-      if (global_capture_opts.has_cfilter) {
-        cmdarg_err("Capture filters were specified both with \"-f\""
-            " and with additional command-line arguments");
+      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;
       }
-      global_capture_opts.has_cfilter = TRUE;
-      global_capture_opts.cfilter = get_args_as_string(argc, argv, optind);
+      for (i = 0; i < global_capture_opts.ifaces->len; i++) {
+        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);
+          global_capture_opts.ifaces = g_array_remove_index(global_capture_opts.ifaces, i);
+          g_array_insert_val(global_capture_opts.ifaces, i, interface_opts);
+        } else {
+          cmdarg_err("A capture filter was specified both with \"-f\""
+              " and with additional command-line arguments.");
+          return 1;
+        }
+      }
+      global_capture_opts.default_options.cfilter = get_args_as_string(argc, argv, optind);
 #else
       capture_option_specified = TRUE;
 #endif
@@ -1390,7 +1479,7 @@ main(int argc, char *argv[])
      support in capture files we read). */
 #ifdef HAVE_LIBPCAP
   if (cf_name != NULL) {
-    if (global_capture_opts.has_cfilter) {
+    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;
@@ -1405,6 +1494,20 @@ main(int argc, char *argv[])
     }
   }
 
+  if (output_only != NULL) {
+    char *ps;
+
+    if (!verbose) {
+      cmdarg_err("-O requires -V");
+      return 1;
+    }
+
+    output_only_tables = g_hash_table_new (g_str_hash, g_str_equal);
+    for (ps = strtok (output_only, ","); ps; ps = strtok (NULL, ",")) {
+      g_hash_table_insert(output_only_tables, (gpointer)ps, (gpointer)ps);
+    }
+  }
+
 #ifdef HAVE_LIBPCAP
   if (list_link_layer_types) {
     /* We're supposed to list the link-layer types for an interface;
@@ -1462,8 +1565,8 @@ main(int argc, char *argv[])
       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 libpcap format. */
-        if (out_file_type != WTAP_FILE_PCAP) {
+        /* When capturing, we only support writing pcap or pcap-ng format. */
+        if (out_file_type != WTAP_FILE_PCAP && out_file_type != WTAP_FILE_PCAPNG) {
           cmdarg_err("Live captures can only be saved in libpcap format.");
           return 1;
         }
@@ -1534,7 +1637,7 @@ main(int argc, char *argv[])
      if we're writing to a pipe. */
   if (global_capture_opts.saving_to_file &&
       global_capture_opts.output_to_pipe) {
-    if (have_tap_listeners()) {
+    if (tap_listeners_require_dissection()) {
       cmdarg_err("Taps aren't supported when saving to a pipe.");
       return 1;
     }
@@ -1609,8 +1712,8 @@ main(int argc, char *argv[])
 
         we're using a read filter on the packets;
 
-        we're using any taps. */
-  do_dissection = print_packet_info || rfcode || have_tap_listeners();
+        we're using any taps that need dissection. */
+  do_dissection = print_packet_info || rfcode || tap_listeners_require_dissection();
 
   if (cf_name) {
     /*
@@ -1656,13 +1759,26 @@ main(int argc, char *argv[])
     }
 
     /* Process the packets in the file */
+    TRY {
 #ifdef HAVE_LIBPCAP
-    err = load_cap_file(&cfile, global_capture_opts.save_file, out_file_type,
-        global_capture_opts.has_autostop_packets ? global_capture_opts.autostop_packets : 0,
-        global_capture_opts.has_autostop_filesize ? global_capture_opts.autostop_filesize : 0);
+      err = load_cap_file(&cfile, global_capture_opts.save_file, out_file_type, out_file_name_res,
+          global_capture_opts.has_autostop_packets ? global_capture_opts.autostop_packets : 0,
+          global_capture_opts.has_autostop_filesize ? global_capture_opts.autostop_filesize : 0);
 #else
-    err = load_cap_file(&cfile, NULL, out_file_type, 0, 0);
+      err = load_cap_file(&cfile, NULL, out_file_type, out_file_name_res, 0, 0);
 #endif
+    }
+    CATCH(OutOfMemoryError) {
+      fprintf(stderr,
+              "Out Of Memory!\n"
+              "\n"
+              "Sorry, but TShark has to terminate now!\n"
+              "\n"
+              "Some infos / workarounds can be found at:\n"
+              "http://wiki.wireshark.org/KnownBugs/OutOfMemory\n");
+      err = ENOMEM;
+    }
+    ENDTRY;
     if (err != 0) {
       /* We still dump out the results of taps, etc., as we might have
          read some packets; however, we exit with an error status. */
@@ -1673,19 +1789,6 @@ main(int argc, char *argv[])
        (or get a list of link-layer types for a live capture device);
        do we have support for live captures? */
 #ifdef HAVE_LIBPCAP
-
-#ifdef _WIN32
-    if (!has_wpcap) {
-      char *detailed_err;
-
-      cmdarg_err("WinPcap couldn't be found.");
-      detailed_err = cant_load_winpcap_err("TShark");
-      cmdarg_err_cont("%s", detailed_err);
-      g_free(detailed_err);
-      return 2;
-    }
-#endif
-
     /* trim the interface name and exit if that failed */
     if (!capture_opts_trim_iface(&global_capture_opts,
         (prefs_p->capture_device) ? get_if_name(prefs_p->capture_device) : NULL)) {
@@ -1694,24 +1797,27 @@ main(int argc, char *argv[])
 
     /* if requested, list the link layer types and exit */
     if (list_link_layer_types) {
-        /* Get the list of link-layer types for the capture device. */
-        if_capabilities_t *caps;
-
-        caps = capture_get_if_capabilities(global_capture_opts.iface,
-                                           global_capture_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.", global_capture_opts.iface);
-            return 2;
+        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);
         }
-        capture_opts_print_if_capabilities(caps,
-                                           global_capture_opts.monitor_mode);
-        free_if_capabilities(caps);
         return 0;
     }
 
@@ -1765,10 +1871,10 @@ main(int argc, char *argv[])
 
   g_free(cf_name);
 
-#if GLIB_CHECK_VERSION(2,10,0)
-  if (cfile.plist_start != NULL)
-    g_slice_free_chain(frame_data, cfile.plist_start, next);
-#endif
+  if (cfile.frames != NULL) {
+    free_frame_data_sequence(cfile.frames);
+    cfile.frames = NULL;
+  }
 
   draw_tap_listeners(TRUE);
   funnel_dump_all_text_windows();
@@ -1795,13 +1901,13 @@ main(int argc, char *argv[])
 typedef gboolean (*pipe_input_cb_t) (gint source, gpointer user_data);
 
 typedef struct pipe_input_tag {
-    gint                source;
-    gpointer            user_data;
-    int                 *child_process;
-    pipe_input_cb_t     input_cb;
-    guint               pipe_input_id;
+  gint                source;
+  gpointer            user_data;
+  int                 *child_process;
+  pipe_input_cb_t     input_cb;
+  guint               pipe_input_id;
 #ifdef _WIN32
-    GStaticMutex        callback_running;
+  GMutex              *callback_running;
 #endif
 } pipe_input_t;
 
@@ -1817,11 +1923,10 @@ pipe_timer_cb(gpointer data)
   DWORD avail = 0;
   gboolean result, result1;
   DWORD childstatus;
-  pipe_input_t *pipe_input = data;
+  pipe_input_t *pipe_input_p = data;
   gint iterations = 0;
 
-
-  g_static_mutex_lock (&pipe_input->callback_running);
+  g_mutex_lock (pipe_input_p->callback_running);
 
   /* try to read data from the pipe only 5 times, to avoid blocking */
   while(iterations < 5) {
@@ -1829,11 +1934,11 @@ pipe_timer_cb(gpointer data)
 
     /* Oddly enough although Named pipes don't work on win9x,
        PeekNamedPipe does !!! */
-    handle = (HANDLE) _get_osfhandle (pipe_input->source);
+    handle = (HANDLE) _get_osfhandle (pipe_input_p->source);
     result = PeekNamedPipe(handle, NULL, 0, NULL, &avail, NULL);
 
     /* Get the child process exit status */
-    result1 = GetExitCodeProcess((HANDLE)*(pipe_input->child_process),
+    result1 = GetExitCodeProcess((HANDLE)*(pipe_input_p->child_process),
                                  &childstatus);
 
     /* If the Peek returned an error, or there are bytes to be read
@@ -1844,10 +1949,10 @@ pipe_timer_cb(gpointer data)
       /*g_log(NULL, G_LOG_LEVEL_DEBUG, "pipe_timer_cb: data avail");*/
 
       /* And call the real handler */
-      if (!pipe_input->input_cb(pipe_input->source, pipe_input->user_data)) {
+      if (!pipe_input_p->input_cb(pipe_input_p->source, pipe_input_p->user_data)) {
         g_log(NULL, G_LOG_LEVEL_DEBUG, "pipe_timer_cb: input pipe closed, iterations: %u", iterations);
         /* pipe closed, return false so that the timer is stopped */
-        g_static_mutex_unlock (&pipe_input->callback_running);
+        g_mutex_unlock (pipe_input_p->callback_running);
         return FALSE;
       }
     }
@@ -1862,7 +1967,7 @@ pipe_timer_cb(gpointer data)
 
   /*g_log(NULL, G_LOG_LEVEL_DEBUG, "pipe_timer_cb: finished with iterations: %u, new timer", iterations);*/
 
-  g_static_mutex_unlock (&pipe_input->callback_running);
+  g_mutex_unlock (pipe_input_p->callback_running);
 
   /* we didn't stopped the timer, so let it run */
   return TRUE;
@@ -1880,7 +1985,12 @@ pipe_input_set_handler(gint source, gpointer user_data, int *child_process, pipe
   pipe_input.input_cb       = input_cb;
 
 #ifdef _WIN32
-  g_static_mutex_init(&pipe_input.callback_running);
+#if GLIB_CHECK_VERSION(2,31,0)
+  pipe_input.callback_running = g_malloc(sizeof(GMutex));
+  g_mutex_init(pipe_input.callback_running);
+#else
+  pipe_input.callback_running = g_mutex_new();
+#endif
   /* Tricky to use pipes in win9x, as no concept of wait.  NT can
      do this but that doesn't cover all win32 platforms.  GTK can do
      this but doesn't seem to work over processes.  Attempt to do
@@ -1897,6 +2007,8 @@ static gboolean
 capture(void)
 {
   gboolean ret;
+  guint i;
+  GString *str = g_string_new("");
 #ifdef USE_TSHARK_SELECT
   fd_set readfds;
 #endif
@@ -1970,9 +2082,40 @@ capture(void)
 
   global_capture_opts.state = CAPTURE_PREPARING;
 
-  /* Let the user know what interface was chosen. */
-  global_capture_opts.iface_descr = get_interface_descriptive_name(global_capture_opts.iface);
-  fprintf(stderr, "Capturing on %s\n", global_capture_opts.iface_descr);
+  /* Let the user know which interfaces were chosen. */
+  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);
+    interface_opts.descr = get_interface_descriptive_name(interface_opts.name);
+    global_capture_opts.ifaces = g_array_remove_index(global_capture_opts.ifaces, i);
+    g_array_insert_val(global_capture_opts.ifaces, i, interface_opts);
+  }
+#ifdef _WIN32
+  if (global_capture_opts.ifaces->len < 2) {
+#else
+  if (global_capture_opts.ifaces->len < 4) {
+#endif
+    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 (i > 0) {
+          if (global_capture_opts.ifaces->len > 2) {
+              g_string_append_printf(str, ",");
+          }
+          g_string_append_printf(str, " ");
+          if (i == global_capture_opts.ifaces->len - 1) {
+              g_string_append_printf(str, "and ");
+          }
+      }
+      g_string_append_printf(str, "%s", interface_opts.descr);
+    }
+  } else {
+    g_string_append_printf(str, "%u interfaces", global_capture_opts.ifaces->len);
+  }
+  fprintf(stdout, "Capturing on %s\n", str->str);
+  g_string_free(str, TRUE);
 
   ret = sync_pipe_start(&global_capture_opts);
 
@@ -2004,27 +2147,40 @@ capture(void)
 
   loop_running = TRUE;
 
-  while (loop_running)
+  TRY
   {
+    while (loop_running)
+    {
 #ifdef USE_TSHARK_SELECT
-    ret = select(pipe_input.source+1, &readfds, NULL, NULL, NULL);
+      ret = select(pipe_input.source+1, &readfds, NULL, NULL, NULL);
 
-    if (ret == -1)
-    {
-      perror("select()");
-      return TRUE;
-    } else if (ret == 1) {
+      if (ret == -1)
+      {
+        perror("select()");
+        return TRUE;
+      } else if (ret == 1) {
 #endif
-      /* Call the real handler */
-      if (!pipe_input.input_cb(pipe_input.source, pipe_input.user_data)) {
-        g_log(NULL, G_LOG_LEVEL_DEBUG, "input pipe closed");
-        return FALSE;
-      }
+        /* Call the real handler */
+        if (!pipe_input.input_cb(pipe_input.source, pipe_input.user_data)) {
+          g_log(NULL, G_LOG_LEVEL_DEBUG, "input pipe closed");
+          return FALSE;
+        }
 #ifdef USE_TSHARK_SELECT
-    }
+      }
 #endif
+    }
   }
-
+  CATCH(OutOfMemoryError) {
+    fprintf(stderr,
+            "Out Of Memory!\n"
+            "\n"
+            "Sorry, but TShark has to terminate now!\n"
+            "\n"
+            "Some infos / workarounds can be found at:\n"
+            "http://wiki.wireshark.org/KnownBugs/OutOfMemory\n");
+    exit(1);
+  }
+  ENDTRY;
   return TRUE;
 }
 
@@ -2046,14 +2202,17 @@ 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, char *error_message)
+capture_input_cfilter_error_message(capture_options *capture_opts, guint i, char *error_message)
 {
   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(capture_opts->cfilter, &rfcode) && rfcode != NULL) {
+  if (dfilter_compile(interface_opts.cfilter, &rfcode) && rfcode != NULL) {
     cmdarg_err(
-      "Invalid capture filter: \"%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"
@@ -2062,15 +2221,15 @@ capture_input_cfilter_error_message(capture_options *capture_opts, char *error_m
       "so you can't use most display filter expressions as capture filters.\n"
       "\n"
       "See the User's Guide for a description of the capture filter syntax.",
-      capture_opts->cfilter, error_message);
+      interface_opts.cfilter, interface_opts.descr, error_message);
     dfilter_free(rfcode);
   } else {
     cmdarg_err(
-      "Invalid capture filter: \"%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.",
-      capture_opts->cfilter, error_message);
+      interface_opts.cfilter, interface_opts.descr, error_message);
   }
 }
 
@@ -2173,7 +2332,7 @@ capture_input_new_packets(capture_options *capture_opts, int to_read)
                              filtering_tap_listeners, tap_flags);
       }
       if (ret != FALSE) {
-        /* packet sucessfully read and gone through the "Read Filter" */
+        /* packet successfully read and gone through the "Read Filter" */
         packet_count++;
       }
     }
@@ -2214,7 +2373,7 @@ report_counts(void)
   if (!print_packet_counts) {
     /* 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(stdout, "%u packet%s captured\n", packet_count,
             plurality(packet_count, "", "s"));
   }
 #ifdef SIGINFO
@@ -2271,9 +2430,9 @@ capture_input_closed(capture_options *capture_opts, gchar *msg)
 
   if(capture_opts->cf != NULL && ((capture_file *) capture_opts->cf)->wth != NULL) {
     wtap_close(((capture_file *) capture_opts->cf)->wth);
-       if(((capture_file *) capture_opts->cf)->user_saved == FALSE){
-               ws_unlink(((capture_file *) capture_opts->cf)->filename);
-       }
+    if(((capture_file *) capture_opts->cf)->user_saved == FALSE) {
+      ws_unlink(((capture_file *) capture_opts->cf)->filename);
+    }
   }
 #ifdef USE_BROKEN_G_MAIN_LOOP
   /*g_main_loop_quit(loop);*/
@@ -2334,25 +2493,26 @@ capture_cleanup(int signum _U_)
 #endif /* _WIN32 */
 #endif /* HAVE_LIBPCAP */
 
-#if GLIB_CHECK_VERSION(2,10,0)
 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)
 {
-  frame_data *fdata = g_slice_new(frame_data);
+  frame_data fdlocal;
+  guint32 framenum;
   epan_dissect_t edt;
   gboolean passed;
 
-  /* Count this packet. */
-  cf->count++;
+  /* The frame number of this packet is one more than the count of
+     frames in this packet. */
+  framenum = cf->count + 1;
 
   /* 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
      that all packets can be marked as 'passed'. */
   passed = TRUE;
 
-  frame_data_init(fdata, cf->count, whdr, offset, cum_bytes);
+  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
@@ -2373,10 +2533,10 @@ process_packet_first_pass(capture_file *cf,
     if (cf->rfcode)
       epan_dissect_prime_dfilter(&edt, cf->rfcode);
 
-    frame_data_set_before_dissect(fdata, &cf->elapsed_time,
+    frame_data_set_before_dissect(&fdlocal, &cf->elapsed_time,
                                   &first_ts, &prev_dis_ts, &prev_cap_ts);
 
-    epan_dissect_run(&edt, pseudo_header, pd, fdata, NULL);
+    epan_dissect_run(&edt, pseudo_header, pd, &fdlocal, NULL);
 
     /* Run the read filter if we have one. */
     if (cf->rfcode)
@@ -2384,11 +2544,10 @@ process_packet_first_pass(capture_file *cf,
   }
 
   if (passed) {
-    frame_data_set_after_dissect(fdata, &cum_bytes, &prev_dis_ts);
-    cap_file_add_fdata(cf, fdata);
+    frame_data_set_after_dissect(&fdlocal, &cum_bytes, &prev_dis_ts);
+    frame_data_sequence_add(cf->frames, &fdlocal);
+    cf->count++;
   }
-  else
-    g_slice_free(frame_data, fdata);
 
   if (do_dissection)
     epan_dissect_cleanup(&edt);
@@ -2507,23 +2666,27 @@ process_packet_second_pass(capture_file *cf, frame_data *fdata,
   }
   return passed;
 }
-#endif
 
 static int
 load_cap_file(capture_file *cf, char *save_file, int out_file_type,
-    int max_packet_count, gint64 max_byte_count)
+    gboolean out_file_name_res, int max_packet_count, gint64 max_byte_count)
 {
   gint         linktype;
   int          snapshot_length;
   wtap_dumper *pdh;
+  guint32      framenum;
   int          err;
-  gchar        *err_info;
+  gchar        *err_info = NULL;
   gint64       data_offset;
   char         *save_file_string = NULL;
   gboolean     filtering_tap_listeners;
   guint        tap_flags;
 
+#ifdef PCAP_NG_DEFAULT
+  linktype = WTAP_ENCAP_PER_PACKET;
+#else
   linktype = wtap_file_encap(cf->wth);
+#endif
   if (save_file != NULL) {
     /* Get a string that describes what we're writing to */
     save_file_string = output_file_description(save_file);
@@ -2547,8 +2710,8 @@ 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 in "
-          "that format.");
+        cmdarg_err("The capture file being read can't be written as a "
+          "\"%s\" file.", wtap_file_type_short_string(out_file_type));
         break;
 
       case WTAP_ERR_CANT_OPEN:
@@ -2579,6 +2742,13 @@ load_cap_file(capture_file *cf, char *save_file, int out_file_type,
     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));
+    }
+  }
+
   /* Do we have any tap listeners with filters? */
   filtering_tap_listeners = have_filtering_tap_listeners();
 
@@ -2586,10 +2756,12 @@ load_cap_file(capture_file *cf, char *save_file, int out_file_type,
   tap_flags = union_of_tap_listener_flags();
 
   if (perform_two_pass_analysis) {
-#if GLIB_CHECK_VERSION(2,10,0)
     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();
+
     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))) {
@@ -2614,7 +2786,8 @@ load_cap_file(capture_file *cf, char *save_file, int out_file_type,
 
     max_packet_count = old_max_packet_count;
 
-    for (fdata = cf->plist_start; err == 0 && fdata != NULL; fdata = fdata->next) {
+    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,
@@ -2628,7 +2801,26 @@ load_cap_file(capture_file *cf, char *save_file, int out_file_type,
                            wtap_pseudoheader(cf->wth), wtap_buf_ptr(cf->wth),
                            &err)) {
               /* Error writing to a capture file */
-              show_capture_file_io_error(save_file, err, FALSE);
+              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.
+                 *
+                 * XXX - framenum is not necessarily the frame number in
+                 * the input file if there was a read filter.
+                 */
+                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));
+                break;
+
+              default:
+                show_capture_file_io_error(save_file, err, FALSE);
+                break;
+              }
               wtap_dump_close(pdh, &err);
               exit(2);
             }
@@ -2645,10 +2837,12 @@ load_cap_file(capture_file *cf, char *save_file, int out_file_type,
         }
       }
     }
-#endif
   }
   else {
+    framenum = 0;
     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)) {
@@ -2660,7 +2854,23 @@ load_cap_file(capture_file *cf, char *save_file, int out_file_type,
                          wtap_pseudoheader(cf->wth), wtap_buf_ptr(cf->wth),
                          &err)) {
             /* Error writing to a capture file */
-            show_capture_file_io_error(save_file, err, FALSE);
+            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.
+               */
+              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));
+              break;
+
+            default:
+              show_capture_file_io_error(save_file, err, FALSE);
+              break;
+            }
             wtap_dump_close(pdh, &err);
             exit(2);
           }
@@ -2706,29 +2916,34 @@ load_cap_file(capture_file *cf, char *save_file, int out_file_type,
     switch (err) {
 
     case WTAP_ERR_UNSUPPORTED_ENCAP:
-      cmdarg_err("\"%s\" has a packet with a network type that TShark doesn't support.\n(%s)",
+      cmdarg_err("The file \"%s\" has a packet with a network type that TShark doesn't support.\n(%s)",
                  cf->filename, err_info);
       g_free(err_info);
       break;
 
     case WTAP_ERR_CANT_READ:
-      cmdarg_err("An attempt to read from \"%s\" failed for some unknown reason.",
+      cmdarg_err("An attempt to read from the file \"%s\" failed for some unknown reason.",
                  cf->filename);
       break;
 
     case WTAP_ERR_SHORT_READ:
-      cmdarg_err("\"%s\" appears to have been cut short in the middle of a packet.",
+      cmdarg_err("The file \"%s\" appears to have been cut short in the middle of a packet.",
                  cf->filename);
       break;
 
-    case WTAP_ERR_BAD_RECORD:
-      cmdarg_err("\"%s\" appears to be damaged or corrupt.\n(%s)",
+    case WTAP_ERR_BAD_FILE:
+      cmdarg_err("The file \"%s\" appears to be damaged or corrupt.\n(%s)",
                  cf->filename, err_info);
       g_free(err_info);
       break;
 
+    case WTAP_ERR_DECOMPRESS:
+      cmdarg_err("The compressed file \"%s\" appears to be damaged or corrupt.\n"
+                 "(%s)", cf->filename, err_info);
+      break;
+
     default:
-      cmdarg_err("An error occurred while reading \"%s\": %s.",
+      cmdarg_err("An error occurred while reading the file \"%s\": %s.",
                  cf->filename, wtap_strerror(err));
       break;
     }
@@ -2895,7 +3110,7 @@ write_preamble(capture_file *cf)
 
   case WRITE_XML:
     if (verbose)
-      write_pdml_preamble(stdout);
+      write_pdml_preamble(stdout, cf ? cf->filename : NULL);
     else
       write_psml_preamble(stdout);
     return !ferror(stdout);
@@ -2944,6 +3159,9 @@ print_columns(capture_file *cf)
   buf_offset = 0;
   *line_bufp = '\0';
   for (i = 0; i < cf->cinfo.num_cols; i++) {
+    /* Skip columns not marked as visible. */
+    if (!get_column_visible(i))
+      continue;
     switch (cf->cinfo.col_fmt[i]) {
     case COL_NUMBER:
 #ifdef HAVE_LIBPCAP
@@ -2958,25 +3176,27 @@ print_columns(capture_file *cf)
        * the same time, sort of like an "Update list of packets
        * in real time" capture in Wireshark.)
        */
-      if (global_capture_opts.iface != NULL)
+      if (global_capture_opts.ifaces->len > 0)
         continue;
 #endif
       column_len = strlen(cf->cinfo.col_data[i]);
       if (column_len < 3)
         column_len = 3;
       line_bufp = get_line_buf(buf_offset + column_len);
-      sprintf(line_bufp + buf_offset, "%3s", cf->cinfo.col_data[i]);
+      g_snprintf(line_bufp + buf_offset, (int)column_len + 1, "%3s", cf->cinfo.col_data[i]);
       break;
 
     case COL_CLS_TIME:
     case COL_REL_TIME:
     case COL_ABS_TIME:
-    case COL_ABS_DATE_TIME: /* XXX - wider */
+    case COL_ABS_DATE_TIME:
+    case COL_UTC_TIME:
+    case COL_UTC_DATE_TIME: /* XXX - wider */
       column_len = strlen(cf->cinfo.col_data[i]);
       if (column_len < 10)
         column_len = 10;
       line_bufp = get_line_buf(buf_offset + column_len);
-      sprintf(line_bufp + buf_offset, "%10s", cf->cinfo.col_data[i]);
+      g_snprintf(line_bufp + buf_offset, (int)column_len + 1, "%10s", cf->cinfo.col_data[i]);
       break;
 
     case COL_DEF_SRC:
@@ -2992,7 +3212,7 @@ print_columns(capture_file *cf)
       if (column_len < 12)
         column_len = 12;
       line_bufp = get_line_buf(buf_offset + column_len);
-      sprintf(line_bufp + buf_offset, "%12s", cf->cinfo.col_data[i]);
+      g_snprintf(line_bufp + buf_offset, (int)column_len + 1, "%12s", cf->cinfo.col_data[i]);
       break;
 
     case COL_DEF_DST:
@@ -3008,13 +3228,13 @@ print_columns(capture_file *cf)
       if (column_len < 12)
         column_len = 12;
       line_bufp = get_line_buf(buf_offset + column_len);
-      sprintf(line_bufp + buf_offset, "%-12s", cf->cinfo.col_data[i]);
+      g_snprintf(line_bufp + buf_offset, (int)column_len + 1, "%-12s", cf->cinfo.col_data[i]);
       break;
 
     default:
       column_len = strlen(cf->cinfo.col_data[i]);
       line_bufp = get_line_buf(buf_offset + column_len);
-      strcat(line_bufp + buf_offset, cf->cinfo.col_data[i]);
+      g_strlcat(line_bufp + buf_offset, cf->cinfo.col_data[i], column_len + 1);
       break;
     }
     buf_offset += column_len;
@@ -3025,9 +3245,9 @@ print_columns(capture_file *cf)
        *
        * If we printed a network source and are printing a
        * network destination of the same type next, separate
-       * them with "->"; if we printed a network destination
+       * them with " -> "; if we printed a network destination
        * and are printing a network source of the same type
-       * next, separate them with "<-"; otherwise separate them
+       * next, separate them with " <- "; otherwise separate them
        * with a space.
        *
        * We add enough space to the buffer for " <- " or " -> ",
@@ -3044,12 +3264,12 @@ print_columns(capture_file *cf)
         case COL_DEF_DST:
         case COL_RES_DST:
         case COL_UNRES_DST:
-          strcat(line_bufp + buf_offset, " -> ");
+          g_strlcat(line_bufp + buf_offset, " -> ", 5);
           buf_offset += 4;
           break;
 
         default:
-          strcat(line_bufp + buf_offset, " ");
+          g_strlcat(line_bufp + buf_offset, " ", 5);
           buf_offset += 1;
           break;
         }
@@ -3063,12 +3283,12 @@ print_columns(capture_file *cf)
         case COL_DEF_DL_DST:
         case COL_RES_DL_DST:
         case COL_UNRES_DL_DST:
-          strcat(line_bufp + buf_offset, " -> ");
+          g_strlcat(line_bufp + buf_offset, " -> ", 5);
           buf_offset += 4;
           break;
 
         default:
-          strcat(line_bufp + buf_offset, " ");
+          g_strlcat(line_bufp + buf_offset, " ", 5);
           buf_offset += 1;
           break;
         }
@@ -3082,12 +3302,12 @@ print_columns(capture_file *cf)
         case COL_DEF_NET_DST:
         case COL_RES_NET_DST:
         case COL_UNRES_NET_DST:
-          strcat(line_bufp + buf_offset, " -> ");
+          g_strlcat(line_bufp + buf_offset, " -> ", 5);
           buf_offset += 4;
           break;
 
         default:
-          strcat(line_bufp + buf_offset, " ");
+          g_strlcat(line_bufp + buf_offset, " ", 5);
           buf_offset += 1;
           break;
         }
@@ -3101,12 +3321,12 @@ print_columns(capture_file *cf)
         case COL_DEF_SRC:
         case COL_RES_SRC:
         case COL_UNRES_SRC:
-          strcat(line_bufp + buf_offset, " <- ");
+          g_strlcat(line_bufp + buf_offset, " <- ", 5);
           buf_offset += 4;
           break;
 
         default:
-          strcat(line_bufp + buf_offset, " ");
+          g_strlcat(line_bufp + buf_offset, " ", 5);
           buf_offset += 1;
           break;
         }
@@ -3120,12 +3340,12 @@ print_columns(capture_file *cf)
         case COL_DEF_DL_SRC:
         case COL_RES_DL_SRC:
         case COL_UNRES_DL_SRC:
-          strcat(line_bufp + buf_offset, " <- ");
+          g_strlcat(line_bufp + buf_offset, " <- ", 5);
           buf_offset += 4;
           break;
 
         default:
-          strcat(line_bufp + buf_offset, " ");
+          g_strlcat(line_bufp + buf_offset, " ", 5);
           buf_offset += 1;
           break;
         }
@@ -3139,19 +3359,19 @@ print_columns(capture_file *cf)
         case COL_DEF_NET_SRC:
         case COL_RES_NET_SRC:
         case COL_UNRES_NET_SRC:
-          strcat(line_bufp + buf_offset, " <- ");
+          g_strlcat(line_bufp + buf_offset, " <- ", 5);
           buf_offset += 4;
           break;
 
         default:
-          strcat(line_bufp + buf_offset, " ");
+          g_strlcat(line_bufp + buf_offset, " ", 5);
           buf_offset += 1;
           break;
         }
         break;
 
       default:
-        strcat(line_bufp + buf_offset, " ");
+        g_strlcat(line_bufp + buf_offset, " ", 5);
         buf_offset += 1;
         break;
       }
@@ -3186,7 +3406,7 @@ print_packet(capture_file *cf, epan_dissect_t *edt)
         /* "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, ""))
+        if (!print_line(print_stream, 0, separator))
           return FALSE;
       }
       break;
@@ -3304,6 +3524,9 @@ cf_open(capture_file *cf, const char *fname, gboolean is_tempfile, int *err)
 
   cf->state = FILE_READ_IN_PROGRESS;
 
+  wtap_set_cb_new_ipv4(cf->wth, add_ipv4_name);
+  wtap_set_cb_new_ipv6(cf->wth, (wtap_new_ipv6_callback_t) add_ipv6_name);
+
   return CF_OK;
 
 fail:
@@ -3378,7 +3601,7 @@ show_print_file_io_error(int err)
 
   default:
     cmdarg_err("An error occurred while printing packets: %s.",
-      strerror(err));
+      g_strerror(err));
     break;
   }
 }
@@ -3415,8 +3638,8 @@ cf_open_error_message(int err, gchar *err_info, gboolean for_writing,
     case WTAP_ERR_CANT_WRITE_TO_PIPE:
       /* 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_string(file_type));
+                 "The file \"%%s\" is a pipe, and \"%s\" capture files can't be "
+                 "written to a pipe.", wtap_file_type_short_string(file_type));
       errmsg = errmsg_errno;
       break;
 
@@ -3426,25 +3649,30 @@ cf_open_error_message(int err, gchar *err_info, gboolean for_writing,
       break;
 
     case WTAP_ERR_UNSUPPORTED_ENCAP:
-      if (for_writing)
-        errmsg = "TShark can't save this capture in that format.";
-      else {
+      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));
+      } else {
         g_snprintf(errmsg_errno, sizeof(errmsg_errno),
                  "The file \"%%s\" is a capture for a network type that TShark doesn't support.\n"
                  "(%s)", err_info);
         g_free(err_info);
-        errmsg = errmsg_errno;
       }
+      errmsg = errmsg_errno;
       break;
 
     case WTAP_ERR_ENCAP_PER_PACKET_UNSUPPORTED:
-      if (for_writing)
-        errmsg = "TShark can't save this capture in that format.";
-      else
+      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));
+        errmsg = errmsg_errno;
+      } else
         errmsg = "The file \"%s\" is a capture for a network type that TShark doesn't support.";
       break;
 
-    case WTAP_ERR_BAD_RECORD:
+    case WTAP_ERR_BAD_FILE:
       /* Seen only when opening a capture file for reading. */
       g_snprintf(errmsg_errno, sizeof(errmsg_errno),
                "The file \"%%s\" appears to be damaged or corrupt.\n"
@@ -3469,6 +3697,15 @@ cf_open_error_message(int err, gchar *err_info, gboolean for_writing,
       errmsg = "A full header couldn't be written to the file \"%s\".";
       break;
 
+    case WTAP_ERR_DECOMPRESS:
+      /* Seen only when opening a capture file for reading. */
+      g_snprintf(errmsg_errno, sizeof(errmsg_errno),
+                 "The compressed file \"%%s\" appears to be damaged or corrupt.\n"
+                 "(%s)", err_info);
+      g_free(err_info);
+      errmsg = errmsg_errno;
+      break;
+
     default:
       g_snprintf(errmsg_errno, sizeof(errmsg_errno),
                  "The file \"%%s\" could not be %s: %s.",
@@ -3512,7 +3749,7 @@ static void
 read_failure_message(const char *filename, int err)
 {
   cmdarg_err("An error occurred while reading from the file \"%s\": %s.",
-          filename, strerror(err));
+          filename, g_strerror(err));
 }
 
 /*
@@ -3522,7 +3759,7 @@ static void
 write_failure_message(const char *filename, int err)
 {
   cmdarg_err("An error occurred while writing to the file \"%s\": %s.",
-          filename, strerror(err));
+          filename, g_strerror(err));
 }
 
 /*