Support reading in and storing multiple Section Header and Name Resolution blocks.
[metze/wireshark/wip.git] / wiretap / file_access.c
index ff23cb2eb3b7a902661fb84c712e5da17a27da54..ff2200bd2d1bac180f0fd754b592d063fbdb1731 100644 (file)
 #include <string.h>
 #include <stdlib.h>
 
-#ifdef HAVE_FCNTL_H
-#include <fcntl.h>
-#endif
-
-#ifdef HAVE_UNISTD_H
-#include <unistd.h>
-#endif
-
 #include <errno.h>
 
 #include <wsutil/file_util.h>
+#include <wsutil/tempfile.h>
 
 #include "wtap-int.h"
 #include "file_wrappers.h"
@@ -90,6 +83,7 @@
 #include "capsa.h"
 #include "pcap-encap.h"
 #include "nettrace_3gpp_32_423.h"
+#include "mplog.h"
 
 /*
  * Add an extension, and all compressed versions thereof, to a GSList
@@ -97,9 +91,9 @@
  */
 static GSList *
 add_extensions(GSList *extensions, const gchar *extension,
-    GSList *compressed_file_extensions)
+    const char **compressed_file_extensions)
 {
-       GSList *compressed_file_extension;
+       const char **compressed_file_extensionp;
 
        /*
         * Add the specified extension.
@@ -110,12 +104,12 @@ add_extensions(GSList *extensions, const gchar *extension,
         * Now add the extensions for compressed-file versions of
         * that extension.
         */
-       for (compressed_file_extension = compressed_file_extensions;
-           compressed_file_extension != NULL;
-           compressed_file_extension = g_slist_next(compressed_file_extension)) {
+       for (compressed_file_extensionp = compressed_file_extensions;
+           *compressed_file_extensionp != NULL;
+           compressed_file_extensionp++) {
                extensions = g_slist_append(extensions,
                    g_strdup_printf("%s.%s", extension,
-                     (gchar *)compressed_file_extension->data));
+                     *compressed_file_extensionp));
        }
 
        return extensions;
@@ -145,6 +139,7 @@ static const struct file_extension_info file_type_extensions_base[] = {
        { "Tektronix K12xx 32-bit .rf5 format", "rf5" },
        { "Savvius *Peek", "pkt;tpc;apc;wpz" },
        { "Catapult DCT2000 trace (.out format)", "out" },
+       { "Micropross mplog", "mplog" },
        { "MPEG files", "mpg;mp3" },
        { "TamoSoft CommView", "ncf" },
        { "Symbian OS btsnoop", "log" },
@@ -205,7 +200,7 @@ wtap_get_file_extension_type_name(int extension_type)
 
 static GSList *
 add_extensions_for_file_extensions_type(int extension_type,
-    GSList *extensions, GSList *compressed_file_extensions)
+    GSList *extensions, const char **compressed_file_extensions)
 {
        gchar **extensions_set, **extensionp, *extension;
 
@@ -241,7 +236,6 @@ add_extensions_for_file_extensions_type(int extension_type,
 GSList *
 wtap_get_file_extension_type_extensions(guint extension_type)
 {
-       GSList *compressed_file_extensions;
        GSList *extensions;
 
        if (extension_type >= file_type_extensions_arr->len)
@@ -249,19 +243,13 @@ wtap_get_file_extension_type_extensions(guint extension_type)
 
        extensions = NULL;      /* empty list, to start with */
 
-       /*
-        * Get the list of compressed-file extensions.
-        */
-       compressed_file_extensions = wtap_get_compressed_file_extensions();
-
        /*
         * Add all this file extension type's extensions, with compressed
         * variants.
         */
        extensions = add_extensions_for_file_extensions_type(extension_type,
-           extensions, compressed_file_extensions);
+           extensions, compressed_file_extension_table);
 
-       g_slist_free(compressed_file_extensions);
        return extensions;
 }
 
@@ -274,7 +262,6 @@ wtap_get_file_extension_type_extensions(guint extension_type)
 GSList *
 wtap_get_all_file_extensions_list(void)
 {
-       GSList *compressed_file_extensions;
        GSList *extensions;
        unsigned int i;
 
@@ -282,21 +269,15 @@ wtap_get_all_file_extensions_list(void)
 
        extensions = NULL;      /* empty list, to start with */
 
-       /*
-        * Get the list of compressed-file extensions.
-        */
-       compressed_file_extensions = wtap_get_compressed_file_extensions();
-
        for (i = 0; i < file_type_extensions_arr->len; i++) {
                /*
                 * Add all this file extension type's extensions, with
                 * compressed variants.
                 */
                extensions = add_extensions_for_file_extensions_type(i,
-                   extensions, compressed_file_extensions);
+                   extensions, compressed_file_extension_table);
        }
 
-       g_slist_free(compressed_file_extensions);
        return extensions;
 }
 
@@ -326,6 +307,17 @@ wtap_get_all_file_extensions_list(void)
  * type to interpret it as, if the file name has no extension, the
  * extension isn't sufficient to determine the appropriate file type,
  * or the extension is wrong.
