4 * Copyright (c) 1998 by Gilbert Ramirez <gram@alumni.rice.edu>
6 * This program is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU General Public License
8 * as published by the Free Software Foundation; either version 2
9 * of the License, or (at your option) any later version.
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, write to the Free Software
18 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
28 #include <wsutil/file_util.h>
29 #include <wsutil/tempfile.h>
32 #include "file_wrappers.h"
33 #include <wsutil/buffer.h>
34 #include "lanalyzer.h"
35 #include "ngsniffer.h"
37 #include "ascendtext.h"
50 #include "peekclassic.h"
51 #include "peektagged.h"
53 #include "dbs-etherwatch.h"
60 #include "logcat_text.h"
62 #include "network_instruments.h"
65 #include "catapult_dct2000.h"
68 #include "netscreen.h"
74 #include "dct3trace.h"
75 #include "packetlogger.h"
76 #include "daintree-sna.h"
77 #include "netscaler.h"
78 #include "mime_file.h"
82 #include "stanag4607.h"
84 #include "pcap-encap.h"
85 #include "nettrace_3gpp_32_423.h"
89 * Add an extension, and all compressed versions thereof, to a GSList
93 add_extensions(GSList *extensions, const gchar *extension,
94 const char **compressed_file_extensions)
96 const char **compressed_file_extensionp;
99 * Add the specified extension.
101 extensions = g_slist_prepend(extensions, g_strdup(extension));
104 * Now add the extensions for compressed-file versions of
107 for (compressed_file_extensionp = compressed_file_extensions;
108 *compressed_file_extensionp != NULL;
109 compressed_file_extensionp++) {
110 extensions = g_slist_prepend(extensions,
111 g_strdup_printf("%s.%s", extension,
112 *compressed_file_extensionp));
119 * File types that can be identified by file extensions.
121 * These are used in file open dialogs to offer choices of extensions
122 * for which to filter. Note that the first field can list more than
123 * one type of file, because, for example, ".cap" is a popular
124 * extension used by a number of capture file types.
126 static const struct file_extension_info file_type_extensions_base[] = {
127 { "Wireshark/tcpdump/... - pcap", TRUE, "pcap;cap;dmp" },
128 { "Wireshark/... - pcapng", TRUE, "pcapng;ntar" },
129 { "Network Monitor, Surveyor, NetScaler", TRUE, "cap" },
130 { "InfoVista 5View capture", TRUE, "5vw" },
131 { "Sniffer (DOS)", TRUE, "cap;enc;trc;fdc;syc" },
132 { "Cinco NetXRay, Sniffer (Windows)", TRUE, "cap;caz" },
133 { "Endace ERF capture", TRUE, "erf" },
134 { "EyeSDN USB S0/E1 ISDN trace format", TRUE, "trc" },
135 { "HP-UX nettl trace", TRUE, "trc0;trc1" },
136 { "Network Instruments Observer", TRUE, "bfr" },
137 { "Colasoft Capsa", TRUE, "cscpkt" },
138 { "Novell LANalyzer", TRUE, "tr1" },
139 { "Tektronix K12xx 32-bit .rf5 format", TRUE, "rf5" },
140 { "Savvius *Peek", TRUE, "pkt;tpc;apc;wpz" },
141 { "Catapult DCT2000 trace (.out format)", TRUE, "out" },
142 { "Micropross mplog", TRUE, "mplog" },
143 { "TamoSoft CommView", TRUE, "ncf" },
144 { "Symbian OS btsnoop", TRUE, "log" },
145 { "XML files (including Gammu DCT3 traces)", TRUE, "xml" },
146 { "macOS PacketLogger", TRUE, "pklg" },
147 { "Daintree SNA", TRUE, "dcf" },
148 { "IPFIX File Format", TRUE, "pfx;ipfix" },
149 { "Aethra .aps file", TRUE, "aps" },
150 { "MPEG2 transport stream", TRUE, "mp2t;ts;mpg" },
151 { "Ixia IxVeriWave .vwr Raw 802.11 Capture", TRUE, "vwr" },
152 { "CAM Inspector file", TRUE, "camins" },
153 { "MPEG files", FALSE, "mpg;mp3" },
154 { "Transport-Neutral Encapsulation Format", FALSE, "tnef" },
155 { "JPEG/JFIF files", FALSE, "jpg;jpeg;jfif" },
156 { "JavaScript Object Notation file", FALSE, "json" }
159 #define N_FILE_TYPE_EXTENSIONS (sizeof file_type_extensions_base / sizeof file_type_extensions_base[0])
161 static const struct file_extension_info* file_type_extensions = NULL;
163 static GArray* file_type_extensions_arr = NULL;
165 /* initialize the extensions array if it has not been initialized yet */
167 init_file_type_extensions(void)
170 if (file_type_extensions_arr) return;
172 file_type_extensions_arr = g_array_new(FALSE,TRUE,sizeof(struct file_extension_info));
174 g_array_append_vals(file_type_extensions_arr,file_type_extensions_base,N_FILE_TYPE_EXTENSIONS);
176 file_type_extensions = (struct file_extension_info*)(void *)file_type_extensions_arr->data;
180 wtap_register_file_type_extension(const struct file_extension_info *ei)
182 init_file_type_extensions();
184 g_array_append_val(file_type_extensions_arr,*ei);
186 file_type_extensions = (const struct file_extension_info*)(void *)file_type_extensions_arr->data;
190 wtap_get_num_file_type_extensions(void)
192 return file_type_extensions_arr->len;
196 wtap_get_file_extension_type_name(int extension_type)
198 return file_type_extensions[extension_type].name;
202 add_extensions_for_file_extensions_type(int extension_type,
203 GSList *extensions, const char **compressed_file_extensions)
205 gchar **extensions_set, **extensionp, *extension;
208 * Split the extension-list string into a set of extensions.
210 extensions_set = g_strsplit(file_type_extensions[extension_type].extensions,
214 * Add each of those extensions to the list.
216 for (extensionp = extensions_set; *extensionp != NULL; extensionp++) {
217 extension = *extensionp;
220 * Add the extension, and all compressed variants
223 extensions = add_extensions(extensions, extension,
224 compressed_file_extensions);
227 g_strfreev(extensions_set);
231 /* Return a list of file extensions that are used by the specified file
234 All strings in the list are allocated with g_malloc() and must be freed
237 wtap_get_file_extension_type_extensions(guint extension_type)
241 if (extension_type >= file_type_extensions_arr->len)
242 return NULL; /* not a valid extension type */
244 extensions = NULL; /* empty list, to start with */
247 * Add all this file extension type's extensions, with compressed
250 extensions = add_extensions_for_file_extensions_type(extension_type,
251 extensions, compressed_file_extension_table);
256 /* Return a list of all extensions that are used by all capture file
257 types, including compressed extensions, e.g. not just "pcap" but
258 also "pcap.gz" if we can read gzipped files.
260 "Capture files" means "include file types that correspond to
261 collections of network packets, but not file types that
262 store data that just happens to be transported over protocols
263 such as HTTP but that aren't collections of network packets",
264 so that it could be used for "All Capture Files" without picking
265 up JPEG files or files such as that - those aren't capture files,
266 and we *do* have them listed in the long list of individual file
267 types, so omitting them from "All Capture Files" is the right
270 All strings in the list are allocated with g_malloc() and must be freed
273 wtap_get_all_capture_file_extensions_list(void)
278 init_file_type_extensions();
280 extensions = NULL; /* empty list, to start with */
282 for (i = 0; i < file_type_extensions_arr->len; i++) {
284 * Is this a capture file, rather than one of the
285 * other random file types we can read?
287 if (file_type_extensions[i].is_capture_file) {
289 * Yes. Add all this file extension type's
290 * extensions, with compressed variants.
292 extensions = add_extensions_for_file_extensions_type(i,
293 extensions, compressed_file_extension_table);
301 * The open_file_* routines should return:
303 * -1 on an I/O error;
305 * 1 if the file they're reading is one of the types it handles;
307 * 0 if the file they're reading isn't the type they're checking for.
309 * If the routine handles this type of file, it should set the "file_type"
310 * field in the "struct wtap" to the type of the file.
312 * Note that the routine does not have to free the private data pointer on
313 * error. The caller takes care of that by calling wtap_close on error.
314 * (See https://bugs.wireshark.org/bugzilla/show_bug.cgi?id=8518)
316 * However, the caller does have to free the private data pointer when
317 * returning 0, since the next file type will be called and will likely
318 * just overwrite the pointer.
320 * The names are used in file open dialogs to select, for files that
321 * don't have magic numbers and that could potentially be files of
322 * more than one type based on the heuristics, a particular file
323 * type to interpret it as, if the file name has no extension, the
324 * extension isn't sufficient to determine the appropriate file type,
325 * or the extension is wrong.
327 * NOTE: when adding file formats to this list you may also want to add them
328 * to the following files so that the various desktop environments will
329 * know that Wireshark can open the file:
330 * 1) wireshark-mime-package.xml (for freedesktop.org environments)
331 * 2) packaging/macosx/Info.plist.in (for macOS)
332 * 3) packaging/nsis/AdditionalTasksPage.ini, packaging/nsis/common.nsh,
333 * and packaging/wix/ComponentGroups.wxi (for Windows)
335 * If your file format has an expected extension (e.g., ".pcap") then you
336 * should probably also add it to file_type_extensions_base[] (in this file).
338 static struct open_info open_info_base[] = {
339 { "Wireshark/tcpdump/... - pcap", OPEN_INFO_MAGIC, libpcap_open, "pcap", NULL, NULL },
340 { "Wireshark/... - pcapng", OPEN_INFO_MAGIC, pcapng_open, "pcapng", NULL, NULL },
341 { "Sniffer (DOS)", OPEN_INFO_MAGIC, ngsniffer_open, NULL, NULL, NULL },
342 { "Snoop, Shomiti/Finisar Surveyor", OPEN_INFO_MAGIC, snoop_open, NULL, NULL, NULL },
343 { "AIX iptrace", OPEN_INFO_MAGIC, iptrace_open, NULL, NULL, NULL },
344 { "Microsoft Network Monitor", OPEN_INFO_MAGIC, netmon_open, NULL, NULL, NULL },
345 { "Cinco NetXray/Sniffer (Windows)", OPEN_INFO_MAGIC, netxray_open, NULL, NULL, NULL },
346 { "RADCOM WAN/LAN analyzer", OPEN_INFO_MAGIC, radcom_open, NULL, NULL, NULL },
347 { "HP-UX nettl trace", OPEN_INFO_MAGIC, nettl_open, NULL, NULL, NULL },
348 { "Visual Networks traffic capture", OPEN_INFO_MAGIC, visual_open, NULL, NULL, NULL },
349 { "InfoVista 5View capture", OPEN_INFO_MAGIC, _5views_open, NULL, NULL, NULL },
350 { "Network Instruments Observer", OPEN_INFO_MAGIC, network_instruments_open, NULL, NULL, NULL },
351 { "Savvius tagged", OPEN_INFO_MAGIC, peektagged_open, NULL, NULL, NULL },
352 { "Colasoft Capsa", OPEN_INFO_MAGIC, capsa_open, NULL, NULL, NULL },
353 { "DBS Etherwatch (VMS)", OPEN_INFO_MAGIC, dbs_etherwatch_open, NULL, NULL, NULL },
354 { "Tektronix K12xx 32-bit .rf5 format", OPEN_INFO_MAGIC, k12_open, NULL, NULL, NULL },
355 { "Catapult DCT2000 trace (.out format)", OPEN_INFO_MAGIC, catapult_dct2000_open, NULL, NULL, NULL },
356 { "Aethra .aps file", OPEN_INFO_MAGIC, aethra_open, NULL, NULL, NULL },
357 { "Symbian OS btsnoop", OPEN_INFO_MAGIC, btsnoop_open, "log", NULL, NULL },
358 { "EyeSDN USB S0/E1 ISDN trace format", OPEN_INFO_MAGIC, eyesdn_open, NULL, NULL, NULL },
359 { "Transport-Neutral Encapsulation Format", OPEN_INFO_MAGIC, tnef_open, NULL, NULL, NULL },
360 /* 3GPP TS 32.423 Trace must come before MIME Files as it's XML based*/
361 { "3GPP TS 32.423 Trace format", OPEN_INFO_MAGIC, nettrace_3gpp_32_423_file_open, NULL, NULL, NULL },
362 /* Gammu DCT3 trace must come before MIME files as it's XML based*/
363 { "Gammu DCT3 trace", OPEN_INFO_MAGIC, dct3trace_open, NULL, NULL, NULL },
364 { "MIME Files Format", OPEN_INFO_MAGIC, mime_file_open, NULL, NULL, NULL },
365 { "Micropross mplog", OPEN_INFO_MAGIC, mplog_open, "mplog", NULL, NULL },
366 { "Novell LANalyzer", OPEN_INFO_HEURISTIC, lanalyzer_open, "tr1", NULL, NULL },
368 * PacketLogger must come before MPEG, because its files
369 * are sometimes grabbed by mpeg_open.
371 { "macOS PacketLogger", OPEN_INFO_HEURISTIC, packetlogger_open, "pklg", NULL, NULL },
372 /* Some MPEG files have magic numbers, others just have heuristics. */
373 { "MPEG", OPEN_INFO_HEURISTIC, mpeg_open, "mpg;mp3", NULL, NULL },
374 { "Daintree SNA", OPEN_INFO_HEURISTIC, daintree_sna_open, "dcf", NULL, NULL },
375 { "STANAG 4607 Format", OPEN_INFO_HEURISTIC, stanag4607_open, NULL, NULL, NULL },
376 { "ASN.1 Basic Encoding Rules", OPEN_INFO_HEURISTIC, ber_open, NULL, NULL, NULL },
378 * I put NetScreen *before* erf, because there were some
379 * false positives with my test-files (Sake Blok, July 2007)
381 * I put VWR *after* ERF, because there were some cases where
382 * ERF files were misidentified as vwr files (Stephen
383 * Donnelly, August 2013; see bug 9054)
385 * I put VWR *after* Peek Classic, CommView, iSeries text,
386 * Toshiba text, K12 text, VMS tcpiptrace text, and NetScaler,
387 * because there were some cases where files of those types were
388 * misidentified as vwr files (Guy Harris, December 2013)
390 { "NetScreen snoop text file", OPEN_INFO_HEURISTIC, netscreen_open, "txt", NULL, NULL },
391 { "Endace ERF capture", OPEN_INFO_HEURISTIC, erf_open, "erf", NULL, NULL },
392 { "IPFIX File Format", OPEN_INFO_HEURISTIC, ipfix_open, "pfx;ipfix",NULL, NULL },
393 { "K12 text file", OPEN_INFO_HEURISTIC, k12text_open, "txt", NULL, NULL },
394 { "Savvius classic", OPEN_INFO_HEURISTIC, peekclassic_open, "pkt;tpc;apc;wpz", NULL, NULL },
395 { "pppd log (pppdump format)", OPEN_INFO_HEURISTIC, pppdump_open, NULL, NULL, NULL },
396 { "IBM iSeries comm. trace", OPEN_INFO_HEURISTIC, iseries_open, "txt", NULL, NULL },
397 { "I4B ISDN trace", OPEN_INFO_HEURISTIC, i4btrace_open, NULL, NULL, NULL },
398 { "MPEG2 transport stream", OPEN_INFO_HEURISTIC, mp2t_open, "ts;mpg", NULL, NULL },
399 { "CSIDS IPLog", OPEN_INFO_HEURISTIC, csids_open, NULL, NULL, NULL },
400 { "TCPIPtrace (VMS)", OPEN_INFO_HEURISTIC, vms_open, "txt", NULL, NULL },
401 { "CoSine IPSX L2 capture", OPEN_INFO_HEURISTIC, cosine_open, "txt", NULL, NULL },
402 { "Bluetooth HCI dump", OPEN_INFO_HEURISTIC, hcidump_open, NULL, NULL, NULL },
403 { "TamoSoft CommView", OPEN_INFO_HEURISTIC, commview_open, "ncf", NULL, NULL },
404 { "NetScaler", OPEN_INFO_HEURISTIC, nstrace_open, "cap", NULL, NULL },
405 { "Android Logcat Binary format", OPEN_INFO_HEURISTIC, logcat_open, "logcat", NULL, NULL },
406 { "Android Logcat Text formats", OPEN_INFO_HEURISTIC, logcat_text_open, "txt", NULL, NULL },
407 /* ASCII trace files from Telnet sessions. */
408 { "Lucent/Ascend access server trace", OPEN_INFO_HEURISTIC, ascend_open, "txt", NULL, NULL },
409 { "Toshiba Compact ISDN Router snoop", OPEN_INFO_HEURISTIC, toshiba_open, "txt", NULL, NULL },
410 /* Extremely weak heuristics - put them at the end. */
411 { "Ixia IxVeriWave .vwr Raw Capture", OPEN_INFO_HEURISTIC, vwr_open, "vwr", NULL, NULL },
412 { "CAM Inspector file", OPEN_INFO_HEURISTIC, camins_open, "camins", NULL, NULL },
413 { "JavaScript Object Notation", OPEN_INFO_HEURISTIC, json_open, "json", NULL, NULL }
416 /* this is only used to build the dynamic array on load, do NOT use this
417 * for anything else, because the size of the actual array will change if
418 * Lua scripts register a new file reader.
420 #define N_OPEN_INFO_ROUTINES ((sizeof open_info_base / sizeof open_info_base[0]))
422 static GArray *open_info_arr = NULL;
424 /* this always points to the top of the created array */
425 struct open_info *open_routines = NULL;
427 /* this points to the first OPEN_INFO_HEURISTIC type in the array */
428 static guint heuristic_open_routine_idx = 0;
431 set_heuristic_routine(void)
434 g_assert(open_info_arr != NULL);
436 for (i = 0; i < open_info_arr->len; i++) {
437 if (open_routines[i].type == OPEN_INFO_HEURISTIC) {
438 heuristic_open_routine_idx = i;
442 g_assert(open_routines[i].type == OPEN_INFO_MAGIC);
445 g_assert(heuristic_open_routine_idx > 0);
449 init_open_routines(void)
452 struct open_info *i_open;
457 open_info_arr = g_array_new(TRUE,TRUE,sizeof(struct open_info));
459 g_array_append_vals(open_info_arr, open_info_base, N_OPEN_INFO_ROUTINES);
461 open_routines = (struct open_info *)(void*) open_info_arr->data;
463 /* Populate the extensions_set list now */
464 for (i = 0, i_open = open_routines; i < open_info_arr->len; i++, i_open++) {
465 if (i_open->extensions != NULL)
466 i_open->extensions_set = g_strsplit(i_open->extensions, ";", 0);
469 set_heuristic_routine();
473 * Registers a new file reader - currently only called by wslua code for Lua readers.
474 * If first_routine is true, it's added before other readers of its type (magic or heuristic).
475 * Also, it checks for an existing reader of the same name and errors if it finds one; if
476 * you want to handle that condition more gracefully, call wtap_has_open_info() first.
479 wtap_register_open_info(struct open_info *oi, const gboolean first_routine)
481 if (!oi || !oi->name) {
482 g_error("No open_info name given to register");
486 /* verify name doesn't already exist */
487 if (wtap_has_open_info(oi->name)) {
488 g_error("Name given to register_open_info already exists");
492 if (oi->extensions != NULL)
493 oi->extensions_set = g_strsplit(oi->extensions, ";", 0);
495 /* if it's magic and first, prepend it; if it's heuristic and not first,
496 append it; if it's anything else, stick it in the middle */
497 if (first_routine && oi->type == OPEN_INFO_MAGIC) {
498 g_array_prepend_val(open_info_arr, *oi);
499 } else if (!first_routine && oi->type == OPEN_INFO_HEURISTIC) {
500 g_array_append_val(open_info_arr, *oi);
502 g_array_insert_val(open_info_arr, heuristic_open_routine_idx, *oi);
505 open_routines = (struct open_info *)(void*) open_info_arr->data;
506 set_heuristic_routine();
509 /* De-registers a file reader by removign it from the GArray based on its name.
510 * This function must NOT be called during wtap_open_offline(), since it changes the array.
511 * Note: this function will error if it doesn't find the given name; if you want to handle
512 * that condition more gracefully, call wtap_has_open_info() first.
515 wtap_deregister_open_info(const gchar *name)
520 g_error("Missing open_info name to de-register");
524 for (i = 0; i < open_info_arr->len; i++) {
525 if (open_routines[i].name && strcmp(open_routines[i].name, name) == 0) {
526 if (open_routines[i].extensions_set != NULL)
527 g_strfreev(open_routines[i].extensions_set);
528 open_info_arr = g_array_remove_index(open_info_arr, i);
529 set_heuristic_routine();
534 g_error("deregister_open_info: name not found");
537 /* Determines if a open routine short name already exists
540 wtap_has_open_info(const gchar *name)
545 g_error("No name given to wtap_has_open_info!");
550 for (i = 0; i < open_info_arr->len; i++) {
551 if (open_routines[i].name && strcmp(open_routines[i].name, name) == 0) {
560 * Visual C++ on Win32 systems doesn't define these. (Old UNIX systems don't
561 * define them either.)
563 * Visual C++ on Win32 systems doesn't define S_IFIFO, it defines _S_IFIFO.
566 #define S_ISREG(mode) (((mode) & S_IFMT) == S_IFREG)
569 #define S_IFIFO _S_IFIFO
572 #define S_ISFIFO(mode) (((mode) & S_IFMT) == S_IFIFO)
575 #define S_ISDIR(mode) (((mode) & S_IFMT) == S_IFDIR)
578 /* returns the 'type' number to use for wtap_open_offline based on the
579 passed-in name (the name in the open_info struct). It returns WTAP_TYPE_AUTO
580 on failure, which is the number 0. The 'type' number is the entry's index+1,
581 because that's what wtap_open_offline() expects it to be. */
583 open_info_name_to_type(const char *name)
588 return WTAP_TYPE_AUTO;
590 for (i = 0; i < open_info_arr->len; i++) {
591 if (open_routines[i].name != NULL &&
592 strcmp(name, open_routines[i].name) == 0)
596 return WTAP_TYPE_AUTO; /* no such file type */
600 get_file_extension(const char *pathname)
605 const char **compressed_file_extensionp;
609 * Is the pathname empty?
611 if (strcmp(pathname, "") == 0)
612 return NULL; /* no extension */
615 * Find the last component of the pathname.
617 filename = g_path_get_basename(pathname);
620 * Does it have an extension?
622 if (strchr(filename, '.') == NULL) {
624 return NULL; /* no extension whatsoever */
628 * Yes. Split it into components separated by ".".
630 components = g_strsplit(filename, ".", 0);
634 * Count the components.
636 for (ncomponents = 0; components[ncomponents] != NULL; ncomponents++)
639 if (ncomponents == 0) {
640 g_strfreev(components);
641 return NULL; /* no components */
643 if (ncomponents == 1) {
644 g_strfreev(components);
645 return NULL; /* only one component, with no "." */
649 * Is the last component one of the extensions used for compressed
652 extensionp = components[ncomponents - 1];
653 for (compressed_file_extensionp = compressed_file_extension_table;
654 *compressed_file_extensionp != NULL;
655 compressed_file_extensionp++) {
656 if (strcmp(extensionp, *compressed_file_extensionp) == 0) {
658 * Yes, it's one of the compressed-file extensions.
659 * Is there an extension before that?
661 if (ncomponents == 2) {
662 g_strfreev(components);
663 return NULL; /* no, only two components */
667 * Yes, return that extension.
669 extensionp = g_strdup(components[ncomponents - 2]);
670 g_strfreev(components);
676 * The extension isn't one of the compressed-file extensions;
679 extensionp = g_strdup(extensionp);
680 g_strfreev(components);
685 * Check if file extension is used in this heuristic
688 heuristic_uses_extension(unsigned int i, const char *extension)
693 * Does this file type *have* any extensions?
695 if (open_routines[i].extensions == NULL)
696 return FALSE; /* no */
699 * Check each of them against the specified extension.
701 for (extensionp = open_routines[i].extensions_set; *extensionp != NULL;
703 if (strcmp(extension, *extensionp) == 0) {
704 return TRUE; /* it's one of them */
708 return FALSE; /* it's not one of them */
711 /* Opens a file and prepares a wtap struct.
712 If "do_random" is TRUE, it opens the file twice; the second open
713 allows the application to do random-access I/O without moving
714 the seek offset for sequential I/O, which is used by Wireshark
715 so that it can do sequential I/O to a capture file that's being
716 written to as new packets arrive independently of random I/O done
717 to display protocol trees for packets when they're selected. */
719 wtap_open_offline(const char *filename, unsigned int type, int *err, char **err_info,
726 gboolean use_stdin = FALSE;
733 /* open standard input if filename is '-' */
734 if (strcmp(filename, "-") == 0)
737 /* First, make sure the file is valid */
739 if (ws_fstat64(0, &statb) < 0) {
744 if (ws_stat64(filename, &statb) < 0) {
749 if (S_ISFIFO(statb.st_mode)) {
751 * Opens of FIFOs are allowed only when not opening
754 * Currently, we do seeking when trying to find out
755 * the file type, but our I/O routines do some amount
756 * of buffering, and do backward seeks within the buffer
757 * if possible, so at least some file types can be
758 * opened from pipes, so we don't completely disallow opens
762 *err = WTAP_ERR_RANDOM_OPEN_PIPE;
765 } else if (S_ISDIR(statb.st_mode)) {
767 * Return different errors for "this is a directory"
768 * and "this is some random special file type", so
769 * the user can get a potentially more helpful error.
773 } else if (! S_ISREG(statb.st_mode)) {
774 *err = WTAP_ERR_NOT_REGULAR_FILE;
779 * We need two independent descriptors for random access, so
780 * they have different file positions. If we're opening the
781 * standard input, we can only dup it to get additional
782 * descriptors, so we can't have two independent descriptors,
783 * and thus can't do random access.
785 if (use_stdin && do_random) {
786 *err = WTAP_ERR_RANDOM_OPEN_STDIN;
791 wth = (wtap *)g_malloc0(sizeof(wtap));
794 errno = WTAP_ERR_CANT_OPEN;
797 * We dup FD 0, so that we don't have to worry about
798 * a file_close of wth->fh closing the standard
799 * input of the process.
808 if (_setmode(fd, O_BINARY) == -1) {
809 /* "Shouldn't happen" */
815 if (!(wth->fh = file_fdopen(fd))) {
822 if (!(wth->fh = file_open(filename))) {
830 if (!(wth->random_fh = file_open(filename))) {
837 wth->random_fh = NULL;
840 wth->file_encap = WTAP_ENCAP_UNKNOWN;
841 wth->subtype_sequential_close = NULL;
842 wth->subtype_close = NULL;
843 wth->file_tsprec = WTAP_TSPREC_USEC;
845 wth->wslua_data = NULL;
846 wth->shb_hdrs = g_array_new(FALSE, FALSE, sizeof(wtap_block_t));
847 shb = wtap_block_create(WTAP_BLOCK_NG_SECTION);
849 g_array_append_val(wth->shb_hdrs, shb);
851 /* Initialize the array containing a list of interfaces. pcapng_open and
852 * erf_open needs this (and libpcap_open for ERF encapsulation types).
853 * Always initing it here saves checking for a NULL ptr later. */
854 wth->interface_data = g_array_new(FALSE, FALSE, sizeof(wtap_block_t));
856 if (wth->random_fh) {
857 wth->fast_seek = g_ptr_array_new();
859 file_set_random_access(wth->fh, FALSE, wth->fast_seek);
860 file_set_random_access(wth->random_fh, TRUE, wth->fast_seek);
863 /* 'type' is 1 greater than the array index */
864 if (type != WTAP_TYPE_AUTO && type <= open_info_arr->len) {
867 if (file_seek(wth->fh, 0, SEEK_SET, err) == -1) {
868 /* I/O error - give up */
873 /* Set wth with wslua data if any - this is how we pass the data
874 * to the file reader, kinda like the priv member but not free'd later.
875 * It's ok for this to copy a NULL.
877 wth->wslua_data = open_routines[type - 1].wslua_data;
879 result = (*open_routines[type - 1].open_routine)(wth, err, err_info);
882 case WTAP_OPEN_ERROR:
883 /* Error - give up */
887 case WTAP_OPEN_NOT_MINE:
888 /* No error, but not that type of file */
892 /* We found the file type */
897 /* Try all file types that support magic numbers */
898 for (i = 0; i < heuristic_open_routine_idx; i++) {
899 /* Seek back to the beginning of the file; the open routine
900 for the previous file type may have left the file
901 position somewhere other than the beginning, and the
902 open routine for this file type will probably want
903 to start reading at the beginning.
905 Initialize the data offset while we're at it. */
906 if (file_seek(wth->fh, 0, SEEK_SET, err) == -1) {
907 /* Error - give up */
912 /* Set wth with wslua data if any - this is how we pass the data
913 * to the file reader, kinda like the priv member but not free'd later.
914 * It's ok for this to copy a NULL.
916 wth->wslua_data = open_routines[i].wslua_data;
918 switch ((*open_routines[i].open_routine)(wth, err, err_info)) {
920 case WTAP_OPEN_ERROR:
921 /* Error - give up */
925 case WTAP_OPEN_NOT_MINE:
926 /* No error, but not that type of file */
930 /* We found the file type */
936 /* Does this file's name have an extension? */
937 extension = get_file_extension(filename);
938 if (extension != NULL) {
939 /* Yes - try the heuristic types that use that extension first. */
940 for (i = heuristic_open_routine_idx; i < open_info_arr->len; i++) {
941 /* Does this type use that extension? */
942 if (heuristic_uses_extension(i, extension)) {
944 if (file_seek(wth->fh, 0, SEEK_SET, err) == -1) {
945 /* Error - give up */
951 /* Set wth with wslua data if any - this is how we pass the data
952 * to the file reader, kind of like priv but not free'd later.
954 wth->wslua_data = open_routines[i].wslua_data;
956 switch ((*open_routines[i].open_routine)(wth,
959 case WTAP_OPEN_ERROR:
960 /* Error - give up */
965 case WTAP_OPEN_NOT_MINE:
966 /* No error, but not that type of file */
970 /* We found the file type */
978 * Now try the heuristic types that have no extensions
979 * to check; we try those before the ones that have
980 * extensions that *don't* match this file's extension,
981 * on the theory that files of those types generally
982 * have one of the type's extensions, and, as this file
983 * *doesn't* have one of those extensions, it's probably
984 * *not* one of those files.
986 for (i = heuristic_open_routine_idx; i < open_info_arr->len; i++) {
987 /* Does this type have any extensions? */
988 if (open_routines[i].extensions == NULL) {
990 if (file_seek(wth->fh, 0, SEEK_SET, err) == -1) {
991 /* Error - give up */
997 /* Set wth with wslua data if any - this is how we pass the data
998 * to the file reader, kind of like priv but not free'd later.
1000 wth->wslua_data = open_routines[i].wslua_data;
1002 switch ((*open_routines[i].open_routine)(wth,
1005 case WTAP_OPEN_ERROR:
1006 /* Error - give up */
1011 case WTAP_OPEN_NOT_MINE:
1012 /* No error, but not that type of file */
1015 case WTAP_OPEN_MINE:
1016 /* We found the file type */
1024 * Now try the ones that have extensions where none of
1025 * them matches this file's extensions.
1027 for (i = heuristic_open_routine_idx; i < open_info_arr->len; i++) {
1029 * Does this type have extensions and is this file's
1030 * extension one of them?
1032 if (open_routines[i].extensions != NULL &&
1033 !heuristic_uses_extension(i, extension)) {
1035 if (file_seek(wth->fh, 0, SEEK_SET, err) == -1) {
1036 /* Error - give up */
1042 /* Set wth with wslua data if any - this is how we pass the data
1043 * to the file reader, kind of like priv but not free'd later.
1045 wth->wslua_data = open_routines[i].wslua_data;
1047 switch ((*open_routines[i].open_routine)(wth,
1050 case WTAP_OPEN_ERROR:
1051 /* Error - give up */
1056 case WTAP_OPEN_NOT_MINE:
1057 /* No error, but not that type of file */
1060 case WTAP_OPEN_MINE:
1061 /* We found the file type */
1069 /* No - try all the heuristics types in order. */
1070 for (i = heuristic_open_routine_idx; i < open_info_arr->len; i++) {
1072 if (file_seek(wth->fh, 0, SEEK_SET, err) == -1) {
1073 /* Error - give up */
1078 /* Set wth with wslua data if any - this is how we pass the data
1079 * to the file reader, kind of like priv but not free'd later.
1081 wth->wslua_data = open_routines[i].wslua_data;
1083 switch ((*open_routines[i].open_routine)(wth, err, err_info)) {
1085 case WTAP_OPEN_ERROR:
1086 /* Error - give up */
1090 case WTAP_OPEN_NOT_MINE:
1091 /* No error, but not that type of file */
1094 case WTAP_OPEN_MINE:
1095 /* We found the file type */
1103 /* Well, it's not one of the types of file we know about. */
1105 *err = WTAP_ERR_FILE_UNKNOWN_FORMAT;
1109 wth->frame_buffer = (struct Buffer *)g_malloc(sizeof(struct Buffer));
1110 ws_buffer_init(wth->frame_buffer, 1500);
1112 if ((wth->file_type_subtype == WTAP_FILE_TYPE_SUBTYPE_PCAP) ||
1113 (wth->file_type_subtype == WTAP_FILE_TYPE_SUBTYPE_PCAP_NSEC)) {
1115 wtap_block_t descr = wtap_block_create(WTAP_BLOCK_IF_DESCR);
1116 wtapng_if_descr_mandatory_t* descr_mand = (wtapng_if_descr_mandatory_t*)wtap_block_get_mandatory_data(descr);
1118 descr_mand->wtap_encap = wth->file_encap;
1119 if (wth->file_type_subtype == WTAP_FILE_TYPE_SUBTYPE_PCAP_NSEC) {
1120 descr_mand->time_units_per_second = 1000000000; /* nanosecond resolution */
1121 wtap_block_add_uint8_option(descr, OPT_IDB_TSRESOL, 9);
1122 descr_mand->tsprecision = WTAP_TSPREC_NSEC;
1124 descr_mand->time_units_per_second = 1000000; /* default microsecond resolution */
1125 /* No need to add an option, this is the default */
1126 descr_mand->tsprecision = WTAP_TSPREC_USEC;
1128 descr_mand->snap_len = wth->snapshot_length;
1130 descr_mand->num_stat_entries = 0; /* Number of ISB:s */
1131 descr_mand->interface_statistics = NULL;
1132 g_array_append_val(wth->interface_data, descr);
1139 * Given the pathname of the file we just closed with wtap_fdclose(), attempt
1140 * to reopen that file and assign the new file descriptor(s) to the sequential
1141 * stream and, if do_random is TRUE, to the random stream. Used on Windows
1142 * after the rename of a file we had open was done or if the rename of a
1143 * file on top of a file we had open failed.
1145 * This is only required by Wireshark, not TShark, and, at the point that
1146 * Wireshark is doing this, the sequential stream is closed, and the
1147 * random stream is open, so this refuses to open pipes, and only
1148 * reopens the random stream.
1151 wtap_fdreopen(wtap *wth, const char *filename, int *err)
1156 * We need two independent descriptors for random access, so
1157 * they have different file positions. If we're opening the
1158 * standard input, we can only dup it to get additional
1159 * descriptors, so we can't have two independent descriptors,
1160 * and thus can't do random access.
1162 if (strcmp(filename, "-") == 0) {
1163 *err = WTAP_ERR_RANDOM_OPEN_STDIN;
1167 /* First, make sure the file is valid */
1168 if (ws_stat64(filename, &statb) < 0) {
1172 if (S_ISFIFO(statb.st_mode)) {
1174 * Opens of FIFOs are not allowed; see above.
1176 *err = WTAP_ERR_RANDOM_OPEN_PIPE;
1178 } else if (S_ISDIR(statb.st_mode)) {
1180 * Return different errors for "this is a directory"
1181 * and "this is some random special file type", so
1182 * the user can get a potentially more helpful error.
1186 } else if (! S_ISREG(statb.st_mode)) {
1187 *err = WTAP_ERR_NOT_REGULAR_FILE;
1192 errno = WTAP_ERR_CANT_OPEN;
1193 if (!file_fdreopen(wth->random_fh, filename)) {
1200 /* Table of the file types and subtypes for which we have built-in support.
1201 Entries must be sorted by WTAP_FILE_TYPE_SUBTYPE_xxx values in ascending
1204 These are used to report what type and subtype a given file is and
1205 to let the user select a format when writing out packets.
1207 This table is what we start with, but it can be modified.
1208 If we need to modify it, we allocate a GArray, copy the entries
1209 in the above table to that GArray, use the copy as the table, and
1210 make all changes to the copy. */
1211 static const struct file_type_subtype_info dump_open_table_base[] = {
1212 /* WTAP_FILE_TYPE_SUBTYPE_UNKNOWN (only used internally for initialization) */
1213 { NULL, NULL, NULL, NULL,
1217 /* WTAP_FILE_TYPE_SUBTYPE_PCAP */
1218 /* Gianluca Varenni suggests that we add "deprecated" to the description. */
1219 { "Wireshark/tcpdump/... - pcap", "pcap", "pcap", "cap;dmp",
1221 libpcap_dump_can_write_encap, libpcap_dump_open, NULL },
1223 /* WTAP_FILE_TYPE_SUBTYPE_PCAPNG */
1224 { "Wireshark/... - pcapng", "pcapng", "pcapng", "ntar",
1225 FALSE, TRUE, WTAP_COMMENT_PER_SECTION|WTAP_COMMENT_PER_INTERFACE|WTAP_COMMENT_PER_PACKET,
1226 pcapng_dump_can_write_encap, pcapng_dump_open, NULL },
1228 /* WTAP_FILE_TYPE_SUBTYPE_PCAP_NSEC */
1229 { "Wireshark/tcpdump/... - nanosecond pcap", "nsecpcap", "pcap", "cap;dmp",
1231 libpcap_dump_can_write_encap, libpcap_dump_open, NULL },
1233 /* WTAP_FILE_TYPE_SUBTYPE_PCAP_AIX */
1234 { "AIX tcpdump - pcap", "aixpcap", "pcap", "cap;dmp",
1238 /* WTAP_FILE_TYPE_SUBTYPE_PCAP_SS991029 */
1239 { "Modified tcpdump - pcap", "modpcap", "pcap", "cap;dmp",
1241 libpcap_dump_can_write_encap, libpcap_dump_open, NULL },
1243 /* WTAP_FILE_TYPE_SUBTYPE_PCAP_NOKIA */
1244 { "Nokia tcpdump - pcap ", "nokiapcap", "pcap", "cap;dmp",
1246 libpcap_dump_can_write_encap, libpcap_dump_open, NULL },
1248 /* WTAP_FILE_TYPE_SUBTYPE_PCAP_SS990417 */
1249 { "RedHat 6.1 tcpdump - pcap", "rh6_1pcap", "pcap", "cap;dmp",
1251 libpcap_dump_can_write_encap, libpcap_dump_open, NULL },
1253 /* WTAP_FILE_TYPE_SUBTYPE_PCAP_SS990915 */
1254 { "SuSE 6.3 tcpdump - pcap", "suse6_3pcap", "pcap", "cap;dmp",
1256 libpcap_dump_can_write_encap, libpcap_dump_open, NULL },
1258 /* WTAP_FILE_TYPE_SUBTYPE_5VIEWS */
1259 { "InfoVista 5View capture", "5views", "5vw", NULL,
1261 _5views_dump_can_write_encap, _5views_dump_open, NULL },
1263 /* WTAP_FILE_TYPE_SUBTYPE_IPTRACE_1_0 */
1264 { "AIX iptrace 1.0", "iptrace_1", NULL, NULL,
1268 /* WTAP_FILE_TYPE_SUBTYPE_IPTRACE_2_0 */
1269 { "AIX iptrace 2.0", "iptrace_2", NULL, NULL,
1273 /* WTAP_FILE_TYPE_SUBTYPE_BER */
1274 { "ASN.1 Basic Encoding Rules", "ber", NULL, NULL,
1278 /* WTAP_FILE_TYPE_SUBTYPE_HCIDUMP */
1279 { "Bluetooth HCI dump", "hcidump", NULL, NULL,
1283 /* WTAP_FILE_TYPE_SUBTYPE_CATAPULT_DCT2000 */
1284 { "Catapult DCT2000 trace (.out format)", "dct2000", "out", NULL,
1286 catapult_dct2000_dump_can_write_encap, catapult_dct2000_dump_open, NULL },
1288 /* WTAP_FILE_TYPE_SUBTYPE_NETXRAY_OLD */
1289 { "Cinco Networks NetXRay 1.x", "netxray1", "cap", NULL,
1293 /* WTAP_FILE_TYPE_SUBTYPE_NETXRAY_1_0 */
1294 { "Cinco Networks NetXRay 2.0 or later", "netxray2", "cap", NULL,
1298 /* WTAP_FILE_TYPE_SUBTYPE_COSINE */
1299 { "CoSine IPSX L2 capture", "cosine", "txt", NULL,
1303 /* WTAP_FILE_TYPE_SUBTYPE_CSIDS */
1304 { "CSIDS IPLog", "csids", NULL, NULL,
1308 /* WTAP_FILE_TYPE_SUBTYPE_DBS_ETHERWATCH */
1309 { "DBS Etherwatch (VMS)", "etherwatch", "txt", NULL,
1313 /* WTAP_FILE_TYPE_SUBTYPE_ERF */
1314 { "Endace ERF capture", "erf", "erf", NULL,
1316 erf_dump_can_write_encap, erf_dump_open, NULL },
1318 /* WTAP_FILE_TYPE_SUBTYPE_EYESDN */
1319 { "EyeSDN USB S0/E1 ISDN trace format", "eyesdn", "trc", NULL,
1321 eyesdn_dump_can_write_encap, eyesdn_dump_open, NULL },
1323 /* WTAP_FILE_TYPE_SUBTYPE_NETTL */
1324 { "HP-UX nettl trace", "nettl", "trc0", "trc1",
1326 nettl_dump_can_write_encap, nettl_dump_open, NULL },
1328 /* WTAP_FILE_TYPE_SUBTYPE_ISERIES */
1329 { "IBM iSeries comm. trace (ASCII)", "iseries_ascii", "txt", NULL,
1333 /* WTAP_FILE_TYPE_SUBTYPE_ISERIES_UNICODE */
1334 { "IBM iSeries comm. trace (UNICODE)", "iseries_unicode", "txt", NULL,
1338 /* WTAP_FILE_TYPE_SUBTYPE_I4BTRACE */
1339 { "I4B ISDN trace", "i4btrace", NULL, NULL,
1343 /* WTAP_FILE_TYPE_SUBTYPE_ASCEND */
1344 { "Lucent/Ascend access server trace", "ascend", "txt", NULL,
1348 /* WTAP_FILE_TYPE_SUBTYPE_NETMON_1_x */
1349 { "Microsoft NetMon 1.x", "netmon1", "cap", NULL,
1351 netmon_dump_can_write_encap_1_x, netmon_dump_open, NULL },
1353 /* WTAP_FILE_TYPE_SUBTYPE_NETMON_2_x */
1354 { "Microsoft NetMon 2.x", "netmon2", "cap", NULL,
1356 netmon_dump_can_write_encap_2_x, netmon_dump_open, NULL },
1358 /* WTAP_FILE_TYPE_SUBTYPE_NGSNIFFER_UNCOMPRESSED */
1359 { "Sniffer (DOS)", "ngsniffer", "cap", "enc;trc;fdc;syc",
1361 ngsniffer_dump_can_write_encap, ngsniffer_dump_open, NULL },
1363 /* WTAP_FILE_TYPE_SUBTYPE_NGSNIFFER_COMPRESSED */
1364 { "Sniffer (DOS), compressed", "ngsniffer_comp", "cap", "enc;trc;fdc;syc",
1368 /* WTAP_FILE_TYPE_SUBTYPE_NETXRAY_1_1 */
1369 { "NetXray, Sniffer (Windows) 1.1", "ngwsniffer_1_1", "cap", NULL,
1371 netxray_dump_can_write_encap_1_1, netxray_dump_open_1_1, NULL },
1373 /* WTAP_FILE_TYPE_SUBTYPE_NETXRAY_2_00x */
1374 { "Sniffer (Windows) 2.00x", "ngwsniffer_2_0", "cap", "caz",
1376 netxray_dump_can_write_encap_2_0, netxray_dump_open_2_0, NULL },
1378 /* WTAP_FILE_TYPE_SUBTYPE_NETWORK_INSTRUMENTS */
1379 { "Network Instruments Observer", "niobserver", "bfr", NULL,
1381 network_instruments_dump_can_write_encap, network_instruments_dump_open, NULL },
1383 /* WTAP_FILE_TYPE_SUBTYPE_LANALYZER */
1384 { "Novell LANalyzer","lanalyzer", "tr1", NULL,
1386 lanalyzer_dump_can_write_encap, lanalyzer_dump_open, NULL },
1388 /* WTAP_FILE_TYPE_SUBTYPE_PPPDUMP */
1389 { "pppd log (pppdump format)", "pppd", NULL, NULL,
1393 /* WTAP_FILE_TYPE_SUBTYPE_RADCOM */
1394 { "RADCOM WAN/LAN analyzer", "radcom", NULL, NULL,
1398 /* WTAP_FILE_TYPE_SUBTYPE_SNOOP */
1399 { "Sun snoop", "snoop", "snoop", "cap",
1401 snoop_dump_can_write_encap, snoop_dump_open, NULL },
1403 /* WTAP_FILE_TYPE_SUBTYPE_SHOMITI */
1404 { "Shomiti/Finisar Surveyor", "shomiti", "cap", NULL,
1408 /* WTAP_FILE_TYPE_SUBTYPE_VMS */
1409 { "TCPIPtrace (VMS)", "tcpiptrace", "txt", NULL,
1413 /* WTAP_FILE_TYPE_SUBTYPE_K12 */
1414 { "Tektronix K12xx 32-bit .rf5 format", "rf5", "rf5", NULL,
1416 k12_dump_can_write_encap, k12_dump_open, NULL },
1418 /* WTAP_FILE_TYPE_SUBTYPE_TOSHIBA */
1419 { "Toshiba Compact ISDN Router snoop", "toshiba", "txt", NULL,
1423 /* WTAP_FILE_TYPE_SUBTYPE_VISUAL_NETWORKS */
1424 { "Visual Networks traffic capture", "visual", NULL, NULL,
1426 visual_dump_can_write_encap, visual_dump_open, NULL },
1428 /* WTAP_FILE_TYPE_SUBTYPE_PEEKCLASSIC_V56 */
1429 { "Savvius classic (V5 and V6)", "peekclassic56", "pkt", "tpc;apc;wpz",
1433 /* WTAP_FILE_TYPE_SUBTYPE_PEEKCLASSIC_V7 */
1434 { "Savvius classic (V7)", "peekclassic7", "pkt", "tpc;apc;wpz",
1438 /* WTAP_FILE_TYPE_SUBTYPE_PEEKTAGGED */
1439 { "Savvius tagged", "peektagged", "pkt", "tpc;apc;wpz",
1443 /* WTAP_FILE_TYPE_SUBTYPE_MPEG */
1444 { "MPEG", "mpeg", "mpeg", "mpg;mp3",
1448 /* WTAP_FILE_TYPE_SUBTYPE_K12TEXT */
1449 { "K12 text file", "k12text", "txt", NULL,
1451 k12text_dump_can_write_encap, k12text_dump_open, NULL },
1453 /* WTAP_FILE_TYPE_SUBTYPE_NETSCREEN */
1454 { "NetScreen snoop text file", "netscreen", "txt", NULL,
1458 /* WTAP_FILE_TYPE_SUBTYPE_COMMVIEW */
1459 { "TamoSoft CommView", "commview", "ncf", NULL,
1461 commview_dump_can_write_encap, commview_dump_open, NULL },
1463 /* WTAP_FILE_TYPE_SUBTYPE_BTSNOOP */
1464 { "Symbian OS btsnoop", "btsnoop", "log", NULL,
1466 btsnoop_dump_can_write_encap, btsnoop_dump_open_h4, NULL },
1468 /* WTAP_FILE_TYPE_SUBTYPE_TNEF */
1469 { "Transport-Neutral Encapsulation Format", "tnef", NULL, NULL,
1473 /* WTAP_FILE_TYPE_SUBTYPE_DCT3TRACE */
1474 { "Gammu DCT3 trace", "dct3trace", "xml", NULL,
1478 /* WTAP_FILE_TYPE_SUBTYPE_PACKETLOGGER */
1479 { "macOS PacketLogger", "pklg", "pklg", NULL,
1483 /* WTAP_FILE_TYPE_SUBTYPE_DAINTREE_SNA */
1484 { "Daintree SNA", "dsna", "dcf", NULL,
1488 /* WTAP_FILE_TYPE_SUBTYPE_NETSCALER_1_0 */
1489 { "NetScaler Trace (Version 1.0)", "nstrace10", NULL, NULL,
1491 nstrace_10_dump_can_write_encap, nstrace_dump_open, NULL },
1493 /* WTAP_FILE_TYPE_SUBTYPE_NETSCALER_2_0 */
1494 { "NetScaler Trace (Version 2.0)", "nstrace20", "cap", NULL,
1496 nstrace_20_dump_can_write_encap, nstrace_dump_open, NULL },
1498 /* WTAP_FILE_TYPE_SUBTYPE_JPEG_JFIF */
1499 { "JPEG/JFIF", "jpeg", "jpg", "jpeg;jfif",
1503 /* WTAP_FILE_TYPE_SUBTYPE_IPFIX */
1504 { "IPFIX File Format", "ipfix", "pfx", "ipfix",
1508 /* WTAP_ENCAP_MIME */
1509 { "MIME File Format", "mime", NULL, NULL,
1513 /* WTAP_FILE_TYPE_SUBTYPE_AETHRA */
1514 { "Aethra .aps file", "aethra", "aps", NULL,
1518 /* WTAP_FILE_TYPE_SUBTYPE_MPEG_2_TS */
1519 { "MPEG2 transport stream", "mp2t", "mp2t", "ts;mpg",
1523 /* WTAP_FILE_TYPE_SUBTYPE_VWR_80211 */
1524 { "Ixia IxVeriWave .vwr Raw 802.11 Capture", "vwr80211", "vwr", NULL,
1528 /* WTAP_FILE_TYPE_SUBTYPE_VWR_ETH */
1529 { "Ixia IxVeriWave .vwr Raw Ethernet Capture", "vwreth", "vwr", NULL,
1533 /* WTAP_FILE_TYPE_SUBTYPE_CAMINS */
1534 { "CAM Inspector file", "camins", "camins", NULL,
1538 /* WTAP_FILE_TYPE_SUBTYPE_STANAG_4607 */
1539 { "STANAG 4607 Format", "stanag4607", NULL, NULL,
1543 /* WTAP_FILE_TYPE_SUBTYPE_NETSCALER_3_0 */
1544 { "NetScaler Trace (Version 3.0)", "nstrace30", "cap", NULL,
1546 nstrace_30_dump_can_write_encap, nstrace_dump_open, NULL },
1548 /* WTAP_FILE_TYPE_SUBTYPE_LOGCAT */
1549 { "Android Logcat Binary format", "logcat", "logcat", NULL,
1551 logcat_dump_can_write_encap, logcat_binary_dump_open, NULL },
1553 /* WTAP_FILE_TYPE_SUBTYPE_LOGCAT_BRIEF */
1554 { "Android Logcat Brief text format", "logcat-brief", NULL, NULL,
1556 logcat_text_brief_dump_can_write_encap, logcat_text_brief_dump_open, NULL },
1558 /* WTAP_FILE_TYPE_SUBTYPE_LOGCAT_PROCESS */
1559 { "Android Logcat Process text format", "logcat-process", NULL, NULL,
1561 logcat_text_process_dump_can_write_encap, logcat_text_process_dump_open, NULL },
1563 /* WTAP_FILE_TYPE_SUBTYPE_LOGCAT_TAG */
1564 { "Android Logcat Tag text format", "logcat-tag", NULL, NULL,
1566 logcat_text_tag_dump_can_write_encap, logcat_text_tag_dump_open, NULL },
1568 /* WTAP_FILE_TYPE_SUBTYPE_LOGCAT_THREAD */
1569 { "Android Logcat Thread text format", "logcat-thread", NULL, NULL,
1571 logcat_text_thread_dump_can_write_encap, logcat_text_thread_dump_open, NULL },
1573 /* WTAP_FILE_TYPE_SUBTYPE_LOGCAT_TIME */
1574 { "Android Logcat Time text format", "logcat-time", NULL, NULL,
1576 logcat_text_time_dump_can_write_encap, logcat_text_time_dump_open, NULL },
1578 /* WTAP_FILE_TYPE_SUBTYPE_LOGCAT_THREADTIME */
1579 { "Android Logcat Threadtime text format", "logcat-threadtime", NULL, NULL,
1581 logcat_text_threadtime_dump_can_write_encap, logcat_text_threadtime_dump_open, NULL },
1583 /* WTAP_FILE_TYPE_SUBTYPE_LOGCAT_LONG */
1584 { "Android Logcat Long text format", "logcat-long", NULL, NULL,
1586 logcat_text_long_dump_can_write_encap, logcat_text_long_dump_open, NULL },
1588 /* WTAP_FILE_TYPE_SUBTYPE_COLASOFT_CAPSA */
1589 { "Colasoft Capsa format", "capsa", "cscpkt", NULL,
1593 /* WTAP_FILE_TYPE_SUBTYPE_COLASOFT_PACKET_BUILDER */
1594 { "Colasoft Packet Builder format", "colasoft-pb", "cscpkt", NULL,
1598 /* WTAP_FILE_TYPE_SUBTYPE_JSON */
1599 { "JavaScript Object Notation", "json", "json", NULL,
1603 /* WTAP_FILE_TYPE_SUBTYPE_NETSCALER_3_5 */
1604 { "NetScaler Trace (Version 3.5)", "nstrace35", "cap", NULL,
1606 nstrace_35_dump_can_write_encap, nstrace_dump_open, NULL },
1608 /* WTAP_FILE_TYPE_SUBTYPE_NETTRACE_3GPP_32_423 */
1609 { "3GPP TS 32.423 Trace", "3gpp32423", NULL, NULL,
1613 /* WTAP_FILE_TYPE_MPLOG */
1614 { "Micropross mplog file", "mplog", "mplog", NULL,
1620 * Pointer to the table we're currently using. It's initialized to point
1621 * to the static table, but, if we have to allocate the GArray, it's
1622 * changed to point to the data in the GArray.
1624 static const struct file_type_subtype_info* dump_open_table = dump_open_table_base;
1627 * Number of elements in the table we're currently using. It's initialized
1628 * to the number of elements in the static table, but, if we have to
1629 * allocate the GArray, it's changed to have the size of the GArray.
1631 gint wtap_num_file_types_subtypes = sizeof(dump_open_table_base) / sizeof(struct file_type_subtype_info);
1634 * Pointer to the GArray; NULL until it's needed.
1636 static GArray* dump_open_table_arr = NULL;
1639 * Create the GArray from the static table if it hasn't already been created.
1642 init_file_types_subtypes_garray(void)
1644 if (dump_open_table_arr) return;
1646 dump_open_table_arr = g_array_new(FALSE,TRUE,sizeof(struct file_type_subtype_info));
1648 g_array_append_vals(dump_open_table_arr,dump_open_table_base,wtap_num_file_types_subtypes);
1650 dump_open_table = (const struct file_type_subtype_info*)(void *)dump_open_table_arr->data;
1653 /* if subtype is WTAP_FILE_TYPE_SUBTYPE_UNKNOWN, then create a new subtype as well as register it, else replace the
1654 existing entry in that spot */
1656 wtap_register_file_type_subtypes(const struct file_type_subtype_info* fi, const int subtype)
1658 struct file_type_subtype_info* finfo;
1660 if (!fi || !fi->name || !fi->short_name || subtype > wtap_num_file_types_subtypes) {
1661 g_error("no file type info or invalid file type to register");
1665 /* do we want a new registration? */
1666 if (subtype == WTAP_FILE_TYPE_SUBTYPE_UNKNOWN) {
1667 /* register a new one; first verify there isn't one named this already */
1668 if (wtap_short_string_to_file_type_subtype(fi->short_name) > -1 ) {
1669 g_error("file type short name already exists");
1674 * Create the GArray if it hasn't already been created.
1676 init_file_types_subtypes_garray();
1678 g_array_append_val(dump_open_table_arr,*fi);
1680 dump_open_table = (const struct file_type_subtype_info*)(void *)dump_open_table_arr->data;
1682 return wtap_num_file_types_subtypes++;
1685 /* re-register an existing one - verify the short names do match (sanity check really) */
1686 if (!dump_open_table[subtype].short_name || strcmp(dump_open_table[subtype].short_name,fi->short_name) != 0) {
1687 g_error("invalid file type name given to register");
1692 * Create the GArray if it hasn't already been created.
1694 init_file_types_subtypes_garray();
1697 * Get the pointer from the GArray, so that we get a non-const
1700 finfo = &g_array_index(dump_open_table_arr, struct file_type_subtype_info, subtype);
1701 /*finfo->name = fi->name;*/
1702 /*finfo->short_name = fi->short_name;*/
1703 finfo->default_file_extension = fi->default_file_extension;
1704 finfo->additional_file_extensions = fi->additional_file_extensions;
1705 finfo->writing_must_seek = fi->writing_must_seek;
1706 finfo->has_name_resolution = fi->has_name_resolution;
1707 finfo->supported_comment_types = fi->supported_comment_types;
1708 finfo->can_write_encap = fi->can_write_encap;
1709 finfo->dump_open = fi->dump_open;
1710 finfo->wslua_info = fi->wslua_info;
1715 /* De-registers a file writer - they can never be removed from the GArray, but we can "clear" an entry.
1718 wtap_deregister_file_type_subtype(const int subtype)
1720 struct file_type_subtype_info* finfo;
1722 if (subtype < 0 || subtype >= wtap_num_file_types_subtypes) {
1723 g_error("invalid file type to de-register");
1728 * Create the GArray if it hasn't already been created.
1730 init_file_types_subtypes_garray();
1733 * Get the pointer from the GArray, so that we get a non-const
1736 finfo = &g_array_index(dump_open_table_arr, struct file_type_subtype_info, subtype);
1737 /* unfortunately, it's not safe to null-out the name or short_name; bunch of other code doesn't guard aainst that, afaict */
1738 /*finfo->name = NULL;*/
1739 /*finfo->short_name = NULL;*/
1740 finfo->default_file_extension = NULL;
1741 finfo->additional_file_extensions = NULL;
1742 finfo->writing_must_seek = FALSE;
1743 finfo->has_name_resolution = FALSE;
1744 finfo->supported_comment_types = 0;
1745 finfo->can_write_encap = NULL;
1746 finfo->dump_open = NULL;
1747 finfo->wslua_info = NULL;
1751 wtap_get_num_file_types_subtypes(void)
1753 return wtap_num_file_types_subtypes;
1757 * Given a GArray of WTAP_ENCAP_ types, return the per-file encapsulation
1758 * type that would be needed to write out a file with those types. If
1759 * there's only one type, it's that type, otherwise it's
1760 * WTAP_ENCAP_PER_PACKET.
1763 wtap_dump_file_encap_type(const GArray *file_encaps)
1767 encap = WTAP_ENCAP_PER_PACKET;
1768 if (file_encaps->len == 1) {
1769 /* OK, use the one-and-only encapsulation type. */
1770 encap = g_array_index(file_encaps, gint, 0);
1776 wtap_dump_can_write_encap(int filetype, int encap)
1780 if (filetype < 0 || filetype >= wtap_num_file_types_subtypes
1781 || dump_open_table[filetype].can_write_encap == NULL)
1784 result = (*dump_open_table[filetype].can_write_encap)(encap);
1787 /* if the err said to check wslua's can_write_encap, try that */
1788 if (result == WTAP_ERR_CHECK_WSLUA
1789 && dump_open_table[filetype].wslua_info != NULL
1790 && dump_open_table[filetype].wslua_info->wslua_can_write_encap != NULL) {
1792 result = (*dump_open_table[filetype].wslua_info->wslua_can_write_encap)(encap, dump_open_table[filetype].wslua_info->wslua_data);
1804 * Return TRUE if a capture with a given GArray of encapsulation types
1805 * and a given bitset of comment types can be written in a specified
1806 * format, and FALSE if it can't.
1809 wtap_dump_can_write_format(int ft, const GArray *file_encaps,
1810 guint32 required_comment_types)
1815 * Can we write in this format?
1817 if (!wtap_dump_can_open(ft)) {
1823 * Yes. Can we write out all the required comments in this
1826 if (!wtap_dump_supports_comment_types(ft, required_comment_types)) {
1832 * Yes. Is the required per-file encapsulation type supported?
1833 * This might be WTAP_ENCAP_PER_PACKET.
1835 if (!wtap_dump_can_write_encap(ft, wtap_dump_file_encap_type(file_encaps))) {
1841 * Yes. Are all the individual encapsulation types supported?
1843 for (i = 0; i < file_encaps->len; i++) {
1844 if (!wtap_dump_can_write_encap(ft,
1845 g_array_index(file_encaps, int, i))) {
1846 /* No - one of them isn't. */
1851 /* Yes - we're OK. */
1856 * Return TRUE if we can write a file with the given GArray of
1857 * encapsulation types and the given bitmask of comment types.
1860 wtap_dump_can_write(const GArray *file_encaps, guint32 required_comment_types)
1864 for (ft = 0; ft < WTAP_NUM_FILE_TYPES_SUBTYPES; ft++) {
1865 /* To save a file with Wiretap, Wiretap has to handle that format,
1866 * and its code to handle that format must be able to write a file
1867 * with this file's encapsulation types.
1869 if (wtap_dump_can_write_format(ft, file_encaps, required_comment_types)) {
1870 /* OK, we can write it out in this type. */
1875 /* No, we couldn't save it in any format. */
1880 * Get a GArray of WTAP_FILE_TYPE_SUBTYPE_ values for file types/subtypes
1881 * that can be used to save a file of a given type/subtype with a given
1882 * GArray of encapsulation types and the given bitmask of comment types.
1885 wtap_get_savable_file_types_subtypes(int file_type_subtype,
1886 const GArray *file_encaps, guint32 required_comment_types)
1888 GArray *savable_file_types_subtypes;
1890 int default_file_type_subtype = -1;
1891 int other_file_type_subtype = -1;
1893 /* Can we save this file in its own file type/subtype? */
1894 if (wtap_dump_can_write_format(file_type_subtype, file_encaps,
1895 required_comment_types)) {
1896 /* Yes - make that the default file type/subtype. */
1897 default_file_type_subtype = file_type_subtype;
1899 /* OK, find the first file type/subtype we *can* save it as. */
1900 default_file_type_subtype = -1;
1901 for (ft = 0; ft < WTAP_NUM_FILE_TYPES_SUBTYPES; ft++) {
1902 if (wtap_dump_can_write_format(ft, file_encaps,
1903 required_comment_types)) {
1905 default_file_type_subtype = ft;
1910 if (default_file_type_subtype == -1) {
1911 /* We don't support writing this file as any file type/subtype. */
1915 /* Allocate the array. */
1916 savable_file_types_subtypes = g_array_new(FALSE, FALSE, (guint)sizeof (int));
1918 /* Put the default file type/subtype first in the list. */
1919 g_array_append_val(savable_file_types_subtypes, default_file_type_subtype);
1921 /* If the default is pcap, put pcap-NG right after it if we can
1922 also write it in pcap-NG format; otherwise, if the default is
1923 pcap-NG, put pcap right after it if we can also write it in
1925 if (default_file_type_subtype == WTAP_FILE_TYPE_SUBTYPE_PCAP) {
1926 if (wtap_dump_can_write_format(WTAP_FILE_TYPE_SUBTYPE_PCAPNG, file_encaps,
1927 required_comment_types))
1928 other_file_type_subtype = WTAP_FILE_TYPE_SUBTYPE_PCAPNG;
1929 } else if (default_file_type_subtype == WTAP_FILE_TYPE_SUBTYPE_PCAPNG) {
1930 if (wtap_dump_can_write_format(WTAP_FILE_TYPE_SUBTYPE_PCAP, file_encaps,
1931 required_comment_types))
1932 other_file_type_subtype = WTAP_FILE_TYPE_SUBTYPE_PCAP;
1934 if (other_file_type_subtype != -1)
1935 g_array_append_val(savable_file_types_subtypes, other_file_type_subtype);
1937 /* Add all the other file types/subtypes that work. */
1938 for (ft = 0; ft < WTAP_NUM_FILE_TYPES_SUBTYPES; ft++) {
1939 if (ft == WTAP_FILE_TYPE_SUBTYPE_UNKNOWN)
1940 continue; /* not a real file type */
1941 if (ft == default_file_type_subtype || ft == other_file_type_subtype)
1942 continue; /* we've already done this one */
1943 if (wtap_dump_can_write_format(ft, file_encaps,
1944 required_comment_types)) {
1945 /* OK, we can write it out in this type. */
1946 g_array_append_val(savable_file_types_subtypes, ft);
1950 return savable_file_types_subtypes;
1953 /* Name that should be somewhat descriptive. */
1955 wtap_file_type_subtype_string(int file_type_subtype)
1957 if (file_type_subtype < 0 || file_type_subtype >= wtap_num_file_types_subtypes) {
1958 g_error("Unknown capture file type %d", file_type_subtype);
1959 /** g_error() does an abort() and thus never returns **/
1962 return dump_open_table[file_type_subtype].name;
1965 /* Name to use in, say, a command-line flag specifying the type/subtype. */
1967 wtap_file_type_subtype_short_string(int file_type_subtype)
1969 if (file_type_subtype < 0 || file_type_subtype >= wtap_num_file_types_subtypes)
1972 return dump_open_table[file_type_subtype].short_name;
1975 /* Translate a short name to a capture file type/subtype. */
1977 wtap_short_string_to_file_type_subtype(const char *short_name)
1979 int file_type_subtype;
1981 for (file_type_subtype = 0; file_type_subtype < wtap_num_file_types_subtypes; file_type_subtype++) {
1982 if (dump_open_table[file_type_subtype].short_name != NULL &&
1983 strcmp(short_name, dump_open_table[file_type_subtype].short_name) == 0)
1984 return file_type_subtype;
1988 * We now call the libpcap file format just pcap, but we allow
1989 * the various variants of it to be specified using names
1990 * containing "libpcap" as well as "pcap", for backwards
1993 if (strcmp(short_name, "libpcap") == 0)
1994 return WTAP_FILE_TYPE_SUBTYPE_PCAP;
1995 else if (strcmp(short_name, "nseclibpcap") == 0)
1996 return WTAP_FILE_TYPE_SUBTYPE_PCAP_NSEC;
1997 else if (strcmp(short_name, "aixlibpcap") == 0)
1998 return WTAP_FILE_TYPE_SUBTYPE_PCAP_AIX;
1999 else if (strcmp(short_name, "modlibpcap") == 0)
2000 return WTAP_FILE_TYPE_SUBTYPE_PCAP_SS991029;
2001 else if (strcmp(short_name, "nokialibpcap") == 0)
2002 return WTAP_FILE_TYPE_SUBTYPE_PCAP_NOKIA;
2003 else if (strcmp(short_name, "rh6_1libpcap") == 0)
2004 return WTAP_FILE_TYPE_SUBTYPE_PCAP_SS990417;
2005 else if (strcmp(short_name, "suse6_3libpcap") == 0)
2006 return WTAP_FILE_TYPE_SUBTYPE_PCAP_SS990915;
2008 return -1; /* no such file type, or we can't write it */
2012 add_extensions_for_file_type_subtype(int file_type_subtype, GSList *extensions,
2013 const char **compressed_file_extensions)
2015 gchar **extensions_set, **extensionp;
2019 * Add the default extension, and all compressed variants of
2022 extensions = add_extensions(extensions,
2023 dump_open_table[file_type_subtype].default_file_extension,
2024 compressed_file_extensions);
2026 if (dump_open_table[file_type_subtype].additional_file_extensions != NULL) {
2028 * We have additional extensions; add them.
2030 * First, split the extension-list string into a set of
2033 extensions_set = g_strsplit(dump_open_table[file_type_subtype].additional_file_extensions,
2037 * Add each of those extensions to the list.
2039 for (extensionp = extensions_set; *extensionp != NULL;
2041 extension = *extensionp;
2044 * Add the extension, and all compressed variants
2047 extensions = add_extensions(extensions, extension,
2048 compressed_file_extensions);
2051 g_strfreev(extensions_set);
2056 /* Return a list of file extensions that are used by the specified file type.
2058 If include_compressed is TRUE, the list will include compressed
2059 extensions, e.g. not just "pcap" but also "pcap.gz" if we can read
2062 All strings in the list are allocated with g_malloc() and must be freed
2065 wtap_get_file_extensions_list(int file_type_subtype, gboolean include_compressed)
2068 static const char *no_compressed_extensions[] = {
2072 if (file_type_subtype < 0 || file_type_subtype >= wtap_num_file_types_subtypes)
2073 return NULL; /* not a valid file type */
2075 if (dump_open_table[file_type_subtype].default_file_extension == NULL)
2076 return NULL; /* valid, but no extensions known */
2078 extensions = NULL; /* empty list, to start with */
2081 * Add all this file type's extensions, with compressed
2082 * variants if include_compressed is true.
2084 extensions = add_extensions_for_file_type_subtype(file_type_subtype, extensions,
2085 include_compressed ? compressed_file_extension_table : no_compressed_extensions);
2091 * Free a list returned by wtap_get_file_extension_type_extensions(),
2092 * wtap_get_all_capture_file_extensions_list, or
2093 * wtap_get_file_extensions_list().
2096 wtap_free_extensions_list(GSList *extensions)
2100 for (extension = extensions; extension != NULL;
2101 extension = g_slist_next(extension)) {
2102 g_free(extension->data);
2104 g_slist_free(extensions);
2107 /* Return the default file extension to use with the specified file type;
2108 that's just the extension, without any ".". */
2110 wtap_default_file_extension(int file_type_subtype)
2112 if (file_type_subtype < 0 || file_type_subtype >= wtap_num_file_types_subtypes)
2115 return dump_open_table[file_type_subtype].default_file_extension;
2119 wtap_dump_can_open(int file_type_subtype)
2121 if (file_type_subtype < 0 || file_type_subtype >= wtap_num_file_types_subtypes
2122 || dump_open_table[file_type_subtype].dump_open == NULL)
2130 wtap_dump_can_compress(int file_type_subtype)
2133 * If this is an unknown file type, or if we have to
2134 * seek when writing out a file with this file type,
2137 if (file_type_subtype < 0 || file_type_subtype >= wtap_num_file_types_subtypes
2138 || dump_open_table[file_type_subtype].writing_must_seek)
2145 wtap_dump_can_compress(int file_type_subtype _U_)
2152 wtap_dump_has_name_resolution(int file_type_subtype)
2154 if (file_type_subtype < 0 || file_type_subtype >= wtap_num_file_types_subtypes
2155 || dump_open_table[file_type_subtype].has_name_resolution == FALSE)
2162 wtap_dump_supports_comment_types(int file_type_subtype, guint32 comment_types)
2164 guint32 supported_comment_types;
2166 if (file_type_subtype < 0 || file_type_subtype >= wtap_num_file_types_subtypes)
2169 supported_comment_types = dump_open_table[file_type_subtype].supported_comment_types;
2171 if ((comment_types & supported_comment_types) == comment_types)
2176 static gboolean wtap_dump_open_check(int file_type_subtype, int encap, gboolean comressed, int *err);
2177 static wtap_dumper* wtap_dump_alloc_wdh(int file_type_subtype, int encap, int snaplen,
2178 gboolean compressed, int *err);
2179 static gboolean wtap_dump_open_finish(wtap_dumper *wdh, int file_type_subtype, gboolean compressed, int *err);
2181 static WFILE_T wtap_dump_file_open(wtap_dumper *wdh, const char *filename);
2182 static WFILE_T wtap_dump_file_fdopen(wtap_dumper *wdh, int fd);
2183 static int wtap_dump_file_close(wtap_dumper *wdh);
2185 static wtap_dumper *
2186 wtap_dump_init_dumper(int file_type_subtype, int encap, int snaplen, gboolean compressed,
2187 GArray* shb_hdrs, wtapng_iface_descriptions_t *idb_inf,
2188 GArray* nrb_hdrs, int *err)
2191 wtap_block_t descr, file_int_data;
2192 wtapng_if_descr_mandatory_t *descr_mand, *file_int_data_mand;
2194 /* Check whether we can open a capture file with that file type
2195 and that encapsulation. */
2196 if (!wtap_dump_open_check(file_type_subtype, encap, compressed, err))
2199 /* Allocate a data structure for the output stream. */
2200 wdh = wtap_dump_alloc_wdh(file_type_subtype, encap, snaplen, compressed, err);
2202 return NULL; /* couldn't allocate it */
2204 /* Set Section Header Block data */
2205 wdh->shb_hdrs = shb_hdrs;
2206 /* Set Name Resolution Block data */
2207 wdh->nrb_hdrs = nrb_hdrs;
2208 /* Set Interface Description Block data */
2209 if ((idb_inf != NULL) && (idb_inf->interface_data->len > 0)) {
2212 /* Note: this memory is owned by wtap_dumper and will become
2213 * invalid after wtap_dump_close. */
2214 wdh->interface_data = g_array_new(FALSE, FALSE, sizeof(wtap_block_t));
2215 for (itf_count = 0; itf_count < idb_inf->interface_data->len; itf_count++) {
2216 file_int_data = g_array_index(idb_inf->interface_data, wtap_block_t, itf_count);
2217 file_int_data_mand = (wtapng_if_descr_mandatory_t*)wtap_block_get_mandatory_data(file_int_data);
2218 descr = wtap_block_create(WTAP_BLOCK_IF_DESCR);
2219 wtap_block_copy(descr, file_int_data);
2220 if ((encap != WTAP_ENCAP_PER_PACKET) && (encap != file_int_data_mand->wtap_encap)) {
2221 descr_mand = (wtapng_if_descr_mandatory_t*)wtap_block_get_mandatory_data(descr);
2222 descr_mand->wtap_encap = encap;
2224 g_array_append_val(wdh->interface_data, descr);
2227 descr = wtap_block_create(WTAP_BLOCK_IF_DESCR);
2228 descr_mand = (wtapng_if_descr_mandatory_t*)wtap_block_get_mandatory_data(descr);
2229 descr_mand->wtap_encap = encap;
2230 descr_mand->time_units_per_second = 1000000; /* default microsecond resolution */
2231 descr_mand->snap_len = snaplen;
2232 descr_mand->num_stat_entries = 0; /* Number of ISB:s */
2233 descr_mand->interface_statistics = NULL;
2234 wdh->interface_data = g_array_new(FALSE, FALSE, sizeof(wtap_block_t));
2235 g_array_append_val(wdh->interface_data, descr);
2241 wtap_dump_open(const char *filename, int file_type_subtype, int encap,
2242 int snaplen, gboolean compressed, int *err)
2244 return wtap_dump_open_ng(filename, file_type_subtype, encap,snaplen, compressed, NULL, NULL, NULL, err);
2248 wtap_dump_open_ng(const char *filename, int file_type_subtype, int encap,
2249 int snaplen, gboolean compressed, GArray* shb_hdrs, wtapng_iface_descriptions_t *idb_inf,
2250 GArray* nrb_hdrs, int *err)
2255 /* Allocate and initialize a data structure for the output stream. */
2256 wdh = wtap_dump_init_dumper(file_type_subtype, encap, snaplen, compressed,
2257 shb_hdrs, idb_inf, nrb_hdrs, err);
2261 /* In case "fopen()" fails but doesn't set "errno", set "errno"
2262 to a generic "the open failed" error. */
2263 errno = WTAP_ERR_CANT_OPEN;
2264 fh = wtap_dump_file_open(wdh, filename);
2268 return NULL; /* can't create file */
2272 if (!wtap_dump_open_finish(wdh, file_type_subtype, compressed, err)) {
2273 /* Get rid of the file we created; we couldn't finish
2275 wtap_dump_file_close(wdh);
2276 ws_unlink(filename);
2284 wtap_dump_open_tempfile(char **filenamep, const char *pfx,
2285 int file_type_subtype, int encap,
2286 int snaplen, gboolean compressed, int *err)
2288 return wtap_dump_open_tempfile_ng(filenamep, pfx, file_type_subtype, encap,snaplen, compressed, NULL, NULL, NULL, err);
2292 wtap_dump_open_tempfile_ng(char **filenamep, const char *pfx,
2293 int file_type_subtype, int encap,
2294 int snaplen, gboolean compressed,
2296 wtapng_iface_descriptions_t *idb_inf,
2297 GArray* nrb_hdrs, int *err)
2304 /* No path name for the temporary file yet. */
2307 /* Allocate and initialize a data structure for the output stream. */
2308 wdh = wtap_dump_init_dumper(file_type_subtype, encap, snaplen, compressed,
2309 shb_hdrs, idb_inf, nrb_hdrs, err);
2313 /* Choose a random name for the file */
2314 fd = create_tempfile(&tmpname, pfx, ".pcapng");
2318 return NULL; /* can't create file */
2320 *filenamep = tmpname;
2322 /* In case "fopen()" fails but doesn't set "errno", set "errno"
2323 to a generic "the open failed" error. */
2324 errno = WTAP_ERR_CANT_OPEN;
2325 fh = wtap_dump_file_fdopen(wdh, fd);
2330 return NULL; /* can't create file */
2334 if (!wtap_dump_open_finish(wdh, file_type_subtype, compressed, err)) {
2335 /* Get rid of the file we created; we couldn't finish
2337 wtap_dump_file_close(wdh);
2346 wtap_dump_fdopen(int fd, int file_type_subtype, int encap, int snaplen,
2347 gboolean compressed, int *err)
2349 return wtap_dump_fdopen_ng(fd, file_type_subtype, encap, snaplen, compressed, NULL, NULL, NULL, err);
2353 wtap_dump_fdopen_ng(int fd, int file_type_subtype, int encap, int snaplen,
2354 gboolean compressed, GArray* shb_hdrs, wtapng_iface_descriptions_t *idb_inf,
2355 GArray* nrb_hdrs, int *err)
2360 /* Allocate and initialize a data structure for the output stream. */
2361 wdh = wtap_dump_init_dumper(file_type_subtype, encap, snaplen, compressed,
2362 shb_hdrs, idb_inf, nrb_hdrs, err);
2366 /* In case "fopen()" fails but doesn't set "errno", set "errno"
2367 to a generic "the open failed" error. */
2368 errno = WTAP_ERR_CANT_OPEN;
2369 fh = wtap_dump_file_fdopen(wdh, fd);
2373 return NULL; /* can't create standard I/O stream */
2377 if (!wtap_dump_open_finish(wdh, file_type_subtype, compressed, err)) {
2378 wtap_dump_file_close(wdh);
2386 wtap_dump_open_stdout(int file_type_subtype, int encap, int snaplen,
2387 gboolean compressed, int *err)
2389 return wtap_dump_open_stdout_ng(file_type_subtype, encap, snaplen, compressed, NULL, NULL, NULL, err);
2393 wtap_dump_open_stdout_ng(int file_type_subtype, int encap, int snaplen,
2394 gboolean compressed, GArray* shb_hdrs,
2395 wtapng_iface_descriptions_t *idb_inf,
2396 GArray* nrb_hdrs, int *err)
2402 * Duplicate the file descriptor, so that we can close the
2403 * wtap_dumper handle the same way we close any other
2404 * wtap_dumper handle, without closing the standard output.
2414 * Put the new descriptor into binary mode.
2416 * XXX - even if the file format we're writing is a text
2419 if (_setmode(new_fd, O_BINARY) == -1) {
2420 /* "Should not happen" */
2427 wdh = wtap_dump_fdopen_ng(new_fd, file_type_subtype, encap, snaplen,
2428 compressed, shb_hdrs, idb_inf, nrb_hdrs, err);
2430 /* Failed; close the new FD */
2438 wtap_dump_open_check(int file_type_subtype, int encap, gboolean compressed, int *err)
2440 if (!wtap_dump_can_open(file_type_subtype)) {
2441 /* Invalid type, or type we don't know how to write. */
2442 *err = WTAP_ERR_UNWRITABLE_FILE_TYPE;
2446 /* OK, we know how to write that type; can we write the specified
2447 encapsulation type? */
2448 *err = (*dump_open_table[file_type_subtype].can_write_encap)(encap);
2449 /* if the err said to check wslua's can_write_encap, try that */
2450 if (*err == WTAP_ERR_CHECK_WSLUA
2451 && dump_open_table[file_type_subtype].wslua_info != NULL
2452 && dump_open_table[file_type_subtype].wslua_info->wslua_can_write_encap != NULL) {
2454 *err = (*dump_open_table[file_type_subtype].wslua_info->wslua_can_write_encap)(encap, dump_open_table[file_type_subtype].wslua_info->wslua_data);
2461 /* if compression is wanted, do we support this for this file_type_subtype? */
2462 if(compressed && !wtap_dump_can_compress(file_type_subtype)) {
2463 *err = WTAP_ERR_COMPRESSION_NOT_SUPPORTED;
2467 /* All systems go! */
2471 static wtap_dumper *
2472 wtap_dump_alloc_wdh(int file_type_subtype, int encap, int snaplen, gboolean compressed, int *err)
2476 wdh = (wtap_dumper *)g_malloc0(sizeof (wtap_dumper));
2482 wdh->file_type_subtype = file_type_subtype;
2483 wdh->snaplen = snaplen;
2485 wdh->compressed = compressed;
2486 wdh->wslua_data = NULL;
2491 wtap_dump_open_finish(wtap_dumper *wdh, int file_type_subtype, gboolean compressed, int *err)
2496 /* Can we do a seek on the file descriptor?
2497 If not, note that fact. */
2501 fd = ws_fileno((FILE *)wdh->fh);
2502 if (ws_lseek64(fd, 1, SEEK_CUR) == (off_t) -1)
2505 /* Undo the seek. */
2506 ws_lseek64(fd, 0, SEEK_SET);
2511 /* If this file type requires seeking, and we can't seek, fail. */
2512 if (dump_open_table[file_type_subtype].writing_must_seek && cant_seek) {
2513 *err = WTAP_ERR_CANT_WRITE_TO_PIPE;
2517 /* Set wdh with wslua data if any - this is how we pass the data
2518 * to the file writer.
2520 if (dump_open_table[file_type_subtype].wslua_info)
2521 wdh->wslua_data = dump_open_table[file_type_subtype].wslua_info->wslua_data;
2523 /* Now try to open the file for writing. */
2524 if (!(*dump_open_table[file_type_subtype].dump_open)(wdh, err)) {
2528 return TRUE; /* success! */
2532 wtap_dump(wtap_dumper *wdh, const struct wtap_pkthdr *phdr,
2533 const guint8 *pd, int *err, gchar **err_info)
2537 return (wdh->subtype_write)(wdh, phdr, pd, err, err_info);
2541 wtap_dump_flush(wtap_dumper *wdh)
2544 if(wdh->compressed) {
2545 gzwfile_flush((GZWFILE_T)wdh->fh);
2549 fflush((FILE *)wdh->fh);
2554 wtap_dump_close(wtap_dumper *wdh, int *err)
2556 gboolean ret = TRUE;
2558 if (wdh->subtype_finish != NULL) {
2559 /* There's a finish routine for this dump stream. */
2560 if (!(wdh->subtype_finish)(wdh, err))
2563 errno = WTAP_ERR_CANT_CLOSE;
2564 if (wtap_dump_file_close(wdh) == EOF) {
2566 /* The per-format finish function succeeded,
2567 but the stream close didn't. Save the
2568 reason why, if our caller asked for it. */
2574 if (wdh->priv != NULL)
2576 wtap_block_array_free(wdh->interface_data);
2582 wtap_get_bytes_dumped(wtap_dumper *wdh)
2584 return wdh->bytes_dumped;
2588 wtap_set_bytes_dumped(wtap_dumper *wdh, gint64 bytes_dumped)
2590 wdh->bytes_dumped = bytes_dumped;
2594 wtap_dump_set_addrinfo_list(wtap_dumper *wdh, addrinfo_lists_t *addrinfo_lists)
2596 if (!wdh || wdh->file_type_subtype < 0 || wdh->file_type_subtype >= wtap_num_file_types_subtypes
2597 || dump_open_table[wdh->file_type_subtype].has_name_resolution == FALSE)
2599 wdh->addrinfo_lists = addrinfo_lists;
2603 /* internally open a file for writing (compressed or not) */
2606 wtap_dump_file_open(wtap_dumper *wdh, const char *filename)
2608 if(wdh->compressed) {
2609 return gzwfile_open(filename);
2611 return ws_fopen(filename, "wb");
2616 wtap_dump_file_open(wtap_dumper *wdh _U_, const char *filename)
2618 return ws_fopen(filename, "wb");
2622 /* internally open a file for writing (compressed or not) */
2625 wtap_dump_file_fdopen(wtap_dumper *wdh, int fd)
2627 if(wdh->compressed) {
2628 return gzwfile_fdopen(fd);
2630 return ws_fdopen(fd, "wb");
2635 wtap_dump_file_fdopen(wtap_dumper *wdh _U_, int fd)
2637 return ws_fdopen(fd, "wb");
2641 /* internally writing raw bytes (compressed or not) */
2643 wtap_dump_file_write(wtap_dumper *wdh, const void *buf, size_t bufsize, int *err)
2648 if (wdh->compressed) {
2649 nwritten = gzwfile_write((GZWFILE_T)wdh->fh, buf, (unsigned int) bufsize);
2651 * gzwfile_write() returns 0 on error.
2653 if (nwritten == 0) {
2654 *err = gzwfile_geterr((GZWFILE_T)wdh->fh);
2660 errno = WTAP_ERR_CANT_WRITE;
2661 nwritten = fwrite(buf, 1, bufsize, (FILE *)wdh->fh);
2663 * At least according to the macOS man page,
2664 * this can return a short count on an error.
2666 if (nwritten != bufsize) {
2667 if (ferror((FILE *)wdh->fh))
2670 *err = WTAP_ERR_SHORT_WRITE;
2677 /* internally close a file for writing (compressed or not) */
2679 wtap_dump_file_close(wtap_dumper *wdh)
2683 return gzwfile_close((GZWFILE_T)wdh->fh);
2686 return fclose((FILE *)wdh->fh);
2690 wtap_dump_file_seek(wtap_dumper *wdh, gint64 offset, int whence, int *err)
2693 if(wdh->compressed) {
2694 *err = WTAP_ERR_CANT_SEEK_COMPRESSED;
2699 if (-1 == fseek((FILE *)wdh->fh, (long)offset, whence)) {
2710 wtap_dump_file_tell(wtap_dumper *wdh, int *err)
2714 if(wdh->compressed) {
2715 *err = WTAP_ERR_CANT_SEEK_COMPRESSED;
2720 if (-1 == (rval = ftell((FILE *)wdh->fh))) {
2731 cleanup_open_routines(void)
2734 struct open_info *i_open;
2736 if (open_routines != NULL && open_info_arr) {
2737 for (i = 0, i_open = open_routines; i < open_info_arr->len; i++, i_open++) {
2738 if (i_open->extensions != NULL)
2739 g_strfreev(i_open->extensions_set);
2742 g_array_free(open_info_arr, TRUE);
2743 open_info_arr = NULL;
2748 * Editor modelines - http://www.wireshark.org/tools/modelines.html
2753 * indent-tabs-mode: t
2756 * vi: set shiftwidth=8 tabstop=8 noexpandtab:
2757 * :indentSize=8:tabSize=8:noTabs=false: