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"
88 #include "pcap-encap.h"
90 /* The open_file_* routines should return:
94 * 1 if the file they're reading is one of the types it handles;
96 * 0 if the file they're reading isn't the type they're checking for.
98 * If the routine handles this type of file, it should set the "file_type"
99 * field in the "struct wtap" to the type of the file.
101 * Put the trace files that are merely saved telnet-sessions last, since it's
102 * possible that you could have captured someone a router telnet-session
103 * using another tool. So, a libpcap trace of an toshiba "snoop" session
104 * should be discovered as a libpcap file, not a toshiba file.
108 static wtap_open_routine_t open_routines_base[] = {
109 /* Files that have magic bytes in fixed locations. These
110 * are easy to identify.
124 network_instruments_open,
128 catapult_dct2000_open,
134 packetlogger_open, /* This type does not have a magic number, but its
135 * files are sometimes grabbed by mpeg_open. */
142 /* Files that don't have magic bytes at a fixed location,
143 * but that instead require a heuristic of some sort to
144 * identify them. This includes the ASCII trace files that
145 * would be, for example, saved copies of a Telnet session
149 /* I put NetScreen *before* erf, because there were some
150 * false positives with my test-files (Sake Blok, July 2007)
170 #define N_FILE_TYPES (sizeof open_routines_base / sizeof open_routines_base[0])
172 static wtap_open_routine_t* open_routines = NULL;
174 static GArray* open_routines_arr = NULL;
177 /* initialize the open routines array if it has not been initialized yet */
178 static void init_open_routines(void) {
180 if (open_routines_arr) return;
182 open_routines_arr = g_array_new(FALSE,TRUE,sizeof(wtap_open_routine_t));
184 g_array_append_vals(open_routines_arr,open_routines_base,N_FILE_TYPES);
186 open_routines = (wtap_open_routine_t*)(void *)open_routines_arr->data;
189 void wtap_register_open_routine(wtap_open_routine_t open_routine, gboolean has_magic) {
190 init_open_routines();
193 g_array_prepend_val(open_routines_arr,open_routine);
195 g_array_append_val(open_routines_arr,open_routine);
197 open_routines = (wtap_open_routine_t*)(void *)open_routines_arr->data;
201 * Visual C++ on Win32 systems doesn't define these. (Old UNIX systems don't
202 * define them either.)
204 * Visual C++ on Win32 systems doesn't define S_IFIFO, it defines _S_IFIFO.
207 #define S_ISREG(mode) (((mode) & S_IFMT) == S_IFREG)
210 #define S_IFIFO _S_IFIFO
213 #define S_ISFIFO(mode) (((mode) & S_IFMT) == S_IFIFO)
216 #define S_ISDIR(mode) (((mode) & S_IFMT) == S_IFDIR)
219 /* Opens a file and prepares a wtap struct.
220 If "do_random" is TRUE, it opens the file twice; the second open
221 allows the application to do random-access I/O without moving
222 the seek offset for sequential I/O, which is used by Wireshark
223 so that it can do sequential I/O to a capture file that's being
224 written to as new packets arrive independently of random I/O done
225 to display protocol trees for packets when they're selected. */
226 wtap* wtap_open_offline(const char *filename, int *err, char **err_info,
233 gboolean use_stdin = FALSE;
235 /* open standard input if filename is '-' */
236 if (strcmp(filename, "-") == 0)
239 /* First, make sure the file is valid */
241 if (ws_fstat64(0, &statb) < 0) {
246 if (ws_stat64(filename, &statb) < 0) {
251 if (S_ISFIFO(statb.st_mode)) {
253 * Opens of FIFOs are allowed only when not opening
256 * XXX - currently, we do seeking when trying to find
257 * out the file type, so we don't actually support
258 * opening FIFOs. However, we may eventually
259 * do buffering that allows us to do at least some
260 * file type determination even on pipes, so we
261 * allow FIFO opens and let things fail later when
265 *err = WTAP_ERR_RANDOM_OPEN_PIPE;
268 } else if (S_ISDIR(statb.st_mode)) {
270 * Return different errors for "this is a directory"
271 * and "this is some random special file type", so
272 * the user can get a potentially more helpful error.
276 } else if (! S_ISREG(statb.st_mode)) {
277 *err = WTAP_ERR_NOT_REGULAR_FILE;
282 * We need two independent descriptors for random access, so
283 * they have different file positions. If we're opening the
284 * standard input, we can only dup it to get additional
285 * descriptors, so we can't have two independent descriptors,
286 * and thus can't do random access.
288 if (use_stdin && do_random) {
289 *err = WTAP_ERR_RANDOM_OPEN_STDIN;
294 wth = (wtap *)g_malloc0(sizeof(wtap));
297 errno = WTAP_ERR_CANT_OPEN;
300 * We dup FD 0, so that we don't have to worry about
301 * a file_close of wth->fh closing the standard
302 * input of the process.
311 if (_setmode(fd, O_BINARY) == -1) {
312 /* "Shouldn't happen" */
318 if (!(wth->fh = file_fdopen(fd))) {
325 if (!(wth->fh = file_open(filename))) {
333 if (!(wth->random_fh = file_open(filename))) {
340 wth->random_fh = NULL;
343 wth->file_encap = WTAP_ENCAP_UNKNOWN;
344 wth->subtype_sequential_close = NULL;
345 wth->subtype_close = NULL;
346 wth->tsprecision = WTAP_FILE_TSPREC_USEC;
349 init_open_routines();
350 if (wth->random_fh) {
351 wth->fast_seek = g_ptr_array_new();
353 file_set_random_access(wth->fh, FALSE, wth->fast_seek);
354 file_set_random_access(wth->random_fh, TRUE, wth->fast_seek);
357 /* Try all file types */
358 for (i = 0; i < open_routines_arr->len; i++) {
359 /* Seek back to the beginning of the file; the open routine
360 for the previous file type may have left the file
361 position somewhere other than the beginning, and the
362 open routine for this file type will probably want
363 to start reading at the beginning.
365 Initialize the data offset while we're at it. */
366 if (file_seek(wth->fh, 0, SEEK_SET, err) == -1) {
367 /* I/O error - give up */
368 if (wth->random_fh != NULL)
369 file_close(wth->random_fh);
375 switch ((*open_routines[i])(wth, err, err_info)) {
378 /* I/O error - give up */
379 if (wth->random_fh != NULL)
380 file_close(wth->random_fh);
386 /* No I/O error, but not that type of file */
390 /* We found the file type */
395 /* Well, it's not one of the types of file we know about. */
397 *err = WTAP_ERR_FILE_UNKNOWN_FORMAT;
401 wth->frame_buffer = (struct Buffer *)g_malloc(sizeof(struct Buffer));
402 buffer_init(wth->frame_buffer, 1500);
404 if(wth->file_type == WTAP_FILE_PCAP){
406 wtapng_if_descr_t descr;
408 descr.wtap_encap = wth->file_encap;
409 descr.time_units_per_second = 1000000; /* default microsecond resolution */
410 descr.link_type = wtap_wtap_encap_to_pcap_encap(wth->file_encap);
411 descr.snap_len = wth->snapshot_length;
412 descr.opt_comment = NULL;
413 descr.if_name = NULL;
414 descr.if_description = NULL;
416 descr.if_tsresol = 6;
417 descr.if_filter_str= NULL;
418 descr.bpf_filter_len= 0;
419 descr.if_filter_bpf_bytes= NULL;
421 descr.if_fcslen = -1;
422 descr.num_stat_entries = 0; /* Number of ISB:s */
423 descr.interface_statistics = NULL;
424 wth->number_of_interfaces= 1;
425 wth->interface_data= g_array_new(FALSE, FALSE, sizeof(wtapng_if_descr_t));
426 g_array_append_val(wth->interface_data, descr);
433 * Given the pathname of the file we just closed with wtap_fdclose(), attempt
434 * to reopen that file and assign the new file descriptor(s) to the sequential
435 * stream and, if do_random is TRUE, to the random stream. Used on Windows
436 * after the rename of a file we had open was done or if the rename of a
437 * file on top of a file we had open failed.
439 * This is only required by Wireshark, not TShark, and, at the point that
440 * Wireshark is doing this, the sequential stream is closed, and the
441 * random stream is open, so this refuses to open pipes, and only
442 * reopens the random stream.
445 wtap_fdreopen(wtap *wth, const char *filename, int *err)
450 * We need two independent descriptors for random access, so
451 * they have different file positions. If we're opening the
452 * standard input, we can only dup it to get additional
453 * descriptors, so we can't have two independent descriptors,
454 * and thus can't do random access.
456 if (strcmp(filename, "-") == 0) {
457 *err = WTAP_ERR_RANDOM_OPEN_STDIN;
461 /* First, make sure the file is valid */
462 if (ws_stat64(filename, &statb) < 0) {
466 if (S_ISFIFO(statb.st_mode)) {
468 * Opens of FIFOs are not allowed; see above.
470 *err = WTAP_ERR_RANDOM_OPEN_PIPE;
472 } else if (S_ISDIR(statb.st_mode)) {
474 * Return different errors for "this is a directory"
475 * and "this is some random special file type", so
476 * the user can get a potentially more helpful error.
480 } else if (! S_ISREG(statb.st_mode)) {
481 *err = WTAP_ERR_NOT_REGULAR_FILE;
486 errno = WTAP_ERR_CANT_OPEN;
487 if (!file_fdreopen(wth->random_fh, filename)) {
494 /* Table of the file types we know about.
495 Entries must be sorted by WTAP_FILE_xxx values in ascending order */
496 static const struct file_type_info dump_open_table_base[] = {
497 /* WTAP_FILE_UNKNOWN (only used internally for initialization) */
498 { NULL, NULL, NULL, NULL, FALSE, FALSE,
502 /* Gianluca Varenni suggests that we add "deprecated" to the description. */
503 { "Wireshark/tcpdump/... - libpcap", "libpcap", "pcap", "cap;dmp", FALSE, FALSE,
504 libpcap_dump_can_write_encap, libpcap_dump_open },
506 /* WTAP_FILE_PCAPNG */
507 { "Wireshark - pcapng", "pcapng", "pcapng", "ntar", FALSE, TRUE,
508 pcapng_dump_can_write_encap, pcapng_dump_open },
510 /* WTAP_FILE_PCAP_NSEC */
511 { "Wireshark - nanosecond libpcap", "nseclibpcap", "pcap", "cap;dmp", FALSE, FALSE,
512 libpcap_dump_can_write_encap, libpcap_dump_open },
514 /* WTAP_FILE_PCAP_AIX */
515 { "AIX tcpdump - libpcap", "aixlibpcap", "pcap", "cap;dmp", FALSE, FALSE,
518 /* WTAP_FILE_PCAP_SS991029 */
519 { "Modified tcpdump - libpcap", "modlibpcap", "pcap", "cap;dmp", FALSE, FALSE,
520 libpcap_dump_can_write_encap, libpcap_dump_open },
522 /* WTAP_FILE_PCAP_NOKIA */
523 { "Nokia tcpdump - libpcap ", "nokialibpcap", "pcap", "cap;dmp", FALSE, FALSE,
524 libpcap_dump_can_write_encap, libpcap_dump_open },
526 /* WTAP_FILE_PCAP_SS990417 */
527 { "RedHat 6.1 tcpdump - libpcap", "rh6_1libpcap", "pcap", "cap;dmp", FALSE, FALSE,
528 libpcap_dump_can_write_encap, libpcap_dump_open },
530 /* WTAP_FILE_PCAP_SS990915 */
531 { "SuSE 6.3 tcpdump - libpcap", "suse6_3libpcap", "pcap", "cap;dmp", FALSE, FALSE,
532 libpcap_dump_can_write_encap, libpcap_dump_open },
534 /* WTAP_FILE_5VIEWS */
535 { "InfoVista 5View capture", "5views", "5vw", NULL, TRUE, FALSE,
536 _5views_dump_can_write_encap, _5views_dump_open },
538 /* WTAP_FILE_IPTRACE_1_0 */
539 { "AIX iptrace 1.0", "iptrace_1", NULL, NULL, FALSE, FALSE,
542 /* WTAP_FILE_IPTRACE_2_0 */
543 { "AIX iptrace 2.0", "iptrace_2", NULL, NULL, FALSE, FALSE,
547 { "ASN.1 Basic Encoding Rules", "ber", NULL, NULL, FALSE, FALSE,
550 /* WTAP_FILE_HCIDUMP */
551 { "Bluetooth HCI dump", "hcidump", NULL, NULL, FALSE, FALSE,
554 /* WTAP_FILE_CATAPULT_DCT2000 */
555 { "Catapult DCT2000 trace (.out format)", "dct2000", "out", NULL, FALSE, FALSE,
556 catapult_dct2000_dump_can_write_encap, catapult_dct2000_dump_open },
558 /* WTAP_FILE_NETXRAY_OLD */
559 { "Cinco Networks NetXRay 1.x", "netxray1", "cap", NULL, TRUE, FALSE,
562 /* WTAP_FILE_NETXRAY_1_0 */
563 { "Cinco Networks NetXRay 2.0 or later", "netxray2", "cap", NULL, TRUE, FALSE,
566 /* WTAP_FILE_COSINE */
567 { "CoSine IPSX L2 capture", "cosine", "txt", NULL, FALSE, FALSE,
570 /* WTAP_FILE_CSIDS */
571 { "CSIDS IPLog", "csids", NULL, NULL, FALSE, FALSE,
574 /* WTAP_FILE_DBS_ETHERWATCH */
575 { "DBS Etherwatch (VMS)", "etherwatch", "txt", NULL, FALSE, FALSE,
579 { "Endace ERF capture", "erf", "erf", NULL, FALSE, FALSE,
580 erf_dump_can_write_encap, erf_dump_open },
582 /* WTAP_FILE_EYESDN */
583 { "EyeSDN USB S0/E1 ISDN trace format", "eyesdn", "trc", NULL, FALSE, FALSE,
584 eyesdn_dump_can_write_encap, eyesdn_dump_open },
586 /* WTAP_FILE_NETTL */
587 { "HP-UX nettl trace", "nettl", "trc0", "trc1", FALSE, FALSE,
588 nettl_dump_can_write_encap, nettl_dump_open },
590 /* WTAP_FILE_ISERIES */
591 { "IBM iSeries comm. trace (ASCII)", "iseries_ascii", "txt", NULL, FALSE, FALSE,
594 /* WTAP_FILE_ISERIES_UNICODE */
595 { "IBM iSeries comm. trace (UNICODE)", "iseries_unicode", "txt", NULL, FALSE, FALSE,
598 /* WTAP_FILE_I4BTRACE */
599 { "I4B ISDN trace", "i4btrace", NULL, NULL, FALSE, FALSE,
602 /* WTAP_FILE_ASCEND */
603 { "Lucent/Ascend access server trace", "ascend", "txt", NULL, FALSE, FALSE,
606 /* WTAP_FILE_NETMON_1_x */
607 { "Microsoft NetMon 1.x", "netmon1", "cap", NULL, TRUE, FALSE,
608 netmon_dump_can_write_encap_1_x, netmon_dump_open },
610 /* WTAP_FILE_NETMON_2_x */
611 { "Microsoft NetMon 2.x", "netmon2", "cap", NULL, TRUE, FALSE,
612 netmon_dump_can_write_encap_2_x, netmon_dump_open },
614 /* WTAP_FILE_NGSNIFFER_UNCOMPRESSED */
615 { "NA Sniffer (DOS)", "ngsniffer", "cap", "enc;trc;fdc;syc", FALSE, FALSE,
616 ngsniffer_dump_can_write_encap, ngsniffer_dump_open },
618 /* WTAP_FILE_NGSNIFFER_COMPRESSED */
619 { "NA Sniffer (DOS), compressed", "ngsniffer_comp", "caz", NULL, FALSE, FALSE,
622 /* WTAP_FILE_NETXRAY_1_1 */
623 { "NA Sniffer (Windows) 1.1", "ngwsniffer_1_1", "cap", NULL, TRUE, FALSE,
624 netxray_dump_can_write_encap_1_1, netxray_dump_open_1_1 },
626 /* WTAP_FILE_NETXRAY_2_00x */
627 { "NA Sniffer (Windows) 2.00x", "ngwsniffer_2_0", "cap", NULL, TRUE, FALSE,
628 netxray_dump_can_write_encap_2_0, netxray_dump_open_2_0 },
630 /* WTAP_FILE_NETWORK_INSTRUMENTS */
631 { "Network Instruments Observer", "niobserver", "bfr", NULL, FALSE, FALSE,
632 network_instruments_dump_can_write_encap, network_instruments_dump_open },
634 /* WTAP_FILE_LANALYZER */
635 { "Novell LANalyzer","lanalyzer", "tr1", NULL, TRUE, FALSE,
636 lanalyzer_dump_can_write_encap, lanalyzer_dump_open },
638 /* WTAP_FILE_PPPDUMP */
639 { "pppd log (pppdump format)", "pppd", NULL, NULL, FALSE, FALSE,
642 /* WTAP_FILE_RADCOM */
643 { "RADCOM WAN/LAN analyzer", "radcom", NULL, NULL, FALSE, FALSE,
646 /* WTAP_FILE_SNOOP */
647 { "Sun snoop", "snoop", "snoop", "cap", FALSE, FALSE,
648 snoop_dump_can_write_encap, snoop_dump_open },
650 /* WTAP_FILE_SHOMITI */
651 { "Shomiti/Finisar Surveyor", "shomiti", "cap", NULL, FALSE, FALSE,
655 { "TCPIPtrace (VMS)", "tcpiptrace", "txt", NULL, FALSE, FALSE,
659 { "Tektronix K12xx 32-bit .rf5 format", "rf5", "rf5", NULL, TRUE, FALSE,
660 k12_dump_can_write_encap, k12_dump_open },
662 /* WTAP_FILE_TOSHIBA */
663 { "Toshiba Compact ISDN Router snoop", "toshiba", "txt", NULL, FALSE, FALSE,
666 /* WTAP_FILE_VISUAL_NETWORKS */
667 { "Visual Networks traffic capture", "visual", NULL, NULL, TRUE, FALSE,
668 visual_dump_can_write_encap, visual_dump_open },
670 /* WTAP_FILE_PEEKCLASSIC_V56 */
671 { "WildPackets classic (V5 and V6)", "peekclassic56", "pkt", "tpc;apc;wpz", FALSE, FALSE,
674 /* WTAP_FILE_PEEKCLASSIC_V7 */
675 { "WildPackets classic (V7)", "peekclassic7", "pkt", "tpc;apc;wpz", FALSE, FALSE,
678 /* WTAP_FILE_PEEKTAGGED */
679 { "WildPackets tagged", "peektagged", "pkt", "tpc;apc;wpz", FALSE, FALSE,
683 { "MPEG", "mpeg", "mpeg", "mpg;mp3", FALSE, FALSE,
686 /* WTAP_FILE_K12TEXT */
687 { "K12 text file", "k12text", "txt", NULL, FALSE, FALSE,
688 k12text_dump_can_write_encap, k12text_dump_open },
690 /* WTAP_FILE_NETSCREEN */
691 { "NetScreen snoop text file", "netscreen", "txt", NULL, FALSE, FALSE,
694 /* WTAP_FILE_COMMVIEW */
695 { "TamoSoft CommView", "commview", "ncf", NULL, FALSE, FALSE,
696 commview_dump_can_write_encap, commview_dump_open },
698 /* WTAP_FILE_BTSNOOP */
699 { "Symbian OS btsnoop", "btsnoop", "log", NULL, FALSE, FALSE,
700 btsnoop_dump_can_write_encap, btsnoop_dump_open_h4 },
703 { "Transport-Neutral Encapsulation Format", "tnef", NULL, NULL, FALSE, FALSE,
706 /* WTAP_FILE_DCT3TRACE */
707 { "Gammu DCT3 trace", "dct3trace", "xml", NULL, FALSE, FALSE,
710 /* WTAP_FILE_PACKETLOGGER */
711 { "PacketLogger", "pklg", "pklg", NULL, FALSE, FALSE,
714 /* WTAP_FILE_DAINTREE_SNA */
715 { "Daintree SNA", "dsna", "dcf", NULL, FALSE, FALSE,
718 /* WTAP_FILE_NETSCALER_1_0 */
719 { "NetScaler Trace (Version 1.0)", "nstrace10", NULL, NULL, TRUE, FALSE,
720 nstrace_10_dump_can_write_encap, nstrace_dump_open },
722 /* WTAP_FILE_NETSCALER_2_0 */
723 { "NetScaler Trace (Version 2.0)", "nstrace20", "cap", NULL, TRUE, FALSE,
724 nstrace_20_dump_can_write_encap, nstrace_dump_open },
726 /* WTAP_FILE_JPEG_JFIF */
727 { "JPEG/JFIF", "jpeg", "jpg", "jpeg;jfif", FALSE, FALSE,
730 /* WTAP_FILE_IPFIX */
731 { "IPFIX File Format", "ipfix", "pfx", "ipfix", FALSE, FALSE,
734 /* WTAP_ENCAP_MIME */
735 { "MIME File Format", "mime", NULL, NULL, FALSE, FALSE,
738 /* WTAP_FILE_AETHRA */
739 { "Aethra .aps file", "aethra", "aps", NULL, FALSE, FALSE,
742 /* WTAP_FILE_MPEG_2_TS */
743 { "MPEG2 transport stream", "mp2t", "mp2t", "ts;mpg", FALSE, FALSE,
746 /* WTAP_FILE_VWR_80211 */
747 { "Ixia IxVeriWave .vwr Raw 802.11 Capture", "vwr80211", "*.vwr", ".vwr", FALSE, FALSE,
750 /* WTAP_FILE_VWR_ETH */
751 { "Ixia IxVeriWave .vwr Raw Ethernet Capture", "vwreth", "*.vwr", ".vwr", FALSE, FALSE,
756 gint wtap_num_file_types = sizeof(dump_open_table_base) / sizeof(struct file_type_info);
758 static GArray* dump_open_table_arr = NULL;
759 static const struct file_type_info* dump_open_table = dump_open_table_base;
761 /* initialize the open routines array if it has not being initialized yet */
762 static void init_file_types(void) {
764 if (dump_open_table_arr) return;
766 dump_open_table_arr = g_array_new(FALSE,TRUE,sizeof(struct file_type_info));
768 g_array_append_vals(dump_open_table_arr,dump_open_table_base,wtap_num_file_types);
770 dump_open_table = (const struct file_type_info*)(void *)dump_open_table_arr->data;
773 int wtap_register_file_type(const struct file_type_info* fi) {
776 g_array_append_val(dump_open_table_arr,*fi);
778 dump_open_table = (const struct file_type_info*)(void *)dump_open_table_arr->data;
780 return wtap_num_file_types++;
783 int wtap_get_num_file_types(void)
785 return wtap_num_file_types;
789 * Given a GArray of WTAP_ENCAP_ types, return the per-file encapsulation
790 * type that would be needed to write out a file with those types. If
791 * there's only one type, it's that type, otherwise it's
792 * WTAP_ENCAP_PER_PACKET.
795 wtap_dump_file_encap_type(const GArray *file_encaps)
799 encap = WTAP_ENCAP_PER_PACKET;
800 if (file_encaps->len == 1) {
801 /* OK, use the one-and-only encapsulation type. */
802 encap = g_array_index(file_encaps, gint, 0);
808 * Return TRUE if a capture with a given GArray of WTAP_ENCAP_ types
809 * can be written in a specified format, and FALSE if it can't.
812 wtap_dump_can_write_encaps(int ft, const GArray *file_encaps)
817 * Can we write in this format?
819 if (!wtap_dump_can_open(ft)) {
825 * Is the required per-file encapsulation type supported?
826 * This might be WTAP_ENCAP_PER_PACKET.
828 if (!wtap_dump_can_write_encap(ft, wtap_dump_file_encap_type(file_encaps)))
832 * Yes. Are all the individual encapsulation types supported?
834 for (i = 0; i < file_encaps->len; i++) {
835 if (!wtap_dump_can_write_encap(ft,
836 g_array_index(file_encaps, int, i))) {
837 /* No - one of them isn't. */
842 /* Yes - we're OK. */
847 * Get a GArray of WTAP_FILE_ values for file types that can be used
848 * to save a file of a given type with a given GArray of WTAP_ENCAP_
852 wtap_get_savable_file_types(int file_type, const GArray *file_encaps)
854 GArray *savable_file_types;
856 int default_file_type = -1;
857 int other_file_type = -1;
859 /* Can we save this file in its own file type? */
860 if (wtap_dump_can_write_encaps(file_type, file_encaps)) {
861 /* Yes - make that the default file type. */
862 default_file_type = file_type;
864 /* No - can we save it as a pcap-NG file? */
865 if (wtap_dump_can_write_encaps(WTAP_FILE_PCAPNG, file_encaps)) {
866 /* Yes - default to pcap-NG, instead. */
867 default_file_type = WTAP_FILE_PCAPNG;
869 /* OK, find the first file type we *can* save it as. */
870 default_file_type = -1;
871 for (ft = 0; ft < WTAP_NUM_FILE_TYPES; ft++) {
872 if (wtap_dump_can_write_encaps(ft, file_encaps)) {
874 default_file_type = ft;
880 if (default_file_type == -1) {
881 /* We don't support writing this file as any file type. */
885 /* Allocate the array. */
886 savable_file_types = g_array_new(FALSE, FALSE, (guint)sizeof (int));
888 /* Put the default file format first in the list. */
889 g_array_append_val(savable_file_types, default_file_type);
891 /* If it's pcap, put pcap-NG right after it; otherwise, if it's
892 pcap-NG, put pcap right after it. */
893 if (default_file_type == WTAP_FILE_PCAP) {
894 if (wtap_dump_can_write_encaps(WTAP_FILE_PCAPNG, file_encaps))
895 other_file_type = WTAP_FILE_PCAPNG;
896 } else if (default_file_type == WTAP_FILE_PCAPNG) {
897 if (wtap_dump_can_write_encaps(WTAP_FILE_PCAP, file_encaps))
898 other_file_type = WTAP_FILE_PCAP;
900 if (other_file_type != -1)
901 g_array_append_val(savable_file_types, other_file_type);
903 /* Add all the other file types that work. */
904 for (ft = 0; ft < WTAP_NUM_FILE_TYPES; ft++) {
905 if (ft == WTAP_FILE_UNKNOWN)
906 continue; /* not a real file type */
907 if (ft == default_file_type || ft == other_file_type)
908 continue; /* we've already done this one */
909 if (wtap_dump_can_write_encaps(ft, file_encaps)) {
910 /* OK, we can write it out in this type. */
911 g_array_append_val(savable_file_types, ft);
915 return savable_file_types;
918 /* Name that should be somewhat descriptive. */
919 const char *wtap_file_type_string(int filetype)
921 if (filetype < 0 || filetype >= wtap_num_file_types) {
922 g_error("Unknown capture file type %d", filetype);
923 /** g_error() does an abort() and thus never returns **/
926 return dump_open_table[filetype].name;
929 /* Name to use in, say, a command-line flag specifying the type. */
930 const char *wtap_file_type_short_string(int filetype)
932 if (filetype < 0 || filetype >= wtap_num_file_types)
935 return dump_open_table[filetype].short_name;
938 /* Translate a short name to a capture file type. */
939 int wtap_short_string_to_file_type(const char *short_name)
943 for (filetype = 0; filetype < wtap_num_file_types; filetype++) {
944 if (dump_open_table[filetype].short_name != NULL &&
945 strcmp(short_name, dump_open_table[filetype].short_name) == 0)
948 return -1; /* no such file type, or we can't write it */
951 static GSList *add_extensions(GSList *extensions, const gchar *extension,
952 GSList *compressed_file_extensions)
954 GSList *compressed_file_extension;
957 * Add the specified extension.
959 extensions = g_slist_append(extensions, g_strdup(extension));
962 * Now add the extensions for compressed-file versions of
965 for (compressed_file_extension = compressed_file_extensions;
966 compressed_file_extension != NULL;
967 compressed_file_extension = g_slist_next(compressed_file_extension)) {
968 extensions = g_slist_append(extensions,
969 g_strdup_printf("%s.%s", extension,
970 (gchar *)compressed_file_extension->data));
976 /* Return a list of file extensions that are used by the specified file type.
978 If include_compressed is TRUE, the list will include compressed
979 extensions, e.g. not just "pcap" but also "pcap.gz" if we can read
982 All strings in the list are allocated with g_malloc() and must be freed
984 GSList *wtap_get_file_extensions_list(int filetype, gboolean include_compressed)
986 gchar **extensions_set, **extensionp;
988 GSList *compressed_file_extensions;
991 if (filetype < 0 || filetype >= wtap_num_file_types)
992 return NULL; /* not a valid file type */
994 if (dump_open_table[filetype].default_file_extension == NULL)
995 return NULL; /* valid, but no extensions known */
997 extensions = NULL; /* empty list, to start with */
1000 * If include_compressions is true, get the list of compressed-file
1003 if (include_compressed)
1004 compressed_file_extensions = wtap_get_compressed_file_extensions();
1006 compressed_file_extensions = NULL;
1009 * Add the default extension, and all compressed variants of
1012 extensions = add_extensions(extensions,
1013 dump_open_table[filetype].default_file_extension,
1014 compressed_file_extensions);
1016 if (dump_open_table[filetype].additional_file_extensions != NULL) {
1018 * We have additional extensions; add them.
1020 * First, split the extension-list string into a set of
1023 extensions_set = g_strsplit(dump_open_table[filetype].additional_file_extensions,
1027 * Add each of those extensions to the list.
1029 for (extensionp = extensions_set; *extensionp != NULL;
1031 extension = *extensionp;
1034 * Add the extension, and all compressed variants
1037 extensions = add_extensions(extensions, extension,
1038 compressed_file_extensions);
1041 g_strfreev(extensions_set);
1043 g_slist_free(compressed_file_extensions);
1048 * Free a list returned by wtap_file_extensions_list().
1050 void wtap_free_file_extensions_list(GSList *extensions)
1054 for (extension = extensions; extension != NULL;
1055 extension = g_slist_next(extension)) {
1056 g_free(extension->data);
1058 g_slist_free(extensions);
1061 /* Return the default file extension to use with the specified file type;
1062 that's just the extension, without any ".". */
1063 const char *wtap_default_file_extension(int filetype)
1065 if (filetype < 0 || filetype >= wtap_num_file_types)
1068 return dump_open_table[filetype].default_file_extension;
1071 gboolean wtap_dump_can_open(int filetype)
1073 if (filetype < 0 || filetype >= wtap_num_file_types
1074 || dump_open_table[filetype].dump_open == NULL)
1080 gboolean wtap_dump_can_write_encap(int filetype, int encap)
1082 if (filetype < 0 || filetype >= wtap_num_file_types
1083 || dump_open_table[filetype].can_write_encap == NULL)
1086 if ((*dump_open_table[filetype].can_write_encap)(encap) != 0)
1093 gboolean wtap_dump_can_compress(int filetype)
1096 * If this is an unknown file type, or if we have to
1097 * seek when writing out a file with this file type,
1100 if (filetype < 0 || filetype >= wtap_num_file_types
1101 || dump_open_table[filetype].writing_must_seek)
1107 gboolean wtap_dump_can_compress(int filetype _U_)
1113 gboolean wtap_dump_has_name_resolution(int filetype)
1115 if (filetype < 0 || filetype >= wtap_num_file_types
1116 || dump_open_table[filetype].has_name_resolution == FALSE)
1122 static gboolean wtap_dump_open_check(int filetype, int encap, gboolean comressed, int *err);
1123 static wtap_dumper* wtap_dump_alloc_wdh(int filetype, int encap, int snaplen,
1124 gboolean compressed, int *err);
1125 static gboolean wtap_dump_open_finish(wtap_dumper *wdh, int filetype, gboolean compressed, int *err);
1127 static WFILE_T wtap_dump_file_open(wtap_dumper *wdh, const char *filename);
1128 static WFILE_T wtap_dump_file_fdopen(wtap_dumper *wdh, int fd);
1129 static int wtap_dump_file_close(wtap_dumper *wdh);
1131 wtap_dumper* wtap_dump_open(const char *filename, int filetype, int encap,
1132 int snaplen, gboolean compressed, int *err)
1134 return wtap_dump_open_ng(filename, filetype, encap,snaplen, compressed, NULL, NULL, err);
1137 static wtap_dumper *
1138 wtap_dump_init_dumper(int filetype, int encap, int snaplen, gboolean compressed,
1139 wtapng_section_t *shb_hdr, wtapng_iface_descriptions_t *idb_inf, int *err)
1143 /* Allocate a data structure for the output stream. */
1144 wdh = wtap_dump_alloc_wdh(filetype, encap, snaplen, compressed, err);
1146 return NULL; /* couldn't allocate it */
1148 /* Set Section Header Block data */
1149 wdh->shb_hdr = shb_hdr;
1150 /* Set Interface Description Block data */
1151 if ((idb_inf != NULL) && (idb_inf->number_of_interfaces > 0)) {
1152 wdh->number_of_interfaces = idb_inf->number_of_interfaces;
1153 wdh->interface_data = idb_inf->interface_data;
1155 wtapng_if_descr_t descr;
1157 descr.wtap_encap = encap;
1158 descr.time_units_per_second = 1000000; /* default microsecond resolution */
1159 descr.link_type = wtap_wtap_encap_to_pcap_encap(encap);
1160 descr.snap_len = snaplen;
1161 descr.opt_comment = NULL;
1162 descr.if_name = g_strdup("Unknown/not available in original file format(libpcap)");
1163 descr.if_description = NULL;
1165 descr.if_tsresol = 6;
1166 descr.if_filter_str= NULL;
1167 descr.bpf_filter_len= 0;
1168 descr.if_filter_bpf_bytes= NULL;
1170 descr.if_fcslen = -1;
1171 descr.num_stat_entries = 0; /* Number of ISB:s */
1172 descr.interface_statistics = NULL;
1173 wdh->number_of_interfaces= 1;
1174 wdh->interface_data= g_array_new(FALSE, FALSE, sizeof(wtapng_if_descr_t));
1175 g_array_append_val(wdh->interface_data, descr);
1180 wtap_dumper* wtap_dump_open_ng(const char *filename, int filetype, int encap,
1181 int snaplen, gboolean compressed, wtapng_section_t *shb_hdr, wtapng_iface_descriptions_t *idb_inf, int *err)
1186 /* Check whether we can open a capture file with that file type
1187 and that encapsulation. */
1188 if (!wtap_dump_open_check(filetype, encap, compressed, err))
1191 /* Allocate and initialize a data structure for the output stream. */
1192 wdh = wtap_dump_init_dumper(filetype, encap, snaplen, compressed,
1193 shb_hdr, idb_inf, err);
1197 /* "-" means stdout */
1198 if (strcmp(filename, "-") == 0) {
1200 *err = EINVAL; /* XXX - return a Wiretap error code for this */
1202 return NULL; /* compress won't work on stdout */
1205 if (_setmode(fileno(stdout), O_BINARY) == -1) {
1206 /* "Should not happen" */
1209 return NULL; /* couldn't put standard output in binary mode */
1214 /* In case "fopen()" fails but doesn't set "errno", set "errno"
1215 to a generic "the open failed" error. */
1216 errno = WTAP_ERR_CANT_OPEN;
1217 fh = wtap_dump_file_open(wdh, filename);
1221 return NULL; /* can't create file */
1226 if (!wtap_dump_open_finish(wdh, filetype, compressed, err)) {
1227 /* Get rid of the file we created; we couldn't finish
1229 if (wdh->fh != stdout) {
1230 wtap_dump_file_close(wdh);
1231 ws_unlink(filename);
1239 wtap_dumper* wtap_dump_fdopen(int fd, int filetype, int encap, int snaplen,
1240 gboolean compressed, int *err)
1242 return wtap_dump_fdopen_ng(fd, filetype, encap, snaplen, compressed, NULL, NULL, err);
1245 wtap_dumper* wtap_dump_fdopen_ng(int fd, int filetype, int encap, int snaplen,
1246 gboolean compressed, wtapng_section_t *shb_hdr, wtapng_iface_descriptions_t *idb_inf, int *err)
1251 /* Check whether we can open a capture file with that file type
1252 and that encapsulation. */
1253 if (!wtap_dump_open_check(filetype, encap, compressed, err))
1256 /* Allocate and initialize a data structure for the output stream. */
1257 wdh = wtap_dump_init_dumper(filetype, encap, snaplen, compressed,
1258 shb_hdr, idb_inf, err);
1264 if (_setmode(fileno(stdout), O_BINARY) == -1) {
1265 /* "Should not happen" */
1268 return NULL; /* couldn't put standard output in binary mode */
1273 /* In case "fopen()" fails but doesn't set "errno", set "errno"
1274 to a generic "the open failed" error. */
1275 errno = WTAP_ERR_CANT_OPEN;
1276 fh = wtap_dump_file_fdopen(wdh, fd);
1280 return NULL; /* can't create standard I/O stream */
1284 if (!wtap_dump_open_finish(wdh, filetype, compressed, err)) {
1285 wtap_dump_file_close(wdh);
1292 static gboolean wtap_dump_open_check(int filetype, int encap, gboolean compressed, int *err)
1294 if (!wtap_dump_can_open(filetype)) {
1295 /* Invalid type, or type we don't know how to write. */
1296 *err = WTAP_ERR_UNSUPPORTED_FILE_TYPE;
1300 /* OK, we know how to write that type; can we write the specified
1301 encapsulation type? */
1302 *err = (*dump_open_table[filetype].can_write_encap)(encap);
1306 /* if compression is wanted, do we support this for this filetype? */
1307 if(compressed && !wtap_dump_can_compress(filetype)) {
1308 *err = WTAP_ERR_COMPRESSION_NOT_SUPPORTED;
1312 *err = (*dump_open_table[filetype].can_write_encap)(encap);
1316 /* All systems go! */
1320 static wtap_dumper* wtap_dump_alloc_wdh(int filetype, int encap, int snaplen,
1321 gboolean compressed, int *err)
1325 wdh = (wtap_dumper *)g_malloc0(sizeof (wtap_dumper));
1331 wdh->file_type = filetype;
1332 wdh->snaplen = snaplen;
1334 wdh->compressed = compressed;
1338 static gboolean wtap_dump_open_finish(wtap_dumper *wdh, int filetype, gboolean compressed, int *err)
1343 /* Can we do a seek on the file descriptor?
1344 If not, note that fact. */
1348 fd = fileno((FILE *)wdh->fh);
1349 if (lseek(fd, 1, SEEK_CUR) == -1)
1352 /* Undo the seek. */
1353 lseek(fd, 0, SEEK_SET);
1358 /* If this file type requires seeking, and we can't seek, fail. */
1359 if (dump_open_table[filetype].writing_must_seek && cant_seek) {
1360 *err = WTAP_ERR_CANT_WRITE_TO_PIPE;
1364 /* Now try to open the file for writing. */
1365 if (!(*dump_open_table[filetype].dump_open)(wdh, err)) {
1369 return TRUE; /* success! */
1372 gboolean wtap_dump(wtap_dumper *wdh, const struct wtap_pkthdr *phdr,
1373 const union wtap_pseudo_header *pseudo_header, const guint8 *pd, int *err)
1375 return (wdh->subtype_write)(wdh, phdr, pseudo_header, pd, err);
1378 void wtap_dump_flush(wtap_dumper *wdh)
1381 if(wdh->compressed) {
1382 gzwfile_flush((GZWFILE_T)wdh->fh);
1386 fflush((FILE *)wdh->fh);
1390 gboolean wtap_dump_close(wtap_dumper *wdh, int *err)
1392 gboolean ret = TRUE;
1394 if (wdh->subtype_close != NULL) {
1395 /* There's a close routine for this dump stream. */
1396 if (!(wdh->subtype_close)(wdh, err))
1399 errno = WTAP_ERR_CANT_CLOSE;
1400 /* Don't close stdout */
1401 if (wdh->fh != stdout) {
1402 if (wtap_dump_file_close(wdh) == EOF) {
1404 /* The per-format close function succeeded,
1405 but the fclose didn't. Save the reason
1406 why, if our caller asked for it. */
1413 /* as we don't close stdout, at least try to flush it */
1414 wtap_dump_flush(wdh);
1416 if (wdh->priv != NULL)
1422 gint64 wtap_get_bytes_dumped(wtap_dumper *wdh)
1424 return wdh->bytes_dumped;
1427 void wtap_set_bytes_dumped(wtap_dumper *wdh, gint64 bytes_dumped)
1429 wdh->bytes_dumped = bytes_dumped;
1432 gboolean wtap_dump_set_addrinfo_list(wtap_dumper *wdh, struct addrinfo *addrinfo_list)
1434 if (!wdh || wdh->file_type < 0 || wdh->file_type >= wtap_num_file_types
1435 || dump_open_table[wdh->file_type].has_name_resolution == FALSE)
1437 wdh->addrinfo_list = addrinfo_list;
1441 /* internally open a file for writing (compressed or not) */
1443 static WFILE_T wtap_dump_file_open(wtap_dumper *wdh, const char *filename)
1445 if(wdh->compressed) {
1446 return gzwfile_open(filename);
1448 return ws_fopen(filename, "wb");
1452 static WFILE_T wtap_dump_file_open(wtap_dumper *wdh _U_, const char *filename)
1454 return ws_fopen(filename, "wb");
1458 /* internally open a file for writing (compressed or not) */
1460 static WFILE_T wtap_dump_file_fdopen(wtap_dumper *wdh, int fd)
1462 if(wdh->compressed) {
1463 return gzwfile_fdopen(fd);
1465 return fdopen(fd, "wb");
1469 static WFILE_T wtap_dump_file_fdopen(wtap_dumper *wdh _U_, int fd)
1471 return fdopen(fd, "wb");
1475 /* internally writing raw bytes (compressed or not) */
1476 gboolean wtap_dump_file_write(wtap_dumper *wdh, const void *buf, size_t bufsize,
1482 if (wdh->compressed) {
1483 nwritten = gzwfile_write((GZWFILE_T)wdh->fh, buf, (unsigned) bufsize);
1485 * gzwfile_write() returns 0 on error.
1487 if (nwritten == 0) {
1488 *err = gzwfile_geterr((GZWFILE_T)wdh->fh);
1494 nwritten = fwrite(buf, 1, bufsize, (FILE *)wdh->fh);
1496 * At least according to the Mac OS X man page,
1497 * this can return a short count on an error.
1499 if (nwritten != bufsize) {
1500 if (ferror((FILE *)wdh->fh))
1503 *err = WTAP_ERR_SHORT_WRITE;
1510 /* internally close a file for writing (compressed or not) */
1511 static int wtap_dump_file_close(wtap_dumper *wdh)
1514 if(wdh->compressed) {
1515 return gzwfile_close((GZWFILE_T)wdh->fh);
1519 return fclose((FILE *)wdh->fh);