+ *
+ * NOTE: when adding file formats to this list you may also want to add them
+ * to the following files so that the various desktop environments will
+ * know that Wireshark can open the file:
+ *     1) wireshark-mime-package.xml (for freedesktop.org environments)
+ *     2) packaging/macosx/Info.plist.in (for OS X)
+ *     3) packaging/nsis/AdditionalTasksPage.ini, packaging/nsis/common.nsh,
+ *        and packaging/wix/ComponentGroups.wxi (for Windows)
+ *
+ * If your file format has an expected extension (e.g., ".pcap") then you
+ * should probably also add it to file_type_extensions_base[] (in this file).
  */
 static struct open_info open_info_base[] = {
        { "Wireshark/tcpdump/... - pcap",           OPEN_INFO_MAGIC,     libpcap_open,             "pcap",     NULL, NULL },
@@ -349,9 +341,12 @@ static struct open_info open_info_base[] = {
        { "Symbian OS btsnoop",                     OPEN_INFO_MAGIC,     btsnoop_open,             "log",      NULL, NULL },
        { "EyeSDN USB S0/E1 ISDN trace format",     OPEN_INFO_MAGIC,     eyesdn_open,              NULL,       NULL, NULL },
        { "Transport-Neutral Encapsulation Format", OPEN_INFO_MAGIC,     tnef_open,                NULL,       NULL, NULL },
-       /* 3GPP Nettrace must come before MIME Files as it's XML based*/
-       { "3GPP Nettrace 32 423 Format",            OPEN_INFO_MAGIC,     nettrace_3gpp_32_423_file_open, NULL, NULL, NULL },
+       /* 3GPP TS 32.423 Trace must come before MIME Files as it's XML based*/
+       { "3GPP TS 32.423 Trace format",            OPEN_INFO_MAGIC,     nettrace_3gpp_32_423_file_open, NULL, NULL, NULL },
+       /* Gammu DCT3 trace must come before MIME files as it's XML based*/
+       { "Gammu DCT3 trace",                       OPEN_INFO_MAGIC,     dct3trace_open,           NULL,       NULL, NULL },
        { "MIME Files Format",                      OPEN_INFO_MAGIC,     mime_file_open,           NULL,       NULL, NULL },
+       { "Micropross mplog",                       OPEN_INFO_MAGIC,     mplog_open,               "mplog",    NULL, NULL },
        { "Novell LANalyzer",                       OPEN_INFO_HEURISTIC, lanalyzer_open,           "tr1",      NULL, NULL },
        /*
         * PacketLogger must come before MPEG, because its files
@@ -360,7 +355,6 @@ static struct open_info open_info_base[] = {
        { "OS X PacketLogger",                      OPEN_INFO_HEURISTIC, packetlogger_open,        "pklg",     NULL, NULL },
        /* Some MPEG files have magic numbers, others just have heuristics. */
        { "MPEG",                                   OPEN_INFO_HEURISTIC, mpeg_open,                "mpg;mp3",  NULL, NULL },
-       { "Gammu DCT3 trace",                       OPEN_INFO_HEURISTIC, dct3trace_open,           "xml",      NULL, NULL },
        { "Daintree SNA",                           OPEN_INFO_HEURISTIC, daintree_sna_open,        "dcf",      NULL, NULL },
        { "STANAG 4607 Format",                     OPEN_INFO_HEURISTIC, stanag4607_open,          NULL,       NULL, NULL },
        { "ASN.1 Basic Encoding Rules",             OPEN_INFO_HEURISTIC, ber_open,                 NULL,       NULL, NULL },
@@ -405,7 +399,7 @@ static struct open_info open_info_base[] = {
 
 /* this is only used to build the dynamic array on load, do NOT use this
  * for anything else, because the size of the actual array will change if
- *  Lua scripts register a new file reader.
+ * Lua scripts register a new file reader.
  */
 #define N_OPEN_INFO_ROUTINES  ((sizeof open_info_base / sizeof open_info_base[0]))
 
@@ -597,7 +591,7 @@ get_file_extension(const char *pathname)
        gchar *filename;
        gchar **components;
        size_t ncomponents;
-       GSList *compressed_file_extensions, *compressed_file_extension;
+       const char **compressed_file_extensionp;
        gchar *extensionp;
 
        /*
@@ -644,21 +638,11 @@ get_file_extension(const char *pathname)
         * Is the last component one of the extensions used for compressed
         * files?
         */
-       compressed_file_extensions = wtap_get_compressed_file_extensions();
-       if (compressed_file_extensions == NULL) {
-               /*
-                * We don't support reading compressed files, so just
-                * return a copy of whatever extension we did find.
-                */
-               extensionp = g_strdup(components[ncomponents - 1]);
-               g_strfreev(components);
-               return extensionp;
-       }
        extensionp = components[ncomponents - 1];
-       for (compressed_file_extension = compressed_file_extensions;
-           compressed_file_extension != NULL;
-           compressed_file_extension = g_slist_next(compressed_file_extension)) {
-               if (strcmp(extensionp, (char *)compressed_file_extension->data) == 0) {
+       for (compressed_file_extensionp = compressed_file_extension_table;
+           *compressed_file_extensionp != NULL;
+           compressed_file_extensionp++) {
+               if (strcmp(extensionp, *compressed_file_extensionp) == 0) {
                        /*
                         * Yes, it's one of the compressed-file extensions.
                         * Is there an extension before that?
@@ -730,6 +714,7 @@ wtap_open_offline(const char *filename, unsigned int type, int *err, char **err_
        unsigned int    i;
        gboolean use_stdin = FALSE;
        gchar *extension;
+       wtap_optionblock_t shb;
 
        *err = 0;
        *err_info = NULL;
@@ -849,11 +834,15 @@ wtap_open_offline(const char *filename, unsigned int type, int *err, char **err_
        wth->file_tsprec = WTAP_TSPREC_USEC;
        wth->priv = NULL;
        wth->wslua_data = NULL;
+       wth->shb_hdrs = g_array_new(FALSE, FALSE, sizeof(wtap_optionblock_t));
+       shb = wtap_optionblock_create(WTAP_OPTION_BLOCK_NG_SECTION);
+       if (shb)
+               g_array_append_val(wth->shb_hdrs, shb);
 
        /* Initialize the array containing a list of interfaces. pcapng_open and
         * erf_open needs this (and libpcap_open for ERF encapsulation types).
         * Always initing it here saves checking for a NULL ptr later. */
-       wth->interface_data = g_array_new(FALSE, FALSE, sizeof(wtapng_if_descr_t));
+       wth->interface_data = g_array_new(FALSE, FALSE, sizeof(wtap_optionblock_t));
 
        if (wth->random_fh) {
                wth->fast_seek = g_ptr_array_new();
@@ -1111,26 +1100,27 @@ success:
        wth->frame_buffer = (struct Buffer *)g_malloc(sizeof(struct Buffer));
        ws_buffer_init(wth->frame_buffer, 1500);
 
-       if(wth->file_type_subtype == WTAP_FILE_TYPE_SUBTYPE_PCAP){
-
-               wtapng_if_descr_t descr;
-
-               descr.wtap_encap = wth->file_encap;
-               descr.time_units_per_second = 1000000; /* default microsecond resolution */
-               descr.link_type = wtap_wtap_encap_to_pcap_encap(wth->file_encap);
-               descr.snap_len = wth->snapshot_length;
-               descr.opt_comment = NULL;
-               descr.if_name = NULL;
-               descr.if_description = NULL;
-               descr.if_speed = 0;
-               descr.if_tsresol = 6;
-               descr.if_filter_str= NULL;
-               descr.bpf_filter_len= 0;
-               descr.if_filter_bpf_bytes= NULL;
-               descr.if_os = NULL;
-               descr.if_fcslen = -1;
-               descr.num_stat_entries = 0;          /* Number of ISB:s */
-               descr.interface_statistics = NULL;
+       if ((wth->file_type_subtype == WTAP_FILE_TYPE_SUBTYPE_PCAP) ||
+               (wth->file_type_subtype == WTAP_FILE_TYPE_SUBTYPE_PCAP_NSEC)) {
+
+               wtap_optionblock_t descr = wtap_optionblock_create(WTAP_OPTION_BLOCK_IF_DESCR);
+               wtapng_if_descr_mandatory_t* descr_mand = (wtapng_if_descr_mandatory_t*)wtap_optionblock_get_mandatory_data(descr);
+
+               descr_mand->wtap_encap = wth->file_encap;
+               if (wth->file_type_subtype == WTAP_FILE_TYPE_SUBTYPE_PCAP_NSEC) {
+                       descr_mand->time_units_per_second = 1000000000; /* nanosecond resolution */
+                       wtap_optionblock_set_option_uint8(descr, OPT_IDB_TSRESOL, 9);
+                       descr_mand->tsprecision = WTAP_TSPREC_NSEC;
+               } else {
+                       descr_mand->time_units_per_second = 1000000; /* default microsecond resolution */
+                       wtap_optionblock_set_option_uint8(descr, OPT_IDB_TSRESOL, 6);
+                       descr_mand->tsprecision = WTAP_TSPREC_USEC;
+               }
+               descr_mand->link_type = wtap_wtap_encap_to_pcap_encap(wth->file_encap);
+               descr_mand->snap_len = wth->snapshot_length;
+
+               descr_mand->num_stat_entries = 0;          /* Number of ISB:s */
+               descr_mand->interface_statistics = NULL;
                g_array_append_val(wth->interface_data, descr);
 
        }
@@ -1199,12 +1189,17 @@ wtap_fdreopen(wtap *wth, const char *filename, int *err)
        return TRUE;
 }
 
-/* Table of the file types and subtypes we know about.
+/* Table of the file types and subtypes for which we have built-in support.
    Entries must be sorted by WTAP_FILE_TYPE_SUBTYPE_xxx values in ascending
    order.
 
    These are used to report what type and subtype a given file is and
-   to let the user select a format when writing out packets. */
+   to let the user select a format when writing out packets.
+
+   This table is what we start with, but it can be modified.
+   If we need to modify it, we allocate a GArray, copy the entries
+   in the above table to that GArray, use the copy as the table, and
+   make all changes to the copy. */
 static const struct file_type_subtype_info dump_open_table_base[] = {
        /* WTAP_FILE_TYPE_SUBTYPE_UNKNOWN (only used internally for initialization) */
        { NULL, NULL, NULL, NULL,
@@ -1547,11 +1542,6 @@ static const struct file_type_subtype_info dump_open_table_base[] = {
          FALSE, FALSE, 0,
          logcat_dump_can_write_encap, logcat_binary_dump_open, NULL },
 
-       /* WTAP_FILE_TYPE_SUBTYPE_JSON */
-       { "JavaScript Object Notation", "json", "json", "NULL",
-         FALSE, FALSE, 0,
-         NULL, NULL, NULL },
-
        /* WTAP_FILE_TYPE_SUBTYPE_LOGCAT_BRIEF */
        { "Android Logcat Brief text format", "logcat-brief", NULL, NULL,
          FALSE, FALSE, 0,
@@ -1597,27 +1587,52 @@ static const struct file_type_subtype_info dump_open_table_base[] = {
          FALSE, FALSE, 0,
          NULL, NULL, NULL },
 
+       /* WTAP_FILE_TYPE_SUBTYPE_JSON */
+       { "JavaScript Object Notation", "json", "json", "NULL",
+         FALSE, FALSE, 0,
+         NULL, NULL, NULL },
+
        /* WTAP_FILE_TYPE_SUBTYPE_NETSCALER_3_5 */
        { "NetScaler Trace (Version 3.5)", "nstrace35", "cap", NULL,
          TRUE, FALSE, 0,
          nstrace_35_dump_can_write_encap, nstrace_dump_open, NULL },
 
        /* WTAP_FILE_TYPE_SUBTYPE_NETTRACE_3GPP_32_423 */
-       { "Nettrace 3GPP 32 423", "nettrace3gpp324423", NULL, NULL,
+       { "3GPP TS 32.423 Trace", "3gpp32423", NULL, NULL,
          FALSE, FALSE, 0,
          NULL, NULL, NULL },
+
+       /* WTAP_FILE_TYPE_MPLOG */
+       { "Micropross mplog file", "mplog", "mplog", NULL,
+         FALSE, FALSE, 0,
+         NULL, NULL, NULL }
 };
 
+/*
+ * Pointer to the table we're currently using.  It's initialized to point
+ * to the static table, but, if we have to allocate the GArray, it's
+ * changed to point to the data in the GArray.
+ */
+static const struct file_type_subtype_info* dump_open_table = dump_open_table_base;
+
+/*
+ * Number of elements in the table we're currently using.  It's initialized
+ * to the number of elements in the static table, but, if we have to
+ * allocate the GArray, it's changed to have the size of the GArray.
+ */
 gint wtap_num_file_types_subtypes = sizeof(dump_open_table_base) / sizeof(struct file_type_subtype_info);
 
+/*
+ * Pointer to the GArray; NULL until it's needed.
+ */
 static GArray*  dump_open_table_arr = NULL;
-static const struct file_type_subtype_info* dump_open_table = dump_open_table_base;
 
-/* initialize the file types array if it has not being initialized yet */
+/*
+ * Create the GArray from the static table if it hasn't already been created.
+ */
 static void
-init_file_types_subtypes(void)
+init_file_types_subtypes_garray(void)
 {
-
        if (dump_open_table_arr) return;
 
        dump_open_table_arr = g_array_new(FALSE,TRUE,sizeof(struct file_type_subtype_info));
@@ -1633,7 +1648,6 @@ int
 wtap_register_file_type_subtypes(const struct file_type_subtype_info* fi, const int subtype)
 {
        struct file_type_subtype_info* finfo;
-       init_file_types_subtypes();
 
        if (!fi || !fi->name || !fi->short_name || subtype > wtap_num_file_types_subtypes) {
                g_error("no file type info or invalid file type to register");
@@ -1648,6 +1662,11 @@ wtap_register_file_type_subtypes(const struct file_type_subtype_info* fi, const
                        return subtype;
                }
 
+               /*
+                * Create the GArray if it hasn't already been created.
+                */
+               init_file_types_subtypes_garray();
+
                g_array_append_val(dump_open_table_arr,*fi);
 
                dump_open_table = (const struct file_type_subtype_info*)(void *)dump_open_table_arr->data;
@@ -1661,8 +1680,16 @@ wtap_register_file_type_subtypes(const struct file_type_subtype_info* fi, const
                return subtype;
        }
 
-       /* yes, we're going to cast to change its const-ness */
-       finfo = (struct file_type_subtype_info*)(&dump_open_table[subtype]);
+       /*
+        * Create the GArray if it hasn't already been created.
+        */
+       init_file_types_subtypes_garray();
+
+       /*
+        * Get the pointer from the GArray, so that we get a non-const
+        * pointer.
+        */
+       finfo = &g_array_index(dump_open_table_arr, struct file_type_subtype_info, subtype);
        /*finfo->name = fi->name;*/
        /*finfo->short_name = fi->short_name;*/
        finfo->default_file_extension     = fi->default_file_extension;
@@ -1689,8 +1716,16 @@ wtap_deregister_file_type_subtype(const int subtype)
                return;
        }
 
-       /* yes, we're going to cast to change its const-ness */
-       finfo = (struct file_type_subtype_info*)(&dump_open_table[subtype]);
+       /*
+        * Create the GArray if it hasn't already been created.
+        */
+       init_file_types_subtypes_garray();
+
+       /*
+        * Get the pointer from the GArray, so that we get a non-const
+        * pointer.
+        */
+       finfo = &g_array_index(dump_open_table_arr, struct file_type_subtype_info, subtype);
        /* unfortunately, it's not safe to null-out the name or short_name; bunch of other code doesn't guard aainst that, afaict */
        /*finfo->name = NULL;*/
        /*finfo->short_name = NULL;*/
@@ -1954,7 +1989,7 @@ wtap_short_string_to_file_type_subtype(const char *short_name)
 
 static GSList *
 add_extensions_for_file_type_subtype(int file_type_subtype, GSList *extensions,
-    GSList *compressed_file_extensions)
+    const char **compressed_file_extensions)
 {
        gchar **extensions_set, **extensionp;
        gchar *extension;
@@ -2008,8 +2043,10 @@ add_extensions_for_file_type_subtype(int file_type_subtype, GSList *extensions,
 GSList *
 wtap_get_file_extensions_list(int file_type_subtype, gboolean include_compressed)
 {
-       GSList *compressed_file_extensions;
        GSList *extensions;
+       static const char *no_compressed_extensions[] = {
+               NULL
+       };
 
        if (file_type_subtype < 0 || file_type_subtype >= wtap_num_file_types_subtypes)
                return NULL;    /* not a valid file type */
@@ -2019,23 +2056,13 @@ wtap_get_file_extensions_list(int file_type_subtype, gboolean include_compressed
 
        extensions = NULL;      /* empty list, to start with */
 
-       /*
-        * If include_compressions is true, get the list of compressed-file
-        * extensions.
-        */
-       if (include_compressed)
-               compressed_file_extensions = wtap_get_compressed_file_extensions();
-       else
-               compressed_file_extensions = NULL;
-
        /*
         * Add all this file type's extensions, with compressed
-        * variants.
+        * variants if include_compressed is true.
         */
        extensions = add_extensions_for_file_type_subtype(file_type_subtype, extensions,
-           compressed_file_extensions);
+           include_compressed ? compressed_file_extension_table : no_compressed_extensions);
 
-       g_slist_free(compressed_file_extensions);
        return extensions;
 }
 
@@ -2076,7 +2103,7 @@ wtap_dump_can_open(int file_type_subtype)
        return TRUE;
 }
 
-#ifdef HAVE_LIBZ
+#ifdef HAVE_ZLIB
 gboolean
 wtap_dump_can_compress(int file_type_subtype)
 {
@@ -2133,18 +2160,19 @@ static WFILE_T wtap_dump_file_open(wtap_dumper *wdh, const char *filename);
 static WFILE_T wtap_dump_file_fdopen(wtap_dumper *wdh, int fd);
 static int wtap_dump_file_close(wtap_dumper *wdh);
 
-wtap_dumper *
-wtap_dump_open(const char *filename, int file_type_subtype, int encap,
-              int snaplen, gboolean compressed, int *err)
-{
-       return wtap_dump_open_ng(filename, file_type_subtype, encap,snaplen, compressed, NULL, NULL, err);
-}
-
 static wtap_dumper *
 wtap_dump_init_dumper(int file_type_subtype, int encap, int snaplen, gboolean compressed,
-    wtapng_section_t *shb_hdr, wtapng_iface_descriptions_t *idb_inf, int *err)
+                      GArray* shb_hdrs, wtapng_iface_descriptions_t *idb_inf,
+                      GArray* nrb_hdrs, int *err)
 {
        wtap_dumper *wdh;
+       wtap_optionblock_t descr, file_int_data;
+       wtapng_if_descr_mandatory_t *descr_mand, *file_int_data_mand;
+
+       /* Check whether we can open a capture file with that file type
+          and that encapsulation. */
+       if (!wtap_dump_open_check(file_type_subtype, encap, compressed, err))
+               return NULL;
 
        /* Allocate a data structure for the output stream. */
        wdh = wtap_dump_alloc_wdh(file_type_subtype, encap, snaplen, compressed, err);
@@ -2152,89 +2180,144 @@ wtap_dump_init_dumper(int file_type_subtype, int encap, int snaplen, gboolean co
                return NULL;    /* couldn't allocate it */
 
        /* Set Section Header Block data */
-       wdh->shb_hdr = shb_hdr;
+       wdh->shb_hdrs = shb_hdrs;
+       /* Set Name Resolution Block data */
+       wdh->nrb_hdrs = nrb_hdrs;
        /* Set Interface Description Block data */
        if ((idb_inf != NULL) && (idb_inf->interface_data->len > 0)) {
-               wdh->interface_data = idb_inf->interface_data;
+               guint itf_count;
+
+               /* XXX: what free's this stuff? */
+               wdh->interface_data = g_array_new(FALSE, FALSE, sizeof(wtap_optionblock_t));
+               for (itf_count = 0; itf_count < idb_inf->interface_data->len; itf_count++) {
+                       file_int_data = g_array_index(idb_inf->interface_data, wtap_optionblock_t, itf_count);
+                       file_int_data_mand = (wtapng_if_descr_mandatory_t*)wtap_optionblock_get_mandatory_data(file_int_data);
+                       descr = wtap_optionblock_create(WTAP_OPTION_BLOCK_IF_DESCR);
+                       wtap_optionblock_copy_options(descr, file_int_data);
+                       if ((encap != WTAP_ENCAP_PER_PACKET) && (encap != file_int_data_mand->wtap_encap)) {
+                               descr_mand = (wtapng_if_descr_mandatory_t*)wtap_optionblock_get_mandatory_data(descr);
+                               descr_mand->wtap_encap = encap;
+                               descr_mand->link_type = wtap_wtap_encap_to_pcap_encap(encap);
+                       }
+                       g_array_append_val(wdh->interface_data, descr);
+               }
        } else {
-               wtapng_if_descr_t descr;
-
-               descr.wtap_encap = encap;
-               descr.time_units_per_second = 1000000; /* default microsecond resolution */
-               descr.link_type = wtap_wtap_encap_to_pcap_encap(encap);
-               descr.snap_len = snaplen;
-               descr.opt_comment = NULL;
-               descr.if_name = g_strdup("Unknown/not available in original file format(libpcap)");
-               descr.if_description = NULL;
-               descr.if_speed = 0;
-               descr.if_tsresol = 6;
-               descr.if_filter_str= NULL;
-               descr.bpf_filter_len= 0;
-               descr.if_filter_bpf_bytes= NULL;
-               descr.if_os = NULL;
-               descr.if_fcslen = -1;
-               descr.num_stat_entries = 0;          /* Number of ISB:s */
-               descr.interface_statistics = NULL;
-               wdh->interface_data = g_array_new(FALSE, FALSE, sizeof(wtapng_if_descr_t));
+               descr = wtap_optionblock_create(WTAP_OPTION_BLOCK_IF_DESCR);
+               descr_mand = (wtapng_if_descr_mandatory_t*)wtap_optionblock_get_mandatory_data(descr);
+               descr_mand->wtap_encap = encap;
+               descr_mand->time_units_per_second = 1000000; /* default microsecond resolution */
+               descr_mand->link_type = wtap_wtap_encap_to_pcap_encap(encap);
+               descr_mand->snap_len = snaplen;
+               wtap_optionblock_set_option_string(descr, OPT_IDB_NAME, "Unknown/not available in original file format(libpcap)",
+                                                                                                               strlen("Unknown/not available in original file format(libpcap)"));
+
+               descr_mand->num_stat_entries = 0;          /* Number of ISB:s */
+               descr_mand->interface_statistics = NULL;
+               wdh->interface_data = g_array_new(FALSE, FALSE, sizeof(wtap_optionblock_t));
                g_array_append_val(wdh->interface_data, descr);
        }
        return wdh;
 }
 
+wtap_dumper *
+wtap_dump_open(const char *filename, int file_type_subtype, int encap,
+              int snaplen, gboolean compressed, int *err)
+{
+       return wtap_dump_open_ng(filename, file_type_subtype, encap,snaplen, compressed, NULL, NULL, NULL, err);
+}
+
 wtap_dumper *
 wtap_dump_open_ng(const char *filename, int file_type_subtype, int encap,
-                 int snaplen, gboolean compressed, wtapng_section_t *shb_hdr, wtapng_iface_descriptions_t *idb_inf, int *err)
+                 int snaplen, gboolean compressed, GArray* shb_hdrs, wtapng_iface_descriptions_t *idb_inf,
+                 GArray* nrb_hdrs, int *err)
 {
        wtap_dumper *wdh;
        WFILE_T fh;
 
-       /* Check whether we can open a capture file with that file type
-          and that encapsulation. */
-       if (!wtap_dump_open_check(file_type_subtype, encap, compressed, err))
+       /* Allocate and initialize a data structure for the output stream. */
+       wdh = wtap_dump_init_dumper(file_type_subtype, encap, snaplen, compressed,
+           shb_hdrs, idb_inf, nrb_hdrs, err);
+       if (wdh == NULL)
+               return NULL;
+
+       /* In case "fopen()" fails but doesn't set "errno", set "errno"
+          to a generic "the open failed" error. */
+       errno = WTAP_ERR_CANT_OPEN;
+       fh = wtap_dump_file_open(wdh, filename);
+       if (fh == NULL) {
+               *err = errno;
+               g_free(wdh);
+               return NULL;    /* can't create file */
+       }
+       wdh->fh = fh;
+
+       if (!wtap_dump_open_finish(wdh, file_type_subtype, compressed, err)) {
+               /* Get rid of the file we created; we couldn't finish
+                  opening it. */
+               wtap_dump_file_close(wdh);
+               ws_unlink(filename);
+               g_free(wdh);
                return NULL;
+       }
+       return wdh;
+}
+
+wtap_dumper *
+wtap_dump_open_tempfile(char **filenamep, const char *pfx,
+                       int file_type_subtype, int encap,
+                       int snaplen, gboolean compressed, int *err)
+{
+       return wtap_dump_open_tempfile_ng(filenamep, pfx, file_type_subtype, encap,snaplen, compressed, NULL, NULL, NULL, err);
+}
+
+wtap_dumper *
+wtap_dump_open_tempfile_ng(char **filenamep, const char *pfx,
+                          int file_type_subtype, int encap,
+                          int snaplen, gboolean compressed,
+                          GArray* shb_hdrs,
+                          wtapng_iface_descriptions_t *idb_inf,
+                          GArray* nrb_hdrs, int *err)
+{
+       int fd;
+       char *tmpname;
+       wtap_dumper *wdh;
+       WFILE_T fh;
+
+       /* No path name for the temporary file yet. */
+       *filenamep = NULL;
 
        /* Allocate and initialize a data structure for the output stream. */
        wdh = wtap_dump_init_dumper(file_type_subtype, encap, snaplen, compressed,
-           shb_hdr, idb_inf, err);
+           shb_hdrs, idb_inf, nrb_hdrs, err);
        if (wdh == NULL)
                return NULL;
 
-       /* "-" means stdout */
-       if (strcmp(filename, "-") == 0) {
-               if (compressed) {
-                       *err = EINVAL;  /* XXX - return a Wiretap error code for this */
-                       g_free(wdh);
-                       return NULL;    /* compress won't work on stdout */
-               }
-#ifdef _WIN32
-               if (_setmode(fileno(stdout), O_BINARY) == -1) {
-                       /* "Should not happen" */
-                       *err = errno;
-                       g_free(wdh);
-                       return NULL;    /* couldn't put standard output in binary mode */
-               }
-#endif
-               wdh->fh = stdout;
-       } else {
-               /* In case "fopen()" fails but doesn't set "errno", set "errno"
-                  to a generic "the open failed" error. */
-               errno = WTAP_ERR_CANT_OPEN;
-               fh = wtap_dump_file_open(wdh, filename);
-               if (fh == NULL) {
-                       *err = errno;
-                       g_free(wdh);
-                       return NULL;    /* can't create file */
-               }
-               wdh->fh = fh;
+       /* Choose a random name for the file */
+       fd = create_tempfile(&tmpname, pfx, ".pcapng");
+       if (fd == -1) {
+               *err = errno;
+               g_free(wdh);
+               return NULL;    /* can't create file */
+       }
+       *filenamep = tmpname;
+
+       /* In case "fopen()" fails but doesn't set "errno", set "errno"
+          to a generic "the open failed" error. */
+       errno = WTAP_ERR_CANT_OPEN;
+       fh = wtap_dump_file_fdopen(wdh, fd);
+       if (fh == NULL) {
+               *err = errno;
+               ws_close(fd);
+               g_free(wdh);
+               return NULL;    /* can't create file */
        }
+       wdh->fh = fh;
 
        if (!wtap_dump_open_finish(wdh, file_type_subtype, compressed, err)) {
                /* Get rid of the file we created; we couldn't finish
                   opening it. */
-               if (wdh->fh != stdout) {
-                       wtap_dump_file_close(wdh);
-                       ws_unlink(filename);
-               }
+               wtap_dump_file_close(wdh);
+               ws_unlink(tmpname);
                g_free(wdh);
                return NULL;
        }
@@ -2245,48 +2328,90 @@ wtap_dumper *
 wtap_dump_fdopen(int fd, int file_type_subtype, int encap, int snaplen,
                 gboolean compressed, int *err)
 {
-       return wtap_dump_fdopen_ng(fd, file_type_subtype, encap, snaplen, compressed, NULL, NULL, err);
+       return wtap_dump_fdopen_ng(fd, file_type_subtype, encap, snaplen, compressed, NULL, NULL, NULL, err);
 }
 
 wtap_dumper *
 wtap_dump_fdopen_ng(int fd, int file_type_subtype, int encap, int snaplen,
-                   gboolean compressed, wtapng_section_t *shb_hdr, wtapng_iface_descriptions_t *idb_inf, int *err)
+                   gboolean compressed, GArray* shb_hdrs, wtapng_iface_descriptions_t *idb_inf,
+                   GArray* nrb_hdrs, int *err)
 {
        wtap_dumper *wdh;
        WFILE_T fh;
 
-       /* Check whether we can open a capture file with that file type
-          and that encapsulation. */
-       if (!wtap_dump_open_check(file_type_subtype, encap, compressed, err))
+       /* Allocate and initialize a data structure for the output stream. */
+       wdh = wtap_dump_init_dumper(file_type_subtype, encap, snaplen, compressed,
+           shb_hdrs, idb_inf, nrb_hdrs, err);
+       if (wdh == NULL)
+               return NULL;
+
+       /* In case "fopen()" fails but doesn't set "errno", set "errno"
+          to a generic "the open failed" error. */
+       errno = WTAP_ERR_CANT_OPEN;
+       fh = wtap_dump_file_fdopen(wdh, fd);
+       if (fh == NULL) {
+               *err = errno;
+               g_free(wdh);
+               return NULL;    /* can't create standard I/O stream */
+       }
+       wdh->fh = fh;
+
+       if (!wtap_dump_open_finish(wdh, file_type_subtype, compressed, err)) {
+               wtap_dump_file_close(wdh);
+               g_free(wdh);
                return NULL;
+       }
+       return wdh;
+}
+
+wtap_dumper *
+wtap_dump_open_stdout(int file_type_subtype, int encap, int snaplen,
+                     gboolean compressed, int *err)
+{
+       return wtap_dump_open_stdout_ng(file_type_subtype, encap, snaplen, compressed, NULL, NULL, NULL, err);
+}
+
+wtap_dumper *
+wtap_dump_open_stdout_ng(int file_type_subtype, int encap, int snaplen,
+                        gboolean compressed, GArray* shb_hdrs,
+                        wtapng_iface_descriptions_t *idb_inf,
+                        GArray* nrb_hdrs, int *err)
+{
+       wtap_dumper *wdh;
+       WFILE_T fh;
 
        /* Allocate and initialize a data structure for the output stream. */
        wdh = wtap_dump_init_dumper(file_type_subtype, encap, snaplen, compressed,
-           shb_hdr, idb_inf, err);
+           shb_hdrs, idb_inf, nrb_hdrs, err);
        if (wdh == NULL)
                return NULL;
 
 #ifdef _WIN32
-       if (fd == 1) {
-               if (_setmode(fileno(stdout), O_BINARY) == -1) {
-                       /* "Should not happen" */
-                       *err = errno;
-                       g_free(wdh);
-                       return NULL;    /* couldn't put standard output in binary mode */
-               }
+       /*
+        * Put the standard output into binary mode.
+        *
+        * XXX - even if the file format we're writing is a text
+        * format?
+        */
+       if (_setmode(1, O_BINARY) == -1) {
+               /* "Should not happen" */
+               *err = errno;
+               g_free(wdh);
+               return NULL;    /* couldn't put standard output in binary mode */
        }
 #endif
 
        /* In case "fopen()" fails but doesn't set "errno", set "errno"
           to a generic "the open failed" error. */
        errno = WTAP_ERR_CANT_OPEN;
-       fh = wtap_dump_file_fdopen(wdh, fd);
+       fh = wtap_dump_file_fdopen(wdh, 1);
        if (fh == NULL) {
                *err = errno;
                g_free(wdh);
                return NULL;    /* can't create standard I/O stream */
        }
        wdh->fh = fh;
+       wdh->is_stdout = TRUE;
 
        if (!wtap_dump_open_finish(wdh, file_type_subtype, compressed, err)) {
                wtap_dump_file_close(wdh);
@@ -2360,7 +2485,7 @@ wtap_dump_open_finish(wtap_dumper *wdh, int file_type_subtype, gboolean compress
        if(compressed) {
                cant_seek = TRUE;
        } else {
-               fd = fileno((FILE *)wdh->fh);
+               fd = ws_fileno((FILE *)wdh->fh);
                if (ws_lseek64(fd, 1, SEEK_CUR) == (off_t) -1)
                        cant_seek = TRUE;
                else {
@@ -2402,7 +2527,7 @@ wtap_dump(wtap_dumper *wdh, const struct wtap_pkthdr *phdr,
 void
 wtap_dump_flush(wtap_dumper *wdh)
 {
-#ifdef HAVE_LIBZ
+#ifdef HAVE_ZLIB
        if(wdh->compressed) {
                gzwfile_flush((GZWFILE_T)wdh->fh);
        } else
@@ -2417,27 +2542,21 @@ wtap_dump_close(wtap_dumper *wdh, int *err)
 {
        gboolean ret = TRUE;
 
-       if (wdh->subtype_close != NULL) {
-               /* There's a close routine for this dump stream. */
-               if (!(wdh->subtype_close)(wdh, err))
+       if (wdh->subtype_finish != NULL) {
+               /* There's a finish routine for this dump stream. */
+               if (!(wdh->subtype_finish)(wdh, err))
                        ret = FALSE;
        }
        errno = WTAP_ERR_CANT_CLOSE;
-       /* Don't close stdout */
-       if (wdh->fh != stdout) {
-               if (wtap_dump_file_close(wdh) == EOF) {
-                       if (ret) {
-                               /* The per-format close function succeeded,
-                                  but the fclose didn't.  Save the reason
-                                  why, if our caller asked for it. */
-                               if (err != NULL)
-                                       *err = errno;
-                       }
-                       ret = FALSE;
+       if (wtap_dump_file_close(wdh) == EOF) {
+               if (ret) {
+                       /* The per-format finish function succeeded,
+                          but the stream close didn't.  Save the
+                          reason why, if our caller asked for it. */
+                       if (err != NULL)
+                               *err = errno;
                }
-       } else {
-               /* as we don't close stdout, at least try to flush it */
-               wtap_dump_flush(wdh);
+               ret = FALSE;
        }
        if (wdh->priv != NULL)
                g_free(wdh->priv);
@@ -2468,7 +2587,7 @@ wtap_dump_set_addrinfo_list(wtap_dumper *wdh, addrinfo_lists_t *addrinfo_lists)
 }
 
 /* internally open a file for writing (compressed or not) */
-#ifdef HAVE_LIBZ
+#ifdef HAVE_ZLIB
 static WFILE_T
 wtap_dump_file_open(wtap_dumper *wdh, const char *filename)
 {
@@ -2487,21 +2606,21 @@ wtap_dump_file_open(wtap_dumper *wdh _U_, const char *filename)
 #endif
 
 /* internally open a file for writing (compressed or not) */
-#ifdef HAVE_LIBZ
+#ifdef HAVE_ZLIB
 static WFILE_T
 wtap_dump_file_fdopen(wtap_dumper *wdh, int fd)
 {
        if(wdh->compressed) {
                return gzwfile_fdopen(fd);
        } else {
-               return fdopen(fd, "wb");
+               return ws_fdopen(fd, "wb");
        }
 }
 #else
 static WFILE_T
 wtap_dump_file_fdopen(wtap_dumper *wdh _U_, int fd)
 {
-       return fdopen(fd, "wb");
+       return ws_fdopen(fd, "wb");
 }
 #endif
 
@@ -2511,7 +2630,7 @@ wtap_dump_file_write(wtap_dumper *wdh, const void *buf, size_t bufsize, int *err
 {
        size_t nwritten;
 
-#ifdef HAVE_LIBZ
+#ifdef HAVE_ZLIB
        if (wdh->compressed) {
                nwritten = gzwfile_write((GZWFILE_T)wdh->fh, buf, (unsigned int) bufsize);
                /*
@@ -2545,20 +2664,31 @@ wtap_dump_file_write(wtap_dumper *wdh, const void *buf, size_t bufsize, int *err
 static int
 wtap_dump_file_close(wtap_dumper *wdh)
 {
-#ifdef HAVE_LIBZ
+#ifdef HAVE_ZLIB
        if(wdh->compressed) {
-               return gzwfile_close((GZWFILE_T)wdh->fh);
+               /*
+                * Tell gzwfile_close() whether to close the descriptor
+                * or not.
+                */
+               return gzwfile_close((GZWFILE_T)wdh->fh, wdh->is_stdout);
        } else
 #endif
        {
-               return fclose((FILE *)wdh->fh);
+               /*
+                * Don't close the standard output.
+                *
+                * XXX - this really should do everything fclose() does,
+                * including freeing all allocated data structures,
+                * *except* for actually closing the file descriptor.
+                */
+               return wdh->is_stdout ? fflush((FILE *)wdh->fh) : fclose((FILE *)wdh->fh);
        }
 }
 
 gint64
 wtap_dump_file_seek(wtap_dumper *wdh, gint64 offset, int whence, int *err)
 {
-#ifdef HAVE_LIBZ
+#ifdef HAVE_ZLIB
        if(wdh->compressed) {
                *err = WTAP_ERR_CANT_SEEK_COMPRESSED;
                return -1;
@@ -2579,7 +2709,7 @@ gint64
 wtap_dump_file_tell(wtap_dumper *wdh, int *err)
 {
        gint64 rval;
-#ifdef HAVE_LIBZ
+#ifdef HAVE_ZLIB
        if(wdh->compressed) {
                *err = WTAP_ERR_CANT_SEEK_COMPRESSED;
                return -1;