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 "pcap-encap.h"
91 /* The open_file_* routines should return:
95 * 1 if the file they're reading is one of the types it handles;
97 * 0 if the file they're reading isn't the type they're checking for.
99 * If the routine handles this type of file, it should set the "file_type"
100 * field in the "struct wtap" to the type of the file.
102 * Note that the routine does not have to free the private data pointer on
103 * error. The caller takes care of that by calling wtap_close on error.
104 * (See https://bugs.wireshark.org/bugzilla/show_bug.cgi?id=8518)
106 * However, the caller does have to free the private data pointer when
107 * returning 0, since the next file type will be called and will likely
108 * just overwrite the pointer.
110 * Put the trace files that are merely saved telnet-sessions last, since it's
111 * possible that you could have captured someone a router telnet-session
112 * using another tool. So, a libpcap trace of an toshiba "snoop" session
113 * should be discovered as a libpcap file, not a toshiba file.
117 static wtap_open_routine_t open_routines_base[] = {
118 /* Files that have magic bytes in fixed locations. These
119 * are easy to identify.
133 network_instruments_open,
137 catapult_dct2000_open,
138 ber_open, /* XXX - this is really a heuristic */
142 vwr_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. */
150 /* Files that don't have magic bytes at a fixed location,
151 * but that instead require a heuristic of some sort to
152 * identify them. This includes the ASCII trace files that
153 * would be, for example, saved copies of a Telnet session
157 /* I put NetScreen *before* erf, because there were some
158 * false positives with my test-files (Sake Blok, July 2007)
180 #define N_FILE_TYPES (sizeof open_routines_base / sizeof open_routines_base[0])
182 static wtap_open_routine_t* open_routines = NULL;
184 static GArray* open_routines_arr = NULL;
187 /* initialize the open routines array if it has not been initialized yet */
188 static void init_open_routines(void) {
190 if (open_routines_arr) return;
192 open_routines_arr = g_array_new(FALSE,TRUE,sizeof(wtap_open_routine_t));
194 g_array_append_vals(open_routines_arr,open_routines_base,N_FILE_TYPES);
196 open_routines = (wtap_open_routine_t*)(void *)open_routines_arr->data;
199 void wtap_register_open_routine(wtap_open_routine_t open_routine, gboolean has_magic) {
200 init_open_routines();
203 g_array_prepend_val(open_routines_arr,open_routine);
205 g_array_append_val(open_routines_arr,open_routine);
207 open_routines = (wtap_open_routine_t*)(void *)open_routines_arr->data;
211 * Visual C++ on Win32 systems doesn't define these. (Old UNIX systems don't
212 * define them either.)
214 * Visual C++ on Win32 systems doesn't define S_IFIFO, it defines _S_IFIFO.
217 #define S_ISREG(mode) (((mode) & S_IFMT) == S_IFREG)
220 #define S_IFIFO _S_IFIFO
223 #define S_ISFIFO(mode) (((mode) & S_IFMT) == S_IFIFO)
226 #define S_ISDIR(mode) (((mode) & S_IFMT) == S_IFDIR)
229 /* Opens a file and prepares a wtap struct.
230 If "do_random" is TRUE, it opens the file twice; the second open
231 allows the application to do random-access I/O without moving
232 the seek offset for sequential I/O, which is used by Wireshark
233 so that it can do sequential I/O to a capture file that's being
234 written to as new packets arrive independently of random I/O done
235 to display protocol trees for packets when they're selected. */
236 wtap* wtap_open_offline(const char *filename, int *err, char **err_info,
243 gboolean use_stdin = FALSE;
245 /* open standard input if filename is '-' */
246 if (strcmp(filename, "-") == 0)
249 /* First, make sure the file is valid */
251 if (ws_fstat64(0, &statb) < 0) {
256 if (ws_stat64(filename, &statb) < 0) {
261 if (S_ISFIFO(statb.st_mode)) {
263 * Opens of FIFOs are allowed only when not opening
266 * XXX - currently, we do seeking when trying to find
267 * out the file type, so we don't actually support
268 * opening FIFOs. However, we may eventually
269 * do buffering that allows us to do at least some
270 * file type determination even on pipes, so we
271 * allow FIFO opens and let things fail later when
275 *err = WTAP_ERR_RANDOM_OPEN_PIPE;
278 } else if (S_ISDIR(statb.st_mode)) {
280 * Return different errors for "this is a directory"
281 * and "this is some random special file type", so
282 * the user can get a potentially more helpful error.
286 } else if (! S_ISREG(statb.st_mode)) {
287 *err = WTAP_ERR_NOT_REGULAR_FILE;
292 * We need two independent descriptors for random access, so
293 * they have different file positions. If we're opening the
294 * standard input, we can only dup it to get additional
295 * descriptors, so we can't have two independent descriptors,
296 * and thus can't do random access.
298 if (use_stdin && do_random) {
299 *err = WTAP_ERR_RANDOM_OPEN_STDIN;
304 wth = (wtap *)g_malloc0(sizeof(wtap));
307 errno = WTAP_ERR_CANT_OPEN;
310 * We dup FD 0, so that we don't have to worry about
311 * a file_close of wth->fh closing the standard
312 * input of the process.
321 if (_setmode(fd, O_BINARY) == -1) {
322 /* "Shouldn't happen" */
328 if (!(wth->fh = file_fdopen(fd))) {
335 if (!(wth->fh = file_open(filename))) {
343 if (!(wth->random_fh = file_open(filename))) {
350 wth->random_fh = NULL;
353 wth->file_encap = WTAP_ENCAP_UNKNOWN;
354 wth->subtype_sequential_close = NULL;
355 wth->subtype_close = NULL;
356 wth->tsprecision = WTAP_FILE_TSPREC_USEC;
359 init_open_routines();
360 if (wth->random_fh) {
361 wth->fast_seek = g_ptr_array_new();
363 file_set_random_access(wth->fh, FALSE, wth->fast_seek);
364 file_set_random_access(wth->random_fh, TRUE, wth->fast_seek);
367 /* Try all file types */
368 for (i = 0; i < open_routines_arr->len; i++) {
369 /* Seek back to the beginning of the file; the open routine
370 for the previous file type may have left the file
371 position somewhere other than the beginning, and the
372 open routine for this file type will probably want
373 to start reading at the beginning.
375 Initialize the data offset while we're at it. */
376 if (file_seek(wth->fh, 0, SEEK_SET, err) == -1) {
377 /* I/O error - give up */
382 switch ((*open_routines[i])(wth, err, err_info)) {
385 /* I/O error - give up */
390 /* No I/O error, but not that type of file */
394 /* We found the file type */
399 /* Well, it's not one of the types of file we know about. */
401 *err = WTAP_ERR_FILE_UNKNOWN_FORMAT;
405 wth->frame_buffer = (struct Buffer *)g_malloc(sizeof(struct Buffer));
406 buffer_init(wth->frame_buffer, 1500);
408 if(wth->file_type == WTAP_FILE_PCAP){
410 wtapng_if_descr_t descr;
412 descr.wtap_encap = wth->file_encap;
413 descr.time_units_per_second = 1000000; /* default microsecond resolution */
414 descr.link_type = wtap_wtap_encap_to_pcap_encap(wth->file_encap);
415 descr.snap_len = wth->snapshot_length;
416 descr.opt_comment = NULL;
417 descr.if_name = NULL;
418 descr.if_description = NULL;
420 descr.if_tsresol = 6;
421 descr.if_filter_str= NULL;
422 descr.bpf_filter_len= 0;
423 descr.if_filter_bpf_bytes= NULL;
425 descr.if_fcslen = -1;
426 descr.num_stat_entries = 0; /* Number of ISB:s */
427 descr.interface_statistics = NULL;
428 wth->number_of_interfaces= 1;
429 wth->interface_data= g_array_new(FALSE, FALSE, sizeof(wtapng_if_descr_t));
430 g_array_append_val(wth->interface_data, descr);
437 * Given the pathname of the file we just closed with wtap_fdclose(), attempt
438 * to reopen that file and assign the new file descriptor(s) to the sequential
439 * stream and, if do_random is TRUE, to the random stream. Used on Windows
440 * after the rename of a file we had open was done or if the rename of a
441 * file on top of a file we had open failed.
443 * This is only required by Wireshark, not TShark, and, at the point that
444 * Wireshark is doing this, the sequential stream is closed, and the
445 * random stream is open, so this refuses to open pipes, and only
446 * reopens the random stream.
449 wtap_fdreopen(wtap *wth, const char *filename, int *err)
454 * We need two independent descriptors for random access, so
455 * they have different file positions. If we're opening the
456 * standard input, we can only dup it to get additional
457 * descriptors, so we can't have two independent descriptors,
458 * and thus can't do random access.
460 if (strcmp(filename, "-") == 0) {
461 *err = WTAP_ERR_RANDOM_OPEN_STDIN;
465 /* First, make sure the file is valid */
466 if (ws_stat64(filename, &statb) < 0) {
470 if (S_ISFIFO(statb.st_mode)) {
472 * Opens of FIFOs are not allowed; see above.
474 *err = WTAP_ERR_RANDOM_OPEN_PIPE;
476 } else if (S_ISDIR(statb.st_mode)) {
478 * Return different errors for "this is a directory"
479 * and "this is some random special file type", so
480 * the user can get a potentially more helpful error.
484 } else if (! S_ISREG(statb.st_mode)) {
485 *err = WTAP_ERR_NOT_REGULAR_FILE;
490 errno = WTAP_ERR_CANT_OPEN;
491 if (!file_fdreopen(wth->random_fh, filename)) {
498 /* Table of the file types we know about.
499 Entries must be sorted by WTAP_FILE_xxx values in ascending order */
500 static const struct file_type_info dump_open_table_base[] = {
501 /* WTAP_FILE_UNKNOWN (only used internally for initialization) */
502 { NULL, NULL, NULL, NULL,
507 /* Gianluca Varenni suggests that we add "deprecated" to the description. */
508 { "Wireshark/tcpdump/... - libpcap", "libpcap", "pcap", "cap;dmp",
510 libpcap_dump_can_write_encap, libpcap_dump_open },
512 /* WTAP_FILE_PCAPNG */
513 { "Wireshark - pcapng", "pcapng", "pcapng", "ntar",
514 FALSE, TRUE, WTAP_COMMENT_PER_SECTION|WTAP_COMMENT_PER_INTERFACE|WTAP_COMMENT_PER_PACKET,
515 pcapng_dump_can_write_encap, pcapng_dump_open },
517 /* WTAP_FILE_PCAP_NSEC */
518 { "Wireshark - nanosecond libpcap", "nseclibpcap", "pcap", "cap;dmp",
520 libpcap_dump_can_write_encap, libpcap_dump_open },
522 /* WTAP_FILE_PCAP_AIX */
523 { "AIX tcpdump - libpcap", "aixlibpcap", "pcap", "cap;dmp",
527 /* WTAP_FILE_PCAP_SS991029 */
528 { "Modified tcpdump - libpcap", "modlibpcap", "pcap", "cap;dmp",
530 libpcap_dump_can_write_encap, libpcap_dump_open },
532 /* WTAP_FILE_PCAP_NOKIA */
533 { "Nokia tcpdump - libpcap ", "nokialibpcap", "pcap", "cap;dmp",
535 libpcap_dump_can_write_encap, libpcap_dump_open },
537 /* WTAP_FILE_PCAP_SS990417 */
538 { "RedHat 6.1 tcpdump - libpcap", "rh6_1libpcap", "pcap", "cap;dmp",
540 libpcap_dump_can_write_encap, libpcap_dump_open },
542 /* WTAP_FILE_PCAP_SS990915 */
543 { "SuSE 6.3 tcpdump - libpcap", "suse6_3libpcap", "pcap", "cap;dmp",
545 libpcap_dump_can_write_encap, libpcap_dump_open },
547 /* WTAP_FILE_5VIEWS */
548 { "InfoVista 5View capture", "5views", "5vw", NULL,
550 _5views_dump_can_write_encap, _5views_dump_open },
552 /* WTAP_FILE_IPTRACE_1_0 */
553 { "AIX iptrace 1.0", "iptrace_1", NULL, NULL,
557 /* WTAP_FILE_IPTRACE_2_0 */
558 { "AIX iptrace 2.0", "iptrace_2", NULL, NULL,
563 { "ASN.1 Basic Encoding Rules", "ber", NULL, NULL,
567 /* WTAP_FILE_HCIDUMP */
568 { "Bluetooth HCI dump", "hcidump", NULL, NULL,
572 /* WTAP_FILE_CATAPULT_DCT2000 */
573 { "Catapult DCT2000 trace (.out format)", "dct2000", "out", NULL,
575 catapult_dct2000_dump_can_write_encap, catapult_dct2000_dump_open },
577 /* WTAP_FILE_NETXRAY_OLD */
578 { "Cinco Networks NetXRay 1.x", "netxray1", "cap", NULL,
582 /* WTAP_FILE_NETXRAY_1_0 */
583 { "Cinco Networks NetXRay 2.0 or later", "netxray2", "cap", NULL,
587 /* WTAP_FILE_COSINE */
588 { "CoSine IPSX L2 capture", "cosine", "txt", NULL,
592 /* WTAP_FILE_CSIDS */
593 { "CSIDS IPLog", "csids", NULL, NULL,
597 /* WTAP_FILE_DBS_ETHERWATCH */
598 { "DBS Etherwatch (VMS)", "etherwatch", "txt", NULL,
603 { "Endace ERF capture", "erf", "erf", NULL,
605 erf_dump_can_write_encap, erf_dump_open },
607 /* WTAP_FILE_EYESDN */
608 { "EyeSDN USB S0/E1 ISDN trace format", "eyesdn", "trc", NULL,
610 eyesdn_dump_can_write_encap, eyesdn_dump_open },
612 /* WTAP_FILE_NETTL */
613 { "HP-UX nettl trace", "nettl", "trc0", "trc1",
615 nettl_dump_can_write_encap, nettl_dump_open },
617 /* WTAP_FILE_ISERIES */
618 { "IBM iSeries comm. trace (ASCII)", "iseries_ascii", "txt", NULL,
622 /* WTAP_FILE_ISERIES_UNICODE */
623 { "IBM iSeries comm. trace (UNICODE)", "iseries_unicode", "txt", NULL,
627 /* WTAP_FILE_I4BTRACE */
628 { "I4B ISDN trace", "i4btrace", NULL, NULL,
632 /* WTAP_FILE_ASCEND */
633 { "Lucent/Ascend access server trace", "ascend", "txt", NULL,
637 /* WTAP_FILE_NETMON_1_x */
638 { "Microsoft NetMon 1.x", "netmon1", "cap", NULL,
640 netmon_dump_can_write_encap_1_x, netmon_dump_open },
642 /* WTAP_FILE_NETMON_2_x */
643 { "Microsoft NetMon 2.x", "netmon2", "cap", NULL,
645 netmon_dump_can_write_encap_2_x, netmon_dump_open },
647 /* WTAP_FILE_NGSNIFFER_UNCOMPRESSED */
648 { "NA Sniffer (DOS)", "ngsniffer", "cap", "enc;trc;fdc;syc",
650 ngsniffer_dump_can_write_encap, ngsniffer_dump_open },
652 /* WTAP_FILE_NGSNIFFER_COMPRESSED */
653 { "NA Sniffer (DOS), compressed", "ngsniffer_comp", "caz", NULL,
657 /* WTAP_FILE_NETXRAY_1_1 */
658 { "NA Sniffer (Windows) 1.1", "ngwsniffer_1_1", "cap", NULL,
660 netxray_dump_can_write_encap_1_1, netxray_dump_open_1_1 },
662 /* WTAP_FILE_NETXRAY_2_00x */
663 { "NA Sniffer (Windows) 2.00x", "ngwsniffer_2_0", "cap", NULL,
665 netxray_dump_can_write_encap_2_0, netxray_dump_open_2_0 },
667 /* WTAP_FILE_NETWORK_INSTRUMENTS */
668 { "Network Instruments Observer", "niobserver", "bfr", NULL,
670 network_instruments_dump_can_write_encap, network_instruments_dump_open },
672 /* WTAP_FILE_LANALYZER */
673 { "Novell LANalyzer","lanalyzer", "tr1", NULL,
675 lanalyzer_dump_can_write_encap, lanalyzer_dump_open },
677 /* WTAP_FILE_PPPDUMP */
678 { "pppd log (pppdump format)", "pppd", NULL, NULL,
682 /* WTAP_FILE_RADCOM */
683 { "RADCOM WAN/LAN analyzer", "radcom", NULL, NULL,
687 /* WTAP_FILE_SNOOP */
688 { "Sun snoop", "snoop", "snoop", "cap",
690 snoop_dump_can_write_encap, snoop_dump_open },
692 /* WTAP_FILE_SHOMITI */
693 { "Shomiti/Finisar Surveyor", "shomiti", "cap", NULL,
698 { "TCPIPtrace (VMS)", "tcpiptrace", "txt", NULL,
703 { "Tektronix K12xx 32-bit .rf5 format", "rf5", "rf5", NULL,
705 k12_dump_can_write_encap, k12_dump_open },
707 /* WTAP_FILE_TOSHIBA */
708 { "Toshiba Compact ISDN Router snoop", "toshiba", "txt", NULL,
712 /* WTAP_FILE_VISUAL_NETWORKS */
713 { "Visual Networks traffic capture", "visual", NULL, NULL,
715 visual_dump_can_write_encap, visual_dump_open },
717 /* WTAP_FILE_PEEKCLASSIC_V56 */
718 { "WildPackets classic (V5 and V6)", "peekclassic56", "pkt", "tpc;apc;wpz",
722 /* WTAP_FILE_PEEKCLASSIC_V7 */
723 { "WildPackets classic (V7)", "peekclassic7", "pkt", "tpc;apc;wpz",
727 /* WTAP_FILE_PEEKTAGGED */
728 { "WildPackets tagged", "peektagged", "pkt", "tpc;apc;wpz",
733 { "MPEG", "mpeg", "mpeg", "mpg;mp3",
737 /* WTAP_FILE_K12TEXT */
738 { "K12 text file", "k12text", "txt", NULL,
740 k12text_dump_can_write_encap, k12text_dump_open },
742 /* WTAP_FILE_NETSCREEN */
743 { "NetScreen snoop text file", "netscreen", "txt", NULL,
747 /* WTAP_FILE_COMMVIEW */
748 { "TamoSoft CommView", "commview", "ncf", NULL,
750 commview_dump_can_write_encap, commview_dump_open },
752 /* WTAP_FILE_BTSNOOP */
753 { "Symbian OS btsnoop", "btsnoop", "log", NULL,
755 btsnoop_dump_can_write_encap, btsnoop_dump_open_h4 },
758 { "Transport-Neutral Encapsulation Format", "tnef", NULL, NULL,
762 /* WTAP_FILE_DCT3TRACE */
763 { "Gammu DCT3 trace", "dct3trace", "xml", NULL,
767 /* WTAP_FILE_PACKETLOGGER */
768 { "PacketLogger", "pklg", "pklg", NULL,
772 /* WTAP_FILE_DAINTREE_SNA */
773 { "Daintree SNA", "dsna", "dcf", NULL,
777 /* WTAP_FILE_NETSCALER_1_0 */
778 { "NetScaler Trace (Version 1.0)", "nstrace10", NULL, NULL,
780 nstrace_10_dump_can_write_encap, nstrace_dump_open },
782 /* WTAP_FILE_NETSCALER_2_0 */
783 { "NetScaler Trace (Version 2.0)", "nstrace20", "cap", NULL,
785 nstrace_20_dump_can_write_encap, nstrace_dump_open },
787 /* WTAP_FILE_JPEG_JFIF */
788 { "JPEG/JFIF", "jpeg", "jpg", "jpeg;jfif",
792 /* WTAP_FILE_IPFIX */
793 { "IPFIX File Format", "ipfix", "pfx", "ipfix",
797 /* WTAP_ENCAP_MIME */
798 { "MIME File Format", "mime", NULL, NULL,
802 /* WTAP_FILE_AETHRA */
803 { "Aethra .aps file", "aethra", "aps", NULL,
807 /* WTAP_FILE_MPEG_2_TS */
808 { "MPEG2 transport stream", "mp2t", "mp2t", "ts;mpg",
812 /* WTAP_FILE_VWR_80211 */
813 { "Ixia IxVeriWave .vwr Raw 802.11 Capture", "vwr80211", "vwr", NULL,
817 /* WTAP_FILE_VWR_ETH */
818 { "Ixia IxVeriWave .vwr Raw Ethernet Capture", "vwreth", "vwr", NULL,
822 /* WTAP_FILE_CAMINS */
823 { "CAM Inspector file", "camins", "camins", NULL,
828 gint wtap_num_file_types = sizeof(dump_open_table_base) / sizeof(struct file_type_info);
830 static GArray* dump_open_table_arr = NULL;
831 static const struct file_type_info* dump_open_table = dump_open_table_base;
833 /* initialize the open routines array if it has not being initialized yet */
834 static void init_file_types(void) {
836 if (dump_open_table_arr) return;
838 dump_open_table_arr = g_array_new(FALSE,TRUE,sizeof(struct file_type_info));
840 g_array_append_vals(dump_open_table_arr,dump_open_table_base,wtap_num_file_types);
842 dump_open_table = (const struct file_type_info*)(void *)dump_open_table_arr->data;
845 int wtap_register_file_type(const struct file_type_info* fi) {
848 g_array_append_val(dump_open_table_arr,*fi);
850 dump_open_table = (const struct file_type_info*)(void *)dump_open_table_arr->data;
852 return wtap_num_file_types++;
855 int wtap_get_num_file_types(void)
857 return wtap_num_file_types;
861 * Given a GArray of WTAP_ENCAP_ types, return the per-file encapsulation
862 * type that would be needed to write out a file with those types. If
863 * there's only one type, it's that type, otherwise it's
864 * WTAP_ENCAP_PER_PACKET.
867 wtap_dump_file_encap_type(const GArray *file_encaps)
871 encap = WTAP_ENCAP_PER_PACKET;
872 if (file_encaps->len == 1) {
873 /* OK, use the one-and-only encapsulation type. */
874 encap = g_array_index(file_encaps, gint, 0);
880 wtap_dump_can_write_encap(int filetype, int encap)
882 if (filetype < 0 || filetype >= wtap_num_file_types
883 || dump_open_table[filetype].can_write_encap == NULL)
886 if ((*dump_open_table[filetype].can_write_encap)(encap) != 0)
893 * Return TRUE if a capture with a given GArray of encapsulation types
894 * and a given bitset of comment types can be written in a specified
895 * format, and FALSE if it can't.
898 wtap_dump_can_write_format(int ft, const GArray *file_encaps,
899 guint32 required_comment_types)
904 * Can we write in this format?
906 if (!wtap_dump_can_open(ft)) {
912 * Yes. Can we write out all the required comments in this
915 if (!wtap_dump_supports_comment_types(ft, required_comment_types)) {
921 * Yes. Is the required per-file encapsulation type supported?
922 * This might be WTAP_ENCAP_PER_PACKET.
924 if (!wtap_dump_can_write_encap(ft, wtap_dump_file_encap_type(file_encaps))) {
930 * Yes. Are all the individual encapsulation types supported?
932 for (i = 0; i < file_encaps->len; i++) {
933 if (!wtap_dump_can_write_encap(ft,
934 g_array_index(file_encaps, int, i))) {
935 /* No - one of them isn't. */
940 /* Yes - we're OK. */
945 * Return TRUE if we can write a file with the given GArray of
946 * encapsulation types and the given bitmask of comment types.
949 wtap_dump_can_write(const GArray *file_encaps, guint32 required_comment_types)
953 for (ft = 0; ft < WTAP_NUM_FILE_TYPES; ft++) {
954 /* To save a file with Wiretap, Wiretap has to handle that format,
955 and its code to handle that format must be able to write a file
956 with this file's encapsulation types. */
957 if (wtap_dump_can_write_format(ft, file_encaps, required_comment_types)) {
958 /* OK, we can write it out in this type. */
963 /* No, we couldn't save it in any format. */
968 * Get a GArray of WTAP_FILE_ values for file types that can be used
969 * to save a file of a given type with a given GArray of encapsulation
970 * types and the given bitmask of comment types.
973 wtap_get_savable_file_types(int file_type, const GArray *file_encaps,
974 guint32 required_comment_types)
976 GArray *savable_file_types;
978 int default_file_type = -1;
979 int other_file_type = -1;
981 /* Can we save this file in its own file type? */
982 if (wtap_dump_can_write_format(file_type, file_encaps,
983 required_comment_types)) {
984 /* Yes - make that the default file type. */
985 default_file_type = file_type;
987 /* OK, find the first file type we *can* save it as. */
988 default_file_type = -1;
989 for (ft = 0; ft < WTAP_NUM_FILE_TYPES; ft++) {
990 if (wtap_dump_can_write_format(ft, file_encaps,
991 required_comment_types)) {
993 default_file_type = ft;
998 if (default_file_type == -1) {
999 /* We don't support writing this file as any file type. */
1003 /* Allocate the array. */
1004 savable_file_types = g_array_new(FALSE, FALSE, (guint)sizeof (int));
1006 /* Put the default file format first in the list. */
1007 g_array_append_val(savable_file_types, default_file_type);
1009 /* If the default is pcap, put pcap-NG right after it if we can
1010 also write it in pcap-NG format; otherwise, if the default is
1011 pcap-NG, put pcap right after it if we can also write it in
1013 if (default_file_type == WTAP_FILE_PCAP) {
1014 if (wtap_dump_can_write_format(WTAP_FILE_PCAPNG, file_encaps,
1015 required_comment_types))
1016 other_file_type = WTAP_FILE_PCAPNG;
1017 } else if (default_file_type == WTAP_FILE_PCAPNG) {
1018 if (wtap_dump_can_write_format(WTAP_FILE_PCAP, file_encaps,
1019 required_comment_types))
1020 other_file_type = WTAP_FILE_PCAP;
1022 if (other_file_type != -1)
1023 g_array_append_val(savable_file_types, other_file_type);
1025 /* Add all the other file types that work. */
1026 for (ft = 0; ft < WTAP_NUM_FILE_TYPES; ft++) {
1027 if (ft == WTAP_FILE_UNKNOWN)
1028 continue; /* not a real file type */
1029 if (ft == default_file_type || ft == other_file_type)
1030 continue; /* we've already done this one */
1031 if (wtap_dump_can_write_format(ft, file_encaps,
1032 required_comment_types)) {
1033 /* OK, we can write it out in this type. */
1034 g_array_append_val(savable_file_types, ft);
1038 return savable_file_types;
1041 /* Name that should be somewhat descriptive. */
1042 const char *wtap_file_type_string(int filetype)
1044 if (filetype < 0 || filetype >= wtap_num_file_types) {
1045 g_error("Unknown capture file type %d", filetype);
1046 /** g_error() does an abort() and thus never returns **/
1049 return dump_open_table[filetype].name;
1052 /* Name to use in, say, a command-line flag specifying the type. */
1053 const char *wtap_file_type_short_string(int filetype)
1055 if (filetype < 0 || filetype >= wtap_num_file_types)
1058 return dump_open_table[filetype].short_name;
1061 /* Translate a short name to a capture file type. */
1062 int wtap_short_string_to_file_type(const char *short_name)
1066 for (filetype = 0; filetype < wtap_num_file_types; filetype++) {
1067 if (dump_open_table[filetype].short_name != NULL &&
1068 strcmp(short_name, dump_open_table[filetype].short_name) == 0)
1071 return -1; /* no such file type, or we can't write it */
1074 static GSList *add_extensions(GSList *extensions, const gchar *extension,
1075 GSList *compressed_file_extensions)
1077 GSList *compressed_file_extension;
1080 * Add the specified extension.
1082 extensions = g_slist_append(extensions, g_strdup(extension));
1085 * Now add the extensions for compressed-file versions of
1088 for (compressed_file_extension = compressed_file_extensions;
1089 compressed_file_extension != NULL;
1090 compressed_file_extension = g_slist_next(compressed_file_extension)) {
1091 extensions = g_slist_append(extensions,
1092 g_strdup_printf("%s.%s", extension,
1093 (gchar *)compressed_file_extension->data));
1099 /* Return a list of file extensions that are used by the specified file type.
1101 If include_compressed is TRUE, the list will include compressed
1102 extensions, e.g. not just "pcap" but also "pcap.gz" if we can read
1105 All strings in the list are allocated with g_malloc() and must be freed
1107 GSList *wtap_get_file_extensions_list(int filetype, gboolean include_compressed)
1109 gchar **extensions_set, **extensionp;
1111 GSList *compressed_file_extensions;
1114 if (filetype < 0 || filetype >= wtap_num_file_types)
1115 return NULL; /* not a valid file type */
1117 if (dump_open_table[filetype].default_file_extension == NULL)
1118 return NULL; /* valid, but no extensions known */
1120 extensions = NULL; /* empty list, to start with */
1123 * If include_compressions is true, get the list of compressed-file
1126 if (include_compressed)
1127 compressed_file_extensions = wtap_get_compressed_file_extensions();
1129 compressed_file_extensions = NULL;
1132 * Add the default extension, and all compressed variants of
1135 extensions = add_extensions(extensions,
1136 dump_open_table[filetype].default_file_extension,
1137 compressed_file_extensions);
1139 if (dump_open_table[filetype].additional_file_extensions != NULL) {
1141 * We have additional extensions; add them.
1143 * First, split the extension-list string into a set of
1146 extensions_set = g_strsplit(dump_open_table[filetype].additional_file_extensions,
1150 * Add each of those extensions to the list.
1152 for (extensionp = extensions_set; *extensionp != NULL;
1154 extension = *extensionp;
1157 * Add the extension, and all compressed variants
1160 extensions = add_extensions(extensions, extension,
1161 compressed_file_extensions);
1164 g_strfreev(extensions_set);
1166 g_slist_free(compressed_file_extensions);
1171 * Free a list returned by wtap_file_extensions_list().
1173 void wtap_free_file_extensions_list(GSList *extensions)
1177 for (extension = extensions; extension != NULL;
1178 extension = g_slist_next(extension)) {
1179 g_free(extension->data);
1181 g_slist_free(extensions);
1184 /* Return the default file extension to use with the specified file type;
1185 that's just the extension, without any ".". */
1186 const char *wtap_default_file_extension(int filetype)
1188 if (filetype < 0 || filetype >= wtap_num_file_types)
1191 return dump_open_table[filetype].default_file_extension;
1194 gboolean wtap_dump_can_open(int filetype)
1196 if (filetype < 0 || filetype >= wtap_num_file_types
1197 || dump_open_table[filetype].dump_open == NULL)
1204 gboolean wtap_dump_can_compress(int filetype)
1207 * If this is an unknown file type, or if we have to
1208 * seek when writing out a file with this file type,
1211 if (filetype < 0 || filetype >= wtap_num_file_types
1212 || dump_open_table[filetype].writing_must_seek)
1218 gboolean wtap_dump_can_compress(int filetype _U_)
1224 gboolean wtap_dump_has_name_resolution(int filetype)
1226 if (filetype < 0 || filetype >= wtap_num_file_types
1227 || dump_open_table[filetype].has_name_resolution == FALSE)
1233 gboolean wtap_dump_supports_comment_types(int filetype, guint32 comment_types)
1235 guint32 supported_comment_types;
1237 if (filetype < 0 || filetype >= wtap_num_file_types)
1240 supported_comment_types = dump_open_table[filetype].supported_comment_types;
1242 if ((comment_types & supported_comment_types) == comment_types)
1247 static gboolean wtap_dump_open_check(int filetype, int encap, gboolean comressed, int *err);
1248 static wtap_dumper* wtap_dump_alloc_wdh(int filetype, int encap, int snaplen,
1249 gboolean compressed, int *err);
1250 static gboolean wtap_dump_open_finish(wtap_dumper *wdh, int filetype, gboolean compressed, int *err);
1252 static WFILE_T wtap_dump_file_open(wtap_dumper *wdh, const char *filename);
1253 static WFILE_T wtap_dump_file_fdopen(wtap_dumper *wdh, int fd);
1254 static int wtap_dump_file_close(wtap_dumper *wdh);
1256 wtap_dumper* wtap_dump_open(const char *filename, int filetype, int encap,
1257 int snaplen, gboolean compressed, int *err)
1259 return wtap_dump_open_ng(filename, filetype, encap,snaplen, compressed, NULL, NULL, err);
1262 static wtap_dumper *
1263 wtap_dump_init_dumper(int filetype, int encap, int snaplen, gboolean compressed,
1264 wtapng_section_t *shb_hdr, wtapng_iface_descriptions_t *idb_inf, int *err)
1268 /* Allocate a data structure for the output stream. */
1269 wdh = wtap_dump_alloc_wdh(filetype, encap, snaplen, compressed, err);
1271 return NULL; /* couldn't allocate it */
1273 /* Set Section Header Block data */
1274 wdh->shb_hdr = shb_hdr;
1275 /* Set Interface Description Block data */
1276 if ((idb_inf != NULL) && (idb_inf->number_of_interfaces > 0)) {
1277 wdh->number_of_interfaces = idb_inf->number_of_interfaces;
1278 wdh->interface_data = idb_inf->interface_data;
1280 wtapng_if_descr_t descr;
1282 descr.wtap_encap = encap;
1283 descr.time_units_per_second = 1000000; /* default microsecond resolution */
1284 descr.link_type = wtap_wtap_encap_to_pcap_encap(encap);
1285 descr.snap_len = snaplen;
1286 descr.opt_comment = NULL;
1287 descr.if_name = g_strdup("Unknown/not available in original file format(libpcap)");
1288 descr.if_description = NULL;
1290 descr.if_tsresol = 6;
1291 descr.if_filter_str= NULL;
1292 descr.bpf_filter_len= 0;
1293 descr.if_filter_bpf_bytes= NULL;
1295 descr.if_fcslen = -1;
1296 descr.num_stat_entries = 0; /* Number of ISB:s */
1297 descr.interface_statistics = NULL;
1298 wdh->number_of_interfaces= 1;
1299 wdh->interface_data= g_array_new(FALSE, FALSE, sizeof(wtapng_if_descr_t));
1300 g_array_append_val(wdh->interface_data, descr);
1305 wtap_dumper* wtap_dump_open_ng(const char *filename, int filetype, int encap,
1306 int snaplen, gboolean compressed, wtapng_section_t *shb_hdr, wtapng_iface_descriptions_t *idb_inf, int *err)
1311 /* Check whether we can open a capture file with that file type
1312 and that encapsulation. */
1313 if (!wtap_dump_open_check(filetype, encap, compressed, err))
1316 /* Allocate and initialize a data structure for the output stream. */
1317 wdh = wtap_dump_init_dumper(filetype, encap, snaplen, compressed,
1318 shb_hdr, idb_inf, err);
1322 /* "-" means stdout */
1323 if (strcmp(filename, "-") == 0) {
1325 *err = EINVAL; /* XXX - return a Wiretap error code for this */
1327 return NULL; /* compress won't work on stdout */
1330 if (_setmode(fileno(stdout), O_BINARY) == -1) {
1331 /* "Should not happen" */
1334 return NULL; /* couldn't put standard output in binary mode */
1339 /* In case "fopen()" fails but doesn't set "errno", set "errno"
1340 to a generic "the open failed" error. */
1341 errno = WTAP_ERR_CANT_OPEN;
1342 fh = wtap_dump_file_open(wdh, filename);
1346 return NULL; /* can't create file */
1351 if (!wtap_dump_open_finish(wdh, filetype, compressed, err)) {
1352 /* Get rid of the file we created; we couldn't finish
1354 if (wdh->fh != stdout) {
1355 wtap_dump_file_close(wdh);
1356 ws_unlink(filename);
1364 wtap_dumper* wtap_dump_fdopen(int fd, int filetype, int encap, int snaplen,
1365 gboolean compressed, int *err)
1367 return wtap_dump_fdopen_ng(fd, filetype, encap, snaplen, compressed, NULL, NULL, err);
1370 wtap_dumper* wtap_dump_fdopen_ng(int fd, int filetype, int encap, int snaplen,
1371 gboolean compressed, wtapng_section_t *shb_hdr, wtapng_iface_descriptions_t *idb_inf, int *err)
1376 /* Check whether we can open a capture file with that file type
1377 and that encapsulation. */
1378 if (!wtap_dump_open_check(filetype, encap, compressed, err))
1381 /* Allocate and initialize a data structure for the output stream. */
1382 wdh = wtap_dump_init_dumper(filetype, encap, snaplen, compressed,
1383 shb_hdr, idb_inf, err);
1389 if (_setmode(fileno(stdout), O_BINARY) == -1) {
1390 /* "Should not happen" */
1393 return NULL; /* couldn't put standard output in binary mode */
1398 /* In case "fopen()" fails but doesn't set "errno", set "errno"
1399 to a generic "the open failed" error. */
1400 errno = WTAP_ERR_CANT_OPEN;
1401 fh = wtap_dump_file_fdopen(wdh, fd);
1405 return NULL; /* can't create standard I/O stream */
1409 if (!wtap_dump_open_finish(wdh, filetype, compressed, err)) {
1410 wtap_dump_file_close(wdh);
1417 static gboolean wtap_dump_open_check(int filetype, int encap, gboolean compressed, int *err)
1419 if (!wtap_dump_can_open(filetype)) {
1420 /* Invalid type, or type we don't know how to write. */
1421 *err = WTAP_ERR_UNSUPPORTED_FILE_TYPE;
1425 /* OK, we know how to write that type; can we write the specified
1426 encapsulation type? */
1427 *err = (*dump_open_table[filetype].can_write_encap)(encap);
1431 /* if compression is wanted, do we support this for this filetype? */
1432 if(compressed && !wtap_dump_can_compress(filetype)) {
1433 *err = WTAP_ERR_COMPRESSION_NOT_SUPPORTED;
1437 *err = (*dump_open_table[filetype].can_write_encap)(encap);
1441 /* All systems go! */
1445 static wtap_dumper* wtap_dump_alloc_wdh(int filetype, int encap, int snaplen,
1446 gboolean compressed, int *err)
1450 wdh = (wtap_dumper *)g_malloc0(sizeof (wtap_dumper));
1456 wdh->file_type = filetype;
1457 wdh->snaplen = snaplen;
1459 wdh->compressed = compressed;
1463 static gboolean wtap_dump_open_finish(wtap_dumper *wdh, int filetype, gboolean compressed, int *err)
1468 /* Can we do a seek on the file descriptor?
1469 If not, note that fact. */
1473 fd = fileno((FILE *)wdh->fh);
1474 if (lseek(fd, 1, SEEK_CUR) == -1)
1477 /* Undo the seek. */
1478 lseek(fd, 0, SEEK_SET);
1483 /* If this file type requires seeking, and we can't seek, fail. */
1484 if (dump_open_table[filetype].writing_must_seek && cant_seek) {
1485 *err = WTAP_ERR_CANT_WRITE_TO_PIPE;
1489 /* Now try to open the file for writing. */
1490 if (!(*dump_open_table[filetype].dump_open)(wdh, err)) {
1494 return TRUE; /* success! */
1497 gboolean wtap_dump(wtap_dumper *wdh, const struct wtap_pkthdr *phdr,
1498 const guint8 *pd, int *err)
1500 return (wdh->subtype_write)(wdh, phdr, pd, err);
1503 void wtap_dump_flush(wtap_dumper *wdh)
1506 if(wdh->compressed) {
1507 gzwfile_flush((GZWFILE_T)wdh->fh);
1511 fflush((FILE *)wdh->fh);
1515 gboolean wtap_dump_close(wtap_dumper *wdh, int *err)
1517 gboolean ret = TRUE;
1519 if (wdh->subtype_close != NULL) {
1520 /* There's a close routine for this dump stream. */
1521 if (!(wdh->subtype_close)(wdh, err))
1524 errno = WTAP_ERR_CANT_CLOSE;
1525 /* Don't close stdout */
1526 if (wdh->fh != stdout) {
1527 if (wtap_dump_file_close(wdh) == EOF) {
1529 /* The per-format close function succeeded,
1530 but the fclose didn't. Save the reason
1531 why, if our caller asked for it. */
1538 /* as we don't close stdout, at least try to flush it */
1539 wtap_dump_flush(wdh);
1541 if (wdh->priv != NULL)
1547 gint64 wtap_get_bytes_dumped(wtap_dumper *wdh)
1549 return wdh->bytes_dumped;
1552 void wtap_set_bytes_dumped(wtap_dumper *wdh, gint64 bytes_dumped)
1554 wdh->bytes_dumped = bytes_dumped;
1557 gboolean wtap_dump_set_addrinfo_list(wtap_dumper *wdh, struct addrinfo *addrinfo_list)
1559 if (!wdh || wdh->file_type < 0 || wdh->file_type >= wtap_num_file_types
1560 || dump_open_table[wdh->file_type].has_name_resolution == FALSE)
1562 wdh->addrinfo_list = addrinfo_list;
1566 /* internally open a file for writing (compressed or not) */
1568 static WFILE_T wtap_dump_file_open(wtap_dumper *wdh, const char *filename)
1570 if(wdh->compressed) {
1571 return gzwfile_open(filename);
1573 return ws_fopen(filename, "wb");
1577 static WFILE_T wtap_dump_file_open(wtap_dumper *wdh _U_, const char *filename)
1579 return ws_fopen(filename, "wb");
1583 /* internally open a file for writing (compressed or not) */
1585 static WFILE_T wtap_dump_file_fdopen(wtap_dumper *wdh, int fd)
1587 if(wdh->compressed) {
1588 return gzwfile_fdopen(fd);
1590 return fdopen(fd, "wb");
1594 static WFILE_T wtap_dump_file_fdopen(wtap_dumper *wdh _U_, int fd)
1596 return fdopen(fd, "wb");
1600 /* internally writing raw bytes (compressed or not) */
1601 gboolean wtap_dump_file_write(wtap_dumper *wdh, const void *buf, size_t bufsize,
1607 if (wdh->compressed) {
1608 nwritten = gzwfile_write((GZWFILE_T)wdh->fh, buf, (unsigned) bufsize);
1610 * gzwfile_write() returns 0 on error.
1612 if (nwritten == 0) {
1613 *err = gzwfile_geterr((GZWFILE_T)wdh->fh);
1619 nwritten = fwrite(buf, 1, bufsize, (FILE *)wdh->fh);
1621 * At least according to the Mac OS X man page,
1622 * this can return a short count on an error.
1624 if (nwritten != bufsize) {
1625 if (ferror((FILE *)wdh->fh))
1628 *err = WTAP_ERR_SHORT_WRITE;
1635 /* internally close a file for writing (compressed or not) */
1636 static int wtap_dump_file_close(wtap_dumper *wdh)
1639 if(wdh->compressed) {
1640 return gzwfile_close((GZWFILE_T)wdh->fh);
1644 return fclose((FILE *)wdh->fh);
1648 gint64 wtap_dump_file_seek(wtap_dumper *wdh, gint64 offset, int whence, int *err)
1651 if(wdh->compressed) {
1652 *err = WTAP_ERR_CANT_SEEK_COMPRESSED;
1657 if (-1 == fseek((FILE *)wdh->fh, (long)offset, whence)) {
1666 gint64 wtap_dump_file_tell(wtap_dumper *wdh, int *err)
1670 if(wdh->compressed) {
1671 *err = WTAP_ERR_CANT_SEEK_COMPRESSED;
1676 if (-1 == (rval = ftell((FILE *)wdh->fh))) {