6 * Copyright (c) 1998 by Gilbert Ramirez <gram@alumni.rice.edu>
8 * This program is free software; you can redistribute it and/or
9 * modify it under the terms of the GNU General Public License
10 * as published by the Free Software Foundation; either version 2
11 * of the License, or (at your option) any later version.
13 * This program is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 * GNU General Public License for more details.
18 * You should have received a copy of the GNU General Public License
19 * along with this program; if not, write to the Free Software
20 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
39 #include <wsutil/file_util.h>
42 #include "file_wrappers.h"
44 #include "lanalyzer.h"
45 #include "ngsniffer.h"
47 #include "ascendtext.h"
60 #include "peekclassic.h"
61 #include "peektagged.h"
63 #include "dbs-etherwatch.h"
69 #include "network_instruments.h"
72 #include "catapult_dct2000.h"
75 #include "netscreen.h"
81 #include "dct3trace.h"
82 #include "packetlogger.h"
83 #include "daintree-sna.h"
84 #include "netscaler.h"
85 #include "mime_file.h"
89 #include "stanag4607.h"
90 #include "pcap-encap.h"
92 /* The open_file_* routines should return:
96 * 1 if the file they're reading is one of the types it handles;
98 * 0 if the file they're reading isn't the type they're checking for.
100 * If the routine handles this type of file, it should set the "file_type"
101 * field in the "struct wtap" to the type of the file.
103 * Note that the routine does not have to free the private data pointer on
104 * error. The caller takes care of that by calling wtap_close on error.
105 * (See https://bugs.wireshark.org/bugzilla/show_bug.cgi?id=8518)
107 * However, the caller does have to free the private data pointer when
108 * returning 0, since the next file type will be called and will likely
109 * just overwrite the pointer.
111 * Put the trace files that are merely saved telnet-sessions last, since it's
112 * possible that you could have captured someone a router telnet-session
113 * using another tool. So, a libpcap trace of an toshiba "snoop" session
114 * should be discovered as a libpcap file, not a toshiba file.
118 static wtap_open_routine_t open_routines_base[] = {
119 /* Files that have magic bytes in fixed locations. These
120 * are easy to identify.
134 network_instruments_open,
138 catapult_dct2000_open,
139 ber_open, /* XXX - this is really a heuristic */
143 packetlogger_open, /* This type does not have a magic number, but its
144 * files are sometimes grabbed by mpeg_open. */
151 /* Files that don't have magic bytes at a fixed location,
152 * but that instead require a heuristic of some sort to
153 * identify them. This includes the ASCII trace files that
154 * would be, for example, saved copies of a Telnet session
158 /* I put NetScreen *before* erf, because there were some
159 * false positives with my test-files (Sake Blok, July 2007)
161 * I put VWR *after* ERF, because there were some cases where
162 * ERF files were misidentified as vwr files (Stephen
163 * Donnelly, August 2013; see bug 9054)
186 #define N_FILE_TYPES (sizeof open_routines_base / sizeof open_routines_base[0])
188 static wtap_open_routine_t* open_routines = NULL;
190 static GArray* open_routines_arr = NULL;
193 /* initialize the open routines array if it has not been initialized yet */
194 static void init_open_routines(void) {
196 if (open_routines_arr) return;
198 open_routines_arr = g_array_new(FALSE,TRUE,sizeof(wtap_open_routine_t));
200 g_array_append_vals(open_routines_arr,open_routines_base,N_FILE_TYPES);
202 open_routines = (wtap_open_routine_t*)(void *)open_routines_arr->data;
205 void wtap_register_open_routine(wtap_open_routine_t open_routine, gboolean has_magic) {
206 init_open_routines();
209 g_array_prepend_val(open_routines_arr,open_routine);
211 g_array_append_val(open_routines_arr,open_routine);
213 open_routines = (wtap_open_routine_t*)(void *)open_routines_arr->data;
217 * Visual C++ on Win32 systems doesn't define these. (Old UNIX systems don't
218 * define them either.)
220 * Visual C++ on Win32 systems doesn't define S_IFIFO, it defines _S_IFIFO.
223 #define S_ISREG(mode) (((mode) & S_IFMT) == S_IFREG)
226 #define S_IFIFO _S_IFIFO
229 #define S_ISFIFO(mode) (((mode) & S_IFMT) == S_IFIFO)
232 #define S_ISDIR(mode) (((mode) & S_IFMT) == S_IFDIR)
235 /* Opens a file and prepares a wtap struct.
236 If "do_random" is TRUE, it opens the file twice; the second open
237 allows the application to do random-access I/O without moving
238 the seek offset for sequential I/O, which is used by Wireshark
239 so that it can do sequential I/O to a capture file that's being
240 written to as new packets arrive independently of random I/O done
241 to display protocol trees for packets when they're selected. */
242 wtap* wtap_open_offline(const char *filename, int *err, char **err_info,
249 gboolean use_stdin = FALSE;
251 /* open standard input if filename is '-' */
252 if (strcmp(filename, "-") == 0)
255 /* First, make sure the file is valid */
257 if (ws_fstat64(0, &statb) < 0) {
262 if (ws_stat64(filename, &statb) < 0) {
267 if (S_ISFIFO(statb.st_mode)) {
269 * Opens of FIFOs are allowed only when not opening
272 * XXX - currently, we do seeking when trying to find
273 * out the file type, so we don't actually support
274 * opening FIFOs. However, we may eventually
275 * do buffering that allows us to do at least some
276 * file type determination even on pipes, so we
277 * allow FIFO opens and let things fail later when
281 *err = WTAP_ERR_RANDOM_OPEN_PIPE;
284 } else if (S_ISDIR(statb.st_mode)) {
286 * Return different errors for "this is a directory"
287 * and "this is some random special file type", so
288 * the user can get a potentially more helpful error.
292 } else if (! S_ISREG(statb.st_mode)) {
293 *err = WTAP_ERR_NOT_REGULAR_FILE;
298 * We need two independent descriptors for random access, so
299 * they have different file positions. If we're opening the
300 * standard input, we can only dup it to get additional
301 * descriptors, so we can't have two independent descriptors,
302 * and thus can't do random access.
304 if (use_stdin && do_random) {
305 *err = WTAP_ERR_RANDOM_OPEN_STDIN;
310 wth = (wtap *)g_malloc0(sizeof(wtap));
313 errno = WTAP_ERR_CANT_OPEN;
316 * We dup FD 0, so that we don't have to worry about
317 * a file_close of wth->fh closing the standard
318 * input of the process.
327 if (_setmode(fd, O_BINARY) == -1) {
328 /* "Shouldn't happen" */
334 if (!(wth->fh = file_fdopen(fd))) {
341 if (!(wth->fh = file_open(filename))) {
349 if (!(wth->random_fh = file_open(filename))) {
356 wth->random_fh = NULL;
359 wth->file_encap = WTAP_ENCAP_UNKNOWN;
360 wth->subtype_sequential_close = NULL;
361 wth->subtype_close = NULL;
362 wth->tsprecision = WTAP_FILE_TSPREC_USEC;
365 init_open_routines();
366 if (wth->random_fh) {
367 wth->fast_seek = g_ptr_array_new();
369 file_set_random_access(wth->fh, FALSE, wth->fast_seek);
370 file_set_random_access(wth->random_fh, TRUE, wth->fast_seek);
373 /* Try all file types */
374 for (i = 0; i < open_routines_arr->len; i++) {
375 /* Seek back to the beginning of the file; the open routine
376 for the previous file type may have left the file
377 position somewhere other than the beginning, and the
378 open routine for this file type will probably want
379 to start reading at the beginning.
381 Initialize the data offset while we're at it. */
382 if (file_seek(wth->fh, 0, SEEK_SET, err) == -1) {
383 /* I/O error - give up */
388 switch ((*open_routines[i])(wth, err, err_info)) {
391 /* I/O error - give up */
396 /* No I/O error, but not that type of file */
400 /* We found the file type */
405 /* Well, it's not one of the types of file we know about. */
407 *err = WTAP_ERR_FILE_UNKNOWN_FORMAT;
411 wth->frame_buffer = (struct Buffer *)g_malloc(sizeof(struct Buffer));
412 buffer_init(wth->frame_buffer, 1500);
414 if(wth->file_type == WTAP_FILE_PCAP){
416 wtapng_if_descr_t descr;
418 descr.wtap_encap = wth->file_encap;
419 descr.time_units_per_second = 1000000; /* default microsecond resolution */
420 descr.link_type = wtap_wtap_encap_to_pcap_encap(wth->file_encap);
421 descr.snap_len = wth->snapshot_length;
422 descr.opt_comment = NULL;
423 descr.if_name = NULL;
424 descr.if_description = NULL;
426 descr.if_tsresol = 6;
427 descr.if_filter_str= NULL;
428 descr.bpf_filter_len= 0;
429 descr.if_filter_bpf_bytes= NULL;
431 descr.if_fcslen = -1;
432 descr.num_stat_entries = 0; /* Number of ISB:s */
433 descr.interface_statistics = NULL;
434 wth->number_of_interfaces= 1;
435 wth->interface_data= g_array_new(FALSE, FALSE, sizeof(wtapng_if_descr_t));
436 g_array_append_val(wth->interface_data, descr);
443 * Given the pathname of the file we just closed with wtap_fdclose(), attempt
444 * to reopen that file and assign the new file descriptor(s) to the sequential
445 * stream and, if do_random is TRUE, to the random stream. Used on Windows
446 * after the rename of a file we had open was done or if the rename of a
447 * file on top of a file we had open failed.
449 * This is only required by Wireshark, not TShark, and, at the point that
450 * Wireshark is doing this, the sequential stream is closed, and the
451 * random stream is open, so this refuses to open pipes, and only
452 * reopens the random stream.
455 wtap_fdreopen(wtap *wth, const char *filename, int *err)
460 * We need two independent descriptors for random access, so
461 * they have different file positions. If we're opening the
462 * standard input, we can only dup it to get additional
463 * descriptors, so we can't have two independent descriptors,
464 * and thus can't do random access.
466 if (strcmp(filename, "-") == 0) {
467 *err = WTAP_ERR_RANDOM_OPEN_STDIN;
471 /* First, make sure the file is valid */
472 if (ws_stat64(filename, &statb) < 0) {
476 if (S_ISFIFO(statb.st_mode)) {
478 * Opens of FIFOs are not allowed; see above.
480 *err = WTAP_ERR_RANDOM_OPEN_PIPE;
482 } else if (S_ISDIR(statb.st_mode)) {
484 * Return different errors for "this is a directory"
485 * and "this is some random special file type", so
486 * the user can get a potentially more helpful error.
490 } else if (! S_ISREG(statb.st_mode)) {
491 *err = WTAP_ERR_NOT_REGULAR_FILE;
496 errno = WTAP_ERR_CANT_OPEN;
497 if (!file_fdreopen(wth->random_fh, filename)) {
504 /* Table of the file types we know about.
505 Entries must be sorted by WTAP_FILE_xxx values in ascending order */
506 static const struct file_type_info dump_open_table_base[] = {
507 /* WTAP_FILE_UNKNOWN (only used internally for initialization) */
508 { NULL, NULL, NULL, NULL,
513 /* Gianluca Varenni suggests that we add "deprecated" to the description. */
514 { "Wireshark/tcpdump/... - pcap", "pcap", "pcap", "cap;dmp",
516 libpcap_dump_can_write_encap, libpcap_dump_open },
518 /* WTAP_FILE_PCAPNG */
519 { "Wireshark/... - pcapng", "pcapng", "pcapng", "ntar",
520 FALSE, TRUE, WTAP_COMMENT_PER_SECTION|WTAP_COMMENT_PER_INTERFACE|WTAP_COMMENT_PER_PACKET,
521 pcapng_dump_can_write_encap, pcapng_dump_open },
523 /* WTAP_FILE_PCAP_NSEC */
524 { "Wireshark - nanosecond libpcap", "nseclibpcap", "pcap", "cap;dmp",
526 libpcap_dump_can_write_encap, libpcap_dump_open },
528 /* WTAP_FILE_PCAP_AIX */
529 { "AIX tcpdump - libpcap", "aixlibpcap", "pcap", "cap;dmp",
533 /* WTAP_FILE_PCAP_SS991029 */
534 { "Modified tcpdump - libpcap", "modlibpcap", "pcap", "cap;dmp",
536 libpcap_dump_can_write_encap, libpcap_dump_open },
538 /* WTAP_FILE_PCAP_NOKIA */
539 { "Nokia tcpdump - libpcap ", "nokialibpcap", "pcap", "cap;dmp",
541 libpcap_dump_can_write_encap, libpcap_dump_open },
543 /* WTAP_FILE_PCAP_SS990417 */
544 { "RedHat 6.1 tcpdump - libpcap", "rh6_1libpcap", "pcap", "cap;dmp",
546 libpcap_dump_can_write_encap, libpcap_dump_open },
548 /* WTAP_FILE_PCAP_SS990915 */
549 { "SuSE 6.3 tcpdump - libpcap", "suse6_3libpcap", "pcap", "cap;dmp",
551 libpcap_dump_can_write_encap, libpcap_dump_open },
553 /* WTAP_FILE_5VIEWS */
554 { "InfoVista 5View capture", "5views", "5vw", NULL,
556 _5views_dump_can_write_encap, _5views_dump_open },
558 /* WTAP_FILE_IPTRACE_1_0 */
559 { "AIX iptrace 1.0", "iptrace_1", NULL, NULL,
563 /* WTAP_FILE_IPTRACE_2_0 */
564 { "AIX iptrace 2.0", "iptrace_2", NULL, NULL,
569 { "ASN.1 Basic Encoding Rules", "ber", NULL, NULL,
573 /* WTAP_FILE_HCIDUMP */
574 { "Bluetooth HCI dump", "hcidump", NULL, NULL,
578 /* WTAP_FILE_CATAPULT_DCT2000 */
579 { "Catapult DCT2000 trace (.out format)", "dct2000", "out", NULL,
581 catapult_dct2000_dump_can_write_encap, catapult_dct2000_dump_open },
583 /* WTAP_FILE_NETXRAY_OLD */
584 { "Cinco Networks NetXRay 1.x", "netxray1", "cap", NULL,
588 /* WTAP_FILE_NETXRAY_1_0 */
589 { "Cinco Networks NetXRay 2.0 or later", "netxray2", "cap", NULL,
593 /* WTAP_FILE_COSINE */
594 { "CoSine IPSX L2 capture", "cosine", "txt", NULL,
598 /* WTAP_FILE_CSIDS */
599 { "CSIDS IPLog", "csids", NULL, NULL,
603 /* WTAP_FILE_DBS_ETHERWATCH */
604 { "DBS Etherwatch (VMS)", "etherwatch", "txt", NULL,
609 { "Endace ERF capture", "erf", "erf", NULL,
611 erf_dump_can_write_encap, erf_dump_open },
613 /* WTAP_FILE_EYESDN */
614 { "EyeSDN USB S0/E1 ISDN trace format", "eyesdn", "trc", NULL,
616 eyesdn_dump_can_write_encap, eyesdn_dump_open },
618 /* WTAP_FILE_NETTL */
619 { "HP-UX nettl trace", "nettl", "trc0", "trc1",
621 nettl_dump_can_write_encap, nettl_dump_open },
623 /* WTAP_FILE_ISERIES */
624 { "IBM iSeries comm. trace (ASCII)", "iseries_ascii", "txt", NULL,
628 /* WTAP_FILE_ISERIES_UNICODE */
629 { "IBM iSeries comm. trace (UNICODE)", "iseries_unicode", "txt", NULL,
633 /* WTAP_FILE_I4BTRACE */
634 { "I4B ISDN trace", "i4btrace", NULL, NULL,
638 /* WTAP_FILE_ASCEND */
639 { "Lucent/Ascend access server trace", "ascend", "txt", NULL,
643 /* WTAP_FILE_NETMON_1_x */
644 { "Microsoft NetMon 1.x", "netmon1", "cap", NULL,
646 netmon_dump_can_write_encap_1_x, netmon_dump_open },
648 /* WTAP_FILE_NETMON_2_x */
649 { "Microsoft NetMon 2.x", "netmon2", "cap", NULL,
651 netmon_dump_can_write_encap_2_x, netmon_dump_open },
653 /* WTAP_FILE_NGSNIFFER_UNCOMPRESSED */
654 { "NA Sniffer (DOS)", "ngsniffer", "cap", "enc;trc;fdc;syc",
656 ngsniffer_dump_can_write_encap, ngsniffer_dump_open },
658 /* WTAP_FILE_NGSNIFFER_COMPRESSED */
659 { "NA Sniffer (DOS), compressed", "ngsniffer_comp", "cap", "enc;trc;fdc;syc",
663 /* WTAP_FILE_NETXRAY_1_1 */
664 { "NA Sniffer (Windows) 1.1", "ngwsniffer_1_1", "cap", NULL,
666 netxray_dump_can_write_encap_1_1, netxray_dump_open_1_1 },
668 /* WTAP_FILE_NETXRAY_2_00x */
669 { "NA Sniffer (Windows) 2.00x", "ngwsniffer_2_0", "cap", "caz",
671 netxray_dump_can_write_encap_2_0, netxray_dump_open_2_0 },
673 /* WTAP_FILE_NETWORK_INSTRUMENTS */
674 { "Network Instruments Observer", "niobserver", "bfr", NULL,
676 network_instruments_dump_can_write_encap, network_instruments_dump_open },
678 /* WTAP_FILE_LANALYZER */
679 { "Novell LANalyzer","lanalyzer", "tr1", NULL,
681 lanalyzer_dump_can_write_encap, lanalyzer_dump_open },
683 /* WTAP_FILE_PPPDUMP */
684 { "pppd log (pppdump format)", "pppd", NULL, NULL,
688 /* WTAP_FILE_RADCOM */
689 { "RADCOM WAN/LAN analyzer", "radcom", NULL, NULL,
693 /* WTAP_FILE_SNOOP */
694 { "Sun snoop", "snoop", "snoop", "cap",
696 snoop_dump_can_write_encap, snoop_dump_open },
698 /* WTAP_FILE_SHOMITI */
699 { "Shomiti/Finisar Surveyor", "shomiti", "cap", NULL,
704 { "TCPIPtrace (VMS)", "tcpiptrace", "txt", NULL,
709 { "Tektronix K12xx 32-bit .rf5 format", "rf5", "rf5", NULL,
711 k12_dump_can_write_encap, k12_dump_open },
713 /* WTAP_FILE_TOSHIBA */
714 { "Toshiba Compact ISDN Router snoop", "toshiba", "txt", NULL,
718 /* WTAP_FILE_VISUAL_NETWORKS */
719 { "Visual Networks traffic capture", "visual", NULL, NULL,
721 visual_dump_can_write_encap, visual_dump_open },
723 /* WTAP_FILE_PEEKCLASSIC_V56 */
724 { "WildPackets classic (V5 and V6)", "peekclassic56", "pkt", "tpc;apc;wpz",
728 /* WTAP_FILE_PEEKCLASSIC_V7 */
729 { "WildPackets classic (V7)", "peekclassic7", "pkt", "tpc;apc;wpz",
733 /* WTAP_FILE_PEEKTAGGED */
734 { "WildPackets tagged", "peektagged", "pkt", "tpc;apc;wpz",
739 { "MPEG", "mpeg", "mpeg", "mpg;mp3",
743 /* WTAP_FILE_K12TEXT */
744 { "K12 text file", "k12text", "txt", NULL,
746 k12text_dump_can_write_encap, k12text_dump_open },
748 /* WTAP_FILE_NETSCREEN */
749 { "NetScreen snoop text file", "netscreen", "txt", NULL,
753 /* WTAP_FILE_COMMVIEW */
754 { "TamoSoft CommView", "commview", "ncf", NULL,
756 commview_dump_can_write_encap, commview_dump_open },
758 /* WTAP_FILE_BTSNOOP */
759 { "Symbian OS btsnoop", "btsnoop", "log", NULL,
761 btsnoop_dump_can_write_encap, btsnoop_dump_open_h4 },
764 { "Transport-Neutral Encapsulation Format", "tnef", NULL, NULL,
768 /* WTAP_FILE_DCT3TRACE */
769 { "Gammu DCT3 trace", "dct3trace", "xml", NULL,
773 /* WTAP_FILE_PACKETLOGGER */
774 { "PacketLogger", "pklg", "pklg", NULL,
778 /* WTAP_FILE_DAINTREE_SNA */
779 { "Daintree SNA", "dsna", "dcf", NULL,
783 /* WTAP_FILE_NETSCALER_1_0 */
784 { "NetScaler Trace (Version 1.0)", "nstrace10", NULL, NULL,
786 nstrace_10_dump_can_write_encap, nstrace_dump_open },
788 /* WTAP_FILE_NETSCALER_2_0 */
789 { "NetScaler Trace (Version 2.0)", "nstrace20", "cap", NULL,
791 nstrace_20_dump_can_write_encap, nstrace_dump_open },
793 /* WTAP_FILE_JPEG_JFIF */
794 { "JPEG/JFIF", "jpeg", "jpg", "jpeg;jfif",
798 /* WTAP_FILE_IPFIX */
799 { "IPFIX File Format", "ipfix", "pfx", "ipfix",
803 /* WTAP_ENCAP_MIME */
804 { "MIME File Format", "mime", NULL, NULL,
808 /* WTAP_FILE_AETHRA */
809 { "Aethra .aps file", "aethra", "aps", NULL,
813 /* WTAP_FILE_MPEG_2_TS */
814 { "MPEG2 transport stream", "mp2t", "mp2t", "ts;mpg",
818 /* WTAP_FILE_VWR_80211 */
819 { "Ixia IxVeriWave .vwr Raw 802.11 Capture", "vwr80211", "vwr", NULL,
823 /* WTAP_FILE_VWR_ETH */
824 { "Ixia IxVeriWave .vwr Raw Ethernet Capture", "vwreth", "vwr", NULL,
828 /* WTAP_FILE_CAMINS */
829 { "CAM Inspector file", "camins", "camins", NULL,
833 /* WTAP_FILE_STANAG_4607 */
834 { "STANAG 4607 Format", "stanag4607", NULL, NULL,
840 gint wtap_num_file_types = sizeof(dump_open_table_base) / sizeof(struct file_type_info);
842 static GArray* dump_open_table_arr = NULL;
843 static const struct file_type_info* dump_open_table = dump_open_table_base;
845 /* initialize the open routines array if it has not being initialized yet */
846 static void init_file_types(void) {
848 if (dump_open_table_arr) return;
850 dump_open_table_arr = g_array_new(FALSE,TRUE,sizeof(struct file_type_info));
852 g_array_append_vals(dump_open_table_arr,dump_open_table_base,wtap_num_file_types);
854 dump_open_table = (const struct file_type_info*)(void *)dump_open_table_arr->data;
857 int wtap_register_file_type(const struct file_type_info* fi) {
860 g_array_append_val(dump_open_table_arr,*fi);
862 dump_open_table = (const struct file_type_info*)(void *)dump_open_table_arr->data;
864 return wtap_num_file_types++;
867 int wtap_get_num_file_types(void)
869 return wtap_num_file_types;
873 * Given a GArray of WTAP_ENCAP_ types, return the per-file encapsulation
874 * type that would be needed to write out a file with those types. If
875 * there's only one type, it's that type, otherwise it's
876 * WTAP_ENCAP_PER_PACKET.
879 wtap_dump_file_encap_type(const GArray *file_encaps)
883 encap = WTAP_ENCAP_PER_PACKET;
884 if (file_encaps->len == 1) {
885 /* OK, use the one-and-only encapsulation type. */
886 encap = g_array_index(file_encaps, gint, 0);
892 wtap_dump_can_write_encap(int filetype, int encap)
894 if (filetype < 0 || filetype >= wtap_num_file_types
895 || dump_open_table[filetype].can_write_encap == NULL)
898 if ((*dump_open_table[filetype].can_write_encap)(encap) != 0)
905 * Return TRUE if a capture with a given GArray of encapsulation types
906 * and a given bitset of comment types can be written in a specified
907 * format, and FALSE if it can't.
910 wtap_dump_can_write_format(int ft, const GArray *file_encaps,
911 guint32 required_comment_types)
916 * Can we write in this format?
918 if (!wtap_dump_can_open(ft)) {
924 * Yes. Can we write out all the required comments in this
927 if (!wtap_dump_supports_comment_types(ft, required_comment_types)) {
933 * Yes. Is the required per-file encapsulation type supported?
934 * This might be WTAP_ENCAP_PER_PACKET.
936 if (!wtap_dump_can_write_encap(ft, wtap_dump_file_encap_type(file_encaps))) {
942 * Yes. Are all the individual encapsulation types supported?
944 for (i = 0; i < file_encaps->len; i++) {
945 if (!wtap_dump_can_write_encap(ft,
946 g_array_index(file_encaps, int, i))) {
947 /* No - one of them isn't. */
952 /* Yes - we're OK. */
957 * Return TRUE if we can write a file with the given GArray of
958 * encapsulation types and the given bitmask of comment types.
961 wtap_dump_can_write(const GArray *file_encaps, guint32 required_comment_types)
965 for (ft = 0; ft < WTAP_NUM_FILE_TYPES; ft++) {
966 /* To save a file with Wiretap, Wiretap has to handle that format,
967 and its code to handle that format must be able to write a file
968 with this file's encapsulation types. */
969 if (wtap_dump_can_write_format(ft, file_encaps, required_comment_types)) {
970 /* OK, we can write it out in this type. */
975 /* No, we couldn't save it in any format. */
980 * Get a GArray of WTAP_FILE_ values for file types that can be used
981 * to save a file of a given type with a given GArray of encapsulation
982 * types and the given bitmask of comment types.
985 wtap_get_savable_file_types(int file_type, const GArray *file_encaps,
986 guint32 required_comment_types)
988 GArray *savable_file_types;
990 int default_file_type = -1;
991 int other_file_type = -1;
993 /* Can we save this file in its own file type? */
994 if (wtap_dump_can_write_format(file_type, file_encaps,
995 required_comment_types)) {
996 /* Yes - make that the default file type. */
997 default_file_type = file_type;
999 /* OK, find the first file type we *can* save it as. */
1000 default_file_type = -1;
1001 for (ft = 0; ft < WTAP_NUM_FILE_TYPES; ft++) {
1002 if (wtap_dump_can_write_format(ft, file_encaps,
1003 required_comment_types)) {
1005 default_file_type = ft;
1010 if (default_file_type == -1) {
1011 /* We don't support writing this file as any file type. */
1015 /* Allocate the array. */
1016 savable_file_types = g_array_new(FALSE, FALSE, (guint)sizeof (int));
1018 /* Put the default file format first in the list. */
1019 g_array_append_val(savable_file_types, default_file_type);
1021 /* If the default is pcap, put pcap-NG right after it if we can
1022 also write it in pcap-NG format; otherwise, if the default is
1023 pcap-NG, put pcap right after it if we can also write it in
1025 if (default_file_type == WTAP_FILE_PCAP) {
1026 if (wtap_dump_can_write_format(WTAP_FILE_PCAPNG, file_encaps,
1027 required_comment_types))
1028 other_file_type = WTAP_FILE_PCAPNG;
1029 } else if (default_file_type == WTAP_FILE_PCAPNG) {
1030 if (wtap_dump_can_write_format(WTAP_FILE_PCAP, file_encaps,
1031 required_comment_types))
1032 other_file_type = WTAP_FILE_PCAP;
1034 if (other_file_type != -1)
1035 g_array_append_val(savable_file_types, other_file_type);
1037 /* Add all the other file types that work. */
1038 for (ft = 0; ft < WTAP_NUM_FILE_TYPES; ft++) {
1039 if (ft == WTAP_FILE_UNKNOWN)
1040 continue; /* not a real file type */
1041 if (ft == default_file_type || ft == other_file_type)
1042 continue; /* we've already done this one */
1043 if (wtap_dump_can_write_format(ft, file_encaps,
1044 required_comment_types)) {
1045 /* OK, we can write it out in this type. */
1046 g_array_append_val(savable_file_types, ft);
1050 return savable_file_types;
1053 /* Name that should be somewhat descriptive. */
1054 const char *wtap_file_type_string(int filetype)
1056 if (filetype < 0 || filetype >= wtap_num_file_types) {
1057 g_error("Unknown capture file type %d", filetype);
1058 /** g_error() does an abort() and thus never returns **/
1061 return dump_open_table[filetype].name;
1064 /* Name to use in, say, a command-line flag specifying the type. */
1065 const char *wtap_file_type_short_string(int filetype)
1067 if (filetype < 0 || filetype >= wtap_num_file_types)
1070 return dump_open_table[filetype].short_name;
1073 /* Translate a short name to a capture file type. */
1074 int wtap_short_string_to_file_type(const char *short_name)
1078 for (filetype = 0; filetype < wtap_num_file_types; filetype++) {
1079 if (dump_open_table[filetype].short_name != NULL &&
1080 strcmp(short_name, dump_open_table[filetype].short_name) == 0)
1085 * We now call the "libpcap" file format just "pcap", but we
1086 * allow it to be specified as "libpcap" as well, for
1087 * backwards compatibility.
1089 if (strcmp(short_name, "libpcap") == 0)
1090 return WTAP_FILE_PCAP;
1092 return -1; /* no such file type, or we can't write it */
1095 static GSList *add_extensions(GSList *extensions, const gchar *extension,
1096 GSList *compressed_file_extensions)
1098 GSList *compressed_file_extension;
1101 * Add the specified extension.
1103 extensions = g_slist_append(extensions, g_strdup(extension));
1106 * Now add the extensions for compressed-file versions of
1109 for (compressed_file_extension = compressed_file_extensions;
1110 compressed_file_extension != NULL;
1111 compressed_file_extension = g_slist_next(compressed_file_extension)) {
1112 extensions = g_slist_append(extensions,
1113 g_strdup_printf("%s.%s", extension,
1114 (gchar *)compressed_file_extension->data));
1121 add_extensions_for_filetype(int filetype, GSList *extensions,
1122 GSList *compressed_file_extensions)
1124 gchar **extensions_set, **extensionp;
1128 * Add the default extension, and all compressed variants of
1131 extensions = add_extensions(extensions,
1132 dump_open_table[filetype].default_file_extension,
1133 compressed_file_extensions);
1135 if (dump_open_table[filetype].additional_file_extensions != NULL) {
1137 * We have additional extensions; add them.
1139 * First, split the extension-list string into a set of
1142 extensions_set = g_strsplit(dump_open_table[filetype].additional_file_extensions,
1146 * Add each of those extensions to the list.
1148 for (extensionp = extensions_set; *extensionp != NULL;
1150 extension = *extensionp;
1153 * Add the extension, and all compressed variants
1156 extensions = add_extensions(extensions, extension,
1157 compressed_file_extensions);
1160 g_strfreev(extensions_set);
1165 /* Return a list of all extensions that are used by all file types,
1166 including compressed extensions, e.g. not just "pcap" but also
1167 "pcap.gz" if we can read gzipped files.
1169 All strings in the list are allocated with g_malloc() and must be freed
1171 GSList *wtap_get_all_file_extensions_list(void)
1173 GSList *compressed_file_extensions;
1177 extensions = NULL; /* empty list, to start with */
1180 * Get the list of compressed-file extensions.
1182 compressed_file_extensions = wtap_get_compressed_file_extensions();
1184 for (filetype = 0; filetype < WTAP_NUM_FILE_TYPES; filetype++) {
1185 if (dump_open_table[filetype].default_file_extension != NULL) {
1187 * This file type has at least one extension.
1188 * Add all its extensions, with compressed
1191 extensions = add_extensions_for_filetype(filetype,
1192 extensions, compressed_file_extensions);
1196 g_slist_free(compressed_file_extensions);
1200 /* Return a list of file extensions that are used by the specified file type.
1202 If include_compressed is TRUE, the list will include compressed
1203 extensions, e.g. not just "pcap" but also "pcap.gz" if we can read
1206 All strings in the list are allocated with g_malloc() and must be freed
1208 GSList *wtap_get_file_extensions_list(int filetype, gboolean include_compressed)
1210 GSList *compressed_file_extensions;
1213 if (filetype < 0 || filetype >= wtap_num_file_types)
1214 return NULL; /* not a valid file type */
1216 if (dump_open_table[filetype].default_file_extension == NULL)
1217 return NULL; /* valid, but no extensions known */
1219 extensions = NULL; /* empty list, to start with */
1222 * If include_compressions is true, get the list of compressed-file
1225 if (include_compressed)
1226 compressed_file_extensions = wtap_get_compressed_file_extensions();
1228 compressed_file_extensions = NULL;
1231 * Add all this file type's extensions, with compressed
1234 extensions = add_extensions_for_filetype(filetype, extensions,
1235 compressed_file_extensions);
1237 g_slist_free(compressed_file_extensions);
1242 * Free a list returned by wtap_get_file_extensions_list().
1244 void wtap_free_file_extensions_list(GSList *extensions)
1248 for (extension = extensions; extension != NULL;
1249 extension = g_slist_next(extension)) {
1250 g_free(extension->data);
1252 g_slist_free(extensions);
1255 /* Return the default file extension to use with the specified file type;
1256 that's just the extension, without any ".". */
1257 const char *wtap_default_file_extension(int filetype)
1259 if (filetype < 0 || filetype >= wtap_num_file_types)
1262 return dump_open_table[filetype].default_file_extension;
1265 gboolean wtap_dump_can_open(int filetype)
1267 if (filetype < 0 || filetype >= wtap_num_file_types
1268 || dump_open_table[filetype].dump_open == NULL)
1275 gboolean wtap_dump_can_compress(int filetype)
1278 * If this is an unknown file type, or if we have to
1279 * seek when writing out a file with this file type,
1282 if (filetype < 0 || filetype >= wtap_num_file_types
1283 || dump_open_table[filetype].writing_must_seek)
1289 gboolean wtap_dump_can_compress(int filetype _U_)
1295 gboolean wtap_dump_has_name_resolution(int filetype)
1297 if (filetype < 0 || filetype >= wtap_num_file_types
1298 || dump_open_table[filetype].has_name_resolution == FALSE)
1304 gboolean wtap_dump_supports_comment_types(int filetype, guint32 comment_types)
1306 guint32 supported_comment_types;
1308 if (filetype < 0 || filetype >= wtap_num_file_types)
1311 supported_comment_types = dump_open_table[filetype].supported_comment_types;
1313 if ((comment_types & supported_comment_types) == comment_types)
1318 static gboolean wtap_dump_open_check(int filetype, int encap, gboolean comressed, int *err);
1319 static wtap_dumper* wtap_dump_alloc_wdh(int filetype, int encap, int snaplen,
1320 gboolean compressed, int *err);
1321 static gboolean wtap_dump_open_finish(wtap_dumper *wdh, int filetype, gboolean compressed, int *err);
1323 static WFILE_T wtap_dump_file_open(wtap_dumper *wdh, const char *filename);
1324 static WFILE_T wtap_dump_file_fdopen(wtap_dumper *wdh, int fd);
1325 static int wtap_dump_file_close(wtap_dumper *wdh);
1327 wtap_dumper* wtap_dump_open(const char *filename, int filetype, int encap,
1328 int snaplen, gboolean compressed, int *err)
1330 return wtap_dump_open_ng(filename, filetype, encap,snaplen, compressed, NULL, NULL, err);
1333 static wtap_dumper *
1334 wtap_dump_init_dumper(int filetype, int encap, int snaplen, gboolean compressed,
1335 wtapng_section_t *shb_hdr, wtapng_iface_descriptions_t *idb_inf, int *err)
1339 /* Allocate a data structure for the output stream. */
1340 wdh = wtap_dump_alloc_wdh(filetype, encap, snaplen, compressed, err);
1342 return NULL; /* couldn't allocate it */
1344 /* Set Section Header Block data */
1345 wdh->shb_hdr = shb_hdr;
1346 /* Set Interface Description Block data */
1347 if ((idb_inf != NULL) && (idb_inf->number_of_interfaces > 0)) {
1348 wdh->number_of_interfaces = idb_inf->number_of_interfaces;
1349 wdh->interface_data = idb_inf->interface_data;
1351 wtapng_if_descr_t descr;
1353 descr.wtap_encap = encap;
1354 descr.time_units_per_second = 1000000; /* default microsecond resolution */
1355 descr.link_type = wtap_wtap_encap_to_pcap_encap(encap);
1356 descr.snap_len = snaplen;
1357 descr.opt_comment = NULL;
1358 descr.if_name = g_strdup("Unknown/not available in original file format(libpcap)");
1359 descr.if_description = NULL;
1361 descr.if_tsresol = 6;
1362 descr.if_filter_str= NULL;
1363 descr.bpf_filter_len= 0;
1364 descr.if_filter_bpf_bytes= NULL;
1366 descr.if_fcslen = -1;
1367 descr.num_stat_entries = 0; /* Number of ISB:s */
1368 descr.interface_statistics = NULL;
1369 wdh->number_of_interfaces= 1;
1370 wdh->interface_data= g_array_new(FALSE, FALSE, sizeof(wtapng_if_descr_t));
1371 g_array_append_val(wdh->interface_data, descr);
1376 wtap_dumper* wtap_dump_open_ng(const char *filename, int filetype, int encap,
1377 int snaplen, gboolean compressed, wtapng_section_t *shb_hdr, wtapng_iface_descriptions_t *idb_inf, int *err)
1382 /* Check whether we can open a capture file with that file type
1383 and that encapsulation. */
1384 if (!wtap_dump_open_check(filetype, encap, compressed, err))
1387 /* Allocate and initialize a data structure for the output stream. */
1388 wdh = wtap_dump_init_dumper(filetype, encap, snaplen, compressed,
1389 shb_hdr, idb_inf, err);
1393 /* "-" means stdout */
1394 if (strcmp(filename, "-") == 0) {
1396 *err = EINVAL; /* XXX - return a Wiretap error code for this */
1398 return NULL; /* compress won't work on stdout */
1401 if (_setmode(fileno(stdout), O_BINARY) == -1) {
1402 /* "Should not happen" */
1405 return NULL; /* couldn't put standard output in binary mode */
1410 /* In case "fopen()" fails but doesn't set "errno", set "errno"
1411 to a generic "the open failed" error. */
1412 errno = WTAP_ERR_CANT_OPEN;
1413 fh = wtap_dump_file_open(wdh, filename);
1417 return NULL; /* can't create file */
1422 if (!wtap_dump_open_finish(wdh, filetype, compressed, err)) {
1423 /* Get rid of the file we created; we couldn't finish
1425 if (wdh->fh != stdout) {
1426 wtap_dump_file_close(wdh);
1427 ws_unlink(filename);
1435 wtap_dumper* wtap_dump_fdopen(int fd, int filetype, int encap, int snaplen,
1436 gboolean compressed, int *err)
1438 return wtap_dump_fdopen_ng(fd, filetype, encap, snaplen, compressed, NULL, NULL, err);
1441 wtap_dumper* wtap_dump_fdopen_ng(int fd, int filetype, int encap, int snaplen,
1442 gboolean compressed, wtapng_section_t *shb_hdr, wtapng_iface_descriptions_t *idb_inf, int *err)
1447 /* Check whether we can open a capture file with that file type
1448 and that encapsulation. */
1449 if (!wtap_dump_open_check(filetype, encap, compressed, err))
1452 /* Allocate and initialize a data structure for the output stream. */
1453 wdh = wtap_dump_init_dumper(filetype, encap, snaplen, compressed,
1454 shb_hdr, idb_inf, err);
1460 if (_setmode(fileno(stdout), O_BINARY) == -1) {
1461 /* "Should not happen" */
1464 return NULL; /* couldn't put standard output in binary mode */
1469 /* In case "fopen()" fails but doesn't set "errno", set "errno"
1470 to a generic "the open failed" error. */
1471 errno = WTAP_ERR_CANT_OPEN;
1472 fh = wtap_dump_file_fdopen(wdh, fd);
1476 return NULL; /* can't create standard I/O stream */
1480 if (!wtap_dump_open_finish(wdh, filetype, compressed, err)) {
1481 wtap_dump_file_close(wdh);
1488 static gboolean wtap_dump_open_check(int filetype, int encap, gboolean compressed, int *err)
1490 if (!wtap_dump_can_open(filetype)) {
1491 /* Invalid type, or type we don't know how to write. */
1492 *err = WTAP_ERR_UNSUPPORTED_FILE_TYPE;
1496 /* OK, we know how to write that type; can we write the specified
1497 encapsulation type? */
1498 *err = (*dump_open_table[filetype].can_write_encap)(encap);
1502 /* if compression is wanted, do we support this for this filetype? */
1503 if(compressed && !wtap_dump_can_compress(filetype)) {
1504 *err = WTAP_ERR_COMPRESSION_NOT_SUPPORTED;
1508 *err = (*dump_open_table[filetype].can_write_encap)(encap);
1512 /* All systems go! */
1516 static wtap_dumper* wtap_dump_alloc_wdh(int filetype, int encap, int snaplen,
1517 gboolean compressed, int *err)
1521 wdh = (wtap_dumper *)g_malloc0(sizeof (wtap_dumper));
1527 wdh->file_type = filetype;
1528 wdh->snaplen = snaplen;
1530 wdh->compressed = compressed;
1534 static gboolean wtap_dump_open_finish(wtap_dumper *wdh, int filetype, gboolean compressed, int *err)
1539 /* Can we do a seek on the file descriptor?
1540 If not, note that fact. */
1544 fd = fileno((FILE *)wdh->fh);
1545 if (lseek(fd, 1, SEEK_CUR) == -1)
1548 /* Undo the seek. */
1549 lseek(fd, 0, SEEK_SET);
1554 /* If this file type requires seeking, and we can't seek, fail. */
1555 if (dump_open_table[filetype].writing_must_seek && cant_seek) {
1556 *err = WTAP_ERR_CANT_WRITE_TO_PIPE;
1560 /* Now try to open the file for writing. */
1561 if (!(*dump_open_table[filetype].dump_open)(wdh, err)) {
1565 return TRUE; /* success! */
1568 gboolean wtap_dump(wtap_dumper *wdh, const struct wtap_pkthdr *phdr,
1569 const guint8 *pd, int *err)
1571 return (wdh->subtype_write)(wdh, phdr, pd, err);
1574 void wtap_dump_flush(wtap_dumper *wdh)
1577 if(wdh->compressed) {
1578 gzwfile_flush((GZWFILE_T)wdh->fh);
1582 fflush((FILE *)wdh->fh);
1586 gboolean wtap_dump_close(wtap_dumper *wdh, int *err)
1588 gboolean ret = TRUE;
1590 if (wdh->subtype_close != NULL) {
1591 /* There's a close routine for this dump stream. */
1592 if (!(wdh->subtype_close)(wdh, err))
1595 errno = WTAP_ERR_CANT_CLOSE;
1596 /* Don't close stdout */
1597 if (wdh->fh != stdout) {
1598 if (wtap_dump_file_close(wdh) == EOF) {
1600 /* The per-format close function succeeded,
1601 but the fclose didn't. Save the reason
1602 why, if our caller asked for it. */
1609 /* as we don't close stdout, at least try to flush it */
1610 wtap_dump_flush(wdh);
1612 if (wdh->priv != NULL)
1618 gint64 wtap_get_bytes_dumped(wtap_dumper *wdh)
1620 return wdh->bytes_dumped;
1623 void wtap_set_bytes_dumped(wtap_dumper *wdh, gint64 bytes_dumped)
1625 wdh->bytes_dumped = bytes_dumped;
1628 gboolean wtap_dump_set_addrinfo_list(wtap_dumper *wdh, struct addrinfo *addrinfo_list)
1630 if (!wdh || wdh->file_type < 0 || wdh->file_type >= wtap_num_file_types
1631 || dump_open_table[wdh->file_type].has_name_resolution == FALSE)
1633 wdh->addrinfo_list = addrinfo_list;
1637 /* internally open a file for writing (compressed or not) */
1639 static WFILE_T wtap_dump_file_open(wtap_dumper *wdh, const char *filename)
1641 if(wdh->compressed) {
1642 return gzwfile_open(filename);
1644 return ws_fopen(filename, "wb");
1648 static WFILE_T wtap_dump_file_open(wtap_dumper *wdh _U_, const char *filename)
1650 return ws_fopen(filename, "wb");
1654 /* internally open a file for writing (compressed or not) */
1656 static WFILE_T wtap_dump_file_fdopen(wtap_dumper *wdh, int fd)
1658 if(wdh->compressed) {
1659 return gzwfile_fdopen(fd);
1661 return fdopen(fd, "wb");
1665 static WFILE_T wtap_dump_file_fdopen(wtap_dumper *wdh _U_, int fd)
1667 return fdopen(fd, "wb");
1671 /* internally writing raw bytes (compressed or not) */
1672 gboolean wtap_dump_file_write(wtap_dumper *wdh, const void *buf, size_t bufsize,
1678 if (wdh->compressed) {
1679 nwritten = gzwfile_write((GZWFILE_T)wdh->fh, buf, (unsigned) bufsize);
1681 * gzwfile_write() returns 0 on error.
1683 if (nwritten == 0) {
1684 *err = gzwfile_geterr((GZWFILE_T)wdh->fh);
1690 nwritten = fwrite(buf, 1, bufsize, (FILE *)wdh->fh);
1692 * At least according to the Mac OS X man page,
1693 * this can return a short count on an error.
1695 if (nwritten != bufsize) {
1696 if (ferror((FILE *)wdh->fh))
1699 *err = WTAP_ERR_SHORT_WRITE;
1706 /* internally close a file for writing (compressed or not) */
1707 static int wtap_dump_file_close(wtap_dumper *wdh)
1710 if(wdh->compressed) {
1711 return gzwfile_close((GZWFILE_T)wdh->fh);
1715 return fclose((FILE *)wdh->fh);
1719 gint64 wtap_dump_file_seek(wtap_dumper *wdh, gint64 offset, int whence, int *err)
1722 if(wdh->compressed) {
1723 *err = WTAP_ERR_CANT_SEEK_COMPRESSED;
1728 if (-1 == fseek((FILE *)wdh->fh, (long)offset, whence)) {
1737 gint64 wtap_dump_file_tell(wtap_dumper *wdh, int *err)
1741 if(wdh->compressed) {
1742 *err = WTAP_ERR_CANT_SEEK_COMPRESSED;
1747 if (-1 == (rval = ftell((FILE *)wdh->fh))) {