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"
93 * Add an extension, and all compressed versions thereof, to a GSList
96 static GSList
*add_extensions(GSList
*extensions
, const gchar
*extension
,
97 GSList
*compressed_file_extensions
)
99 GSList
*compressed_file_extension
;
102 * Add the specified extension.
104 extensions
= g_slist_append(extensions
, g_strdup(extension
));
107 * Now add the extensions for compressed-file versions of
110 for (compressed_file_extension
= compressed_file_extensions
;
111 compressed_file_extension
!= NULL
;
112 compressed_file_extension
= g_slist_next(compressed_file_extension
)) {
113 extensions
= g_slist_append(extensions
,
114 g_strdup_printf("%s.%s", extension
,
115 (gchar
*)compressed_file_extension
->data
));
122 * File types that can be identified by file extensions.
124 static const struct file_extension_info file_type_extensions_base
[] = {
125 { "Wireshark/tcpdump/... - pcap", "pcap;cap;dmp" },
126 { "Wireshark/... - pcapng", "pcapng;ntar" },
127 { "Network Monitor, Surveyor, NetScaler", "cap" },
128 { "InfoVista 5View capture", "5vw" },
129 { "Sniffer (DOS)", "cap;enc;trc;fdc;syc" },
130 { "NetXRay, Sniffer (Windows)", "cap;caz" },
131 { "Endace ERF capture", "erf" },
132 { "EyeSDN USB S0/E1 ISDN trace format", "trc" },
133 { "HP-UX nettl trace", "trc0;trc1" },
134 { "Network Instruments Observer", "bfr" },
135 { "Novell LANalyzer", "tr1" },
136 { "Tektronix K12xx 32-bit .rf5 format", "rf5" },
137 { "WildPackets *Peek", "pkt;tpc;apc;wpz" },
138 { "Catapult DCT2000 trace (.out format)", "out" },
139 { "MPEG files", "mpg;mp3" },
140 { "CommView", "ncf" },
141 { "Symbian OS btsnoop", "log" },
142 { "Transport-Neutral Encapsulation Format", "tnef" },
143 { "XML files (including Gammu DCT3 traces)", "xml" },
144 { "OS X PacketLogger", "pklg" },
145 { "Daintree SNA", "dcf" },
146 { "JPEG/JFIF files", "jpg;jpeg;jfif" },
147 { "IPFIX File Format", "pfx;ipfix" },
148 { "Aethra .aps file", "aps" },
149 { "MPEG2 transport stream", "mp2t;ts;mpg" },
150 { "Ixia IxVeriWave .vwr Raw 802.11 Capture", "vwr" },
151 { "CAM Inspector file", "camins" },
154 #define N_FILE_TYPE_EXTENSIONS (sizeof file_type_extensions_base / sizeof file_type_extensions_base[0])
156 static const struct file_extension_info
* file_type_extensions
= NULL
;
158 static GArray
* file_type_extensions_arr
= NULL
;
160 /* initialize the extensions array if it has not been initialized yet */
161 static void init_file_type_extensions(void) {
163 if (file_type_extensions_arr
) return;
165 file_type_extensions_arr
= g_array_new(FALSE
,TRUE
,sizeof(struct file_extension_info
));
167 g_array_append_vals(file_type_extensions_arr
,file_type_extensions_base
,N_FILE_TYPE_EXTENSIONS
);
169 file_type_extensions
= (struct file_extension_info
*)(void *)file_type_extensions_arr
->data
;
172 void wtap_register_file_type_extension(const struct file_extension_info
*ei
) {
173 init_file_type_extensions();
175 g_array_append_val(file_type_extensions_arr
,*ei
);
177 file_type_extensions
= (const struct file_extension_info
*)(void *)file_type_extensions_arr
->data
;
180 int wtap_get_num_file_type_extensions(void)
182 return file_type_extensions_arr
->len
;
185 const char *wtap_get_file_extension_type_name(int extension_type
)
187 return file_type_extensions
[extension_type
].name
;
190 static GSList
*add_extensions_for_file_extensions_type(int extension_type
,
191 GSList
*extensions
, GSList
*compressed_file_extensions
)
193 gchar
**extensions_set
, **extensionp
, *extension
;
196 * Split the extension-list string into a set of extensions.
198 extensions_set
= g_strsplit(file_type_extensions
[extension_type
].extensions
,
202 * Add each of those extensions to the list.
204 for (extensionp
= extensions_set
; *extensionp
!= NULL
; extensionp
++) {
205 extension
= *extensionp
;
208 * Add the extension, and all compressed variants
211 extensions
= add_extensions(extensions
, extension
,
212 compressed_file_extensions
);
215 g_strfreev(extensions_set
);
219 /* Return a list of file extensions that are used by the specified file
222 All strings in the list are allocated with g_malloc() and must be freed
224 GSList
*wtap_get_file_extension_type_extensions(guint extension_type
)
226 GSList
*compressed_file_extensions
;
229 if (extension_type
>= file_type_extensions_arr
->len
)
230 return NULL
; /* not a valid extension type */
232 extensions
= NULL
; /* empty list, to start with */
235 * Get the list of compressed-file extensions.
237 compressed_file_extensions
= wtap_get_compressed_file_extensions();
240 * Add all this file extension type's extensions, with compressed
243 extensions
= add_extensions_for_file_extensions_type(extension_type
,
244 extensions
, compressed_file_extensions
);
246 g_slist_free(compressed_file_extensions
);
250 /* Return a list of all extensions that are used by all file types,
251 including compressed extensions, e.g. not just "pcap" but also
252 "pcap.gz" if we can read gzipped files.
254 All strings in the list are allocated with g_malloc() and must be freed
256 GSList
*wtap_get_all_file_extensions_list(void)
258 GSList
*compressed_file_extensions
;
262 init_file_type_extensions();
264 extensions
= NULL
; /* empty list, to start with */
267 * Get the list of compressed-file extensions.
269 compressed_file_extensions
= wtap_get_compressed_file_extensions();
271 for (i
= 0; i
< file_type_extensions_arr
->len
; i
++) {
273 * Add all this file extension type's extensions, with
274 * compressed variants.
276 extensions
= add_extensions_for_file_extensions_type(i
,
277 extensions
, compressed_file_extensions
);
280 g_slist_free(compressed_file_extensions
);
284 /* The open_file_* routines should return:
286 * -1 on an I/O error;
288 * 1 if the file they're reading is one of the types it handles;
290 * 0 if the file they're reading isn't the type they're checking for.
292 * If the routine handles this type of file, it should set the "file_type"
293 * field in the "struct wtap" to the type of the file.
295 * Note that the routine does not have to free the private data pointer on
296 * error. The caller takes care of that by calling wtap_close on error.
297 * (See https://bugs.wireshark.org/bugzilla/show_bug.cgi?id=8518)
299 * However, the caller does have to free the private data pointer when
300 * returning 0, since the next file type will be called and will likely
301 * just overwrite the pointer.
303 * Put the trace files that are merely saved telnet-sessions last, since it's
304 * possible that you could have captured someone a router telnet-session
305 * using another tool. So, a libpcap trace of an toshiba "snoop" session
306 * should be discovered as a libpcap file, not a toshiba file.
310 static wtap_open_routine_t open_routines_base
[] = {
311 /* Files that have magic bytes in fixed locations. These
312 * are easy to identify.
326 network_instruments_open
,
330 catapult_dct2000_open
,
331 ber_open
, /* XXX - this is really a heuristic */
335 packetlogger_open
, /* This type does not have a magic number, but its
336 * files are sometimes grabbed by mpeg_open. */
343 /* Files that don't have magic bytes at a fixed location,
344 * but that instead require a heuristic of some sort to
345 * identify them. This includes the ASCII trace files that
346 * would be, for example, saved copies of a Telnet session
350 /* I put NetScreen *before* erf, because there were some
351 * false positives with my test-files (Sake Blok, July 2007)
353 * I put VWR *after* ERF, because there were some cases where
354 * ERF files were misidentified as vwr files (Stephen
355 * Donnelly, August 2013; see bug 9054)
378 #define N_FILE_TYPES (sizeof open_routines_base / sizeof open_routines_base[0])
380 static wtap_open_routine_t
* open_routines
= NULL
;
382 static GArray
* open_routines_arr
= NULL
;
385 /* initialize the open routines array if it has not been initialized yet */
386 static void init_open_routines(void) {
388 if (open_routines_arr
) return;
390 open_routines_arr
= g_array_new(FALSE
,TRUE
,sizeof(wtap_open_routine_t
));
392 g_array_append_vals(open_routines_arr
,open_routines_base
,N_FILE_TYPES
);
394 open_routines
= (wtap_open_routine_t
*)(void *)open_routines_arr
->data
;
397 void wtap_register_open_routine(wtap_open_routine_t open_routine
, gboolean has_magic
) {
398 init_open_routines();
401 g_array_prepend_val(open_routines_arr
,open_routine
);
403 g_array_append_val(open_routines_arr
,open_routine
);
405 open_routines
= (wtap_open_routine_t
*)(void *)open_routines_arr
->data
;
409 * Visual C++ on Win32 systems doesn't define these. (Old UNIX systems don't
410 * define them either.)
412 * Visual C++ on Win32 systems doesn't define S_IFIFO, it defines _S_IFIFO.
415 #define S_ISREG(mode) (((mode) & S_IFMT) == S_IFREG)
418 #define S_IFIFO _S_IFIFO
421 #define S_ISFIFO(mode) (((mode) & S_IFMT) == S_IFIFO)
424 #define S_ISDIR(mode) (((mode) & S_IFMT) == S_IFDIR)
427 /* Opens a file and prepares a wtap struct.
428 If "do_random" is TRUE, it opens the file twice; the second open
429 allows the application to do random-access I/O without moving
430 the seek offset for sequential I/O, which is used by Wireshark
431 so that it can do sequential I/O to a capture file that's being
432 written to as new packets arrive independently of random I/O done
433 to display protocol trees for packets when they're selected. */
434 wtap
* wtap_open_offline(const char *filename
, int *err
, char **err_info
,
441 gboolean use_stdin
= FALSE
;
443 /* open standard input if filename is '-' */
444 if (strcmp(filename
, "-") == 0)
447 /* First, make sure the file is valid */
449 if (ws_fstat64(0, &statb
) < 0) {
454 if (ws_stat64(filename
, &statb
) < 0) {
459 if (S_ISFIFO(statb
.st_mode
)) {
461 * Opens of FIFOs are allowed only when not opening
464 * XXX - currently, we do seeking when trying to find
465 * out the file type, so we don't actually support
466 * opening FIFOs. However, we may eventually
467 * do buffering that allows us to do at least some
468 * file type determination even on pipes, so we
469 * allow FIFO opens and let things fail later when
473 *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 * We need two independent descriptors for random access, so
491 * they have different file positions. If we're opening the
492 * standard input, we can only dup it to get additional
493 * descriptors, so we can't have two independent descriptors,
494 * and thus can't do random access.
496 if (use_stdin
&& do_random
) {
497 *err
= WTAP_ERR_RANDOM_OPEN_STDIN
;
502 wth
= (wtap
*)g_malloc0(sizeof(wtap
));
505 errno
= WTAP_ERR_CANT_OPEN
;
508 * We dup FD 0, so that we don't have to worry about
509 * a file_close of wth->fh closing the standard
510 * input of the process.
519 if (_setmode(fd
, O_BINARY
) == -1) {
520 /* "Shouldn't happen" */
526 if (!(wth
->fh
= file_fdopen(fd
))) {
533 if (!(wth
->fh
= file_open(filename
))) {
541 if (!(wth
->random_fh
= file_open(filename
))) {
548 wth
->random_fh
= NULL
;
551 wth
->file_encap
= WTAP_ENCAP_UNKNOWN
;
552 wth
->subtype_sequential_close
= NULL
;
553 wth
->subtype_close
= NULL
;
554 wth
->tsprecision
= WTAP_FILE_TSPREC_USEC
;
557 init_open_routines();
558 if (wth
->random_fh
) {
559 wth
->fast_seek
= g_ptr_array_new();
561 file_set_random_access(wth
->fh
, FALSE
, wth
->fast_seek
);
562 file_set_random_access(wth
->random_fh
, TRUE
, wth
->fast_seek
);
565 /* Try all file types */
566 for (i
= 0; i
< open_routines_arr
->len
; i
++) {
567 /* Seek back to the beginning of the file; the open routine
568 for the previous file type may have left the file
569 position somewhere other than the beginning, and the
570 open routine for this file type will probably want
571 to start reading at the beginning.
573 Initialize the data offset while we're at it. */
574 if (file_seek(wth
->fh
, 0, SEEK_SET
, err
) == -1) {
575 /* I/O error - give up */
580 switch ((*open_routines
[i
])(wth
, err
, err_info
)) {
583 /* I/O error - give up */
588 /* No I/O error, but not that type of file */
592 /* We found the file type */
597 /* Well, it's not one of the types of file we know about. */
599 *err
= WTAP_ERR_FILE_UNKNOWN_FORMAT
;
603 wth
->frame_buffer
= (struct Buffer
*)g_malloc(sizeof(struct Buffer
));
604 buffer_init(wth
->frame_buffer
, 1500);
606 if(wth
->file_type_subtype
== WTAP_FILE_TYPE_SUBTYPE_PCAP
){
608 wtapng_if_descr_t descr
;
610 descr
.wtap_encap
= wth
->file_encap
;
611 descr
.time_units_per_second
= 1000000; /* default microsecond resolution */
612 descr
.link_type
= wtap_wtap_encap_to_pcap_encap(wth
->file_encap
);
613 descr
.snap_len
= wth
->snapshot_length
;
614 descr
.opt_comment
= NULL
;
615 descr
.if_name
= NULL
;
616 descr
.if_description
= NULL
;
618 descr
.if_tsresol
= 6;
619 descr
.if_filter_str
= NULL
;
620 descr
.bpf_filter_len
= 0;
621 descr
.if_filter_bpf_bytes
= NULL
;
623 descr
.if_fcslen
= -1;
624 descr
.num_stat_entries
= 0; /* Number of ISB:s */
625 descr
.interface_statistics
= NULL
;
626 wth
->number_of_interfaces
= 1;
627 wth
->interface_data
= g_array_new(FALSE
, FALSE
, sizeof(wtapng_if_descr_t
));
628 g_array_append_val(wth
->interface_data
, descr
);
635 * Given the pathname of the file we just closed with wtap_fdclose(), attempt
636 * to reopen that file and assign the new file descriptor(s) to the sequential
637 * stream and, if do_random is TRUE, to the random stream. Used on Windows
638 * after the rename of a file we had open was done or if the rename of a
639 * file on top of a file we had open failed.
641 * This is only required by Wireshark, not TShark, and, at the point that
642 * Wireshark is doing this, the sequential stream is closed, and the
643 * random stream is open, so this refuses to open pipes, and only
644 * reopens the random stream.
647 wtap_fdreopen(wtap
*wth
, const char *filename
, int *err
)
652 * We need two independent descriptors for random access, so
653 * they have different file positions. If we're opening the
654 * standard input, we can only dup it to get additional
655 * descriptors, so we can't have two independent descriptors,
656 * and thus can't do random access.
658 if (strcmp(filename
, "-") == 0) {
659 *err
= WTAP_ERR_RANDOM_OPEN_STDIN
;
663 /* First, make sure the file is valid */
664 if (ws_stat64(filename
, &statb
) < 0) {
668 if (S_ISFIFO(statb
.st_mode
)) {
670 * Opens of FIFOs are not allowed; see above.
672 *err
= WTAP_ERR_RANDOM_OPEN_PIPE
;
674 } else if (S_ISDIR(statb
.st_mode
)) {
676 * Return different errors for "this is a directory"
677 * and "this is some random special file type", so
678 * the user can get a potentially more helpful error.
682 } else if (! S_ISREG(statb
.st_mode
)) {
683 *err
= WTAP_ERR_NOT_REGULAR_FILE
;
688 errno
= WTAP_ERR_CANT_OPEN
;
689 if (!file_fdreopen(wth
->random_fh
, filename
)) {
696 /* Table of the file types we know about.
697 Entries must be sorted by WTAP_FILE_TYPE_SUBTYPE_xxx values in ascending order */
698 static const struct file_type_subtype_info dump_open_table_base
[] = {
699 /* WTAP_FILE_TYPE_SUBTYPE_UNKNOWN (only used internally for initialization) */
700 { NULL
, NULL
, NULL
, NULL
,
704 /* WTAP_FILE_TYPE_SUBTYPE_PCAP */
705 /* Gianluca Varenni suggests that we add "deprecated" to the description. */
706 { "Wireshark/tcpdump/... - pcap", "pcap", "pcap", "cap;dmp",
708 libpcap_dump_can_write_encap
, libpcap_dump_open
},
710 /* WTAP_FILE_TYPE_SUBTYPE_PCAPNG */
711 { "Wireshark/... - pcapng", "pcapng", "pcapng", "ntar",
712 FALSE
, TRUE
, WTAP_COMMENT_PER_SECTION
|WTAP_COMMENT_PER_INTERFACE
|WTAP_COMMENT_PER_PACKET
,
713 pcapng_dump_can_write_encap
, pcapng_dump_open
},
715 /* WTAP_FILE_TYPE_SUBTYPE_PCAP_NSEC */
716 { "Wireshark - nanosecond libpcap", "nseclibpcap", "pcap", "cap;dmp",
718 libpcap_dump_can_write_encap
, libpcap_dump_open
},
720 /* WTAP_FILE_TYPE_SUBTYPE_PCAP_AIX */
721 { "AIX tcpdump - libpcap", "aixlibpcap", "pcap", "cap;dmp",
725 /* WTAP_FILE_TYPE_SUBTYPE_PCAP_SS991029 */
726 { "Modified tcpdump - libpcap", "modlibpcap", "pcap", "cap;dmp",
728 libpcap_dump_can_write_encap
, libpcap_dump_open
},
730 /* WTAP_FILE_TYPE_SUBTYPE_PCAP_NOKIA */
731 { "Nokia tcpdump - libpcap ", "nokialibpcap", "pcap", "cap;dmp",
733 libpcap_dump_can_write_encap
, libpcap_dump_open
},
735 /* WTAP_FILE_TYPE_SUBTYPE_PCAP_SS990417 */
736 { "RedHat 6.1 tcpdump - libpcap", "rh6_1libpcap", "pcap", "cap;dmp",
738 libpcap_dump_can_write_encap
, libpcap_dump_open
},
740 /* WTAP_FILE_TYPE_SUBTYPE_PCAP_SS990915 */
741 { "SuSE 6.3 tcpdump - libpcap", "suse6_3libpcap", "pcap", "cap;dmp",
743 libpcap_dump_can_write_encap
, libpcap_dump_open
},
745 /* WTAP_FILE_TYPE_SUBTYPE_5VIEWS */
746 { "InfoVista 5View capture", "5views", "5vw", NULL
,
748 _5views_dump_can_write_encap
, _5views_dump_open
},
750 /* WTAP_FILE_TYPE_SUBTYPE_IPTRACE_1_0 */
751 { "AIX iptrace 1.0", "iptrace_1", NULL
, NULL
,
755 /* WTAP_FILE_TYPE_SUBTYPE_IPTRACE_2_0 */
756 { "AIX iptrace 2.0", "iptrace_2", NULL
, NULL
,
760 /* WTAP_FILE_TYPE_SUBTYPE_BER */
761 { "ASN.1 Basic Encoding Rules", "ber", NULL
, NULL
,
765 /* WTAP_FILE_TYPE_SUBTYPE_HCIDUMP */
766 { "Bluetooth HCI dump", "hcidump", NULL
, NULL
,
770 /* WTAP_FILE_TYPE_SUBTYPE_CATAPULT_DCT2000 */
771 { "Catapult DCT2000 trace (.out format)", "dct2000", "out", NULL
,
773 catapult_dct2000_dump_can_write_encap
, catapult_dct2000_dump_open
},
775 /* WTAP_FILE_TYPE_SUBTYPE_NETXRAY_OLD */
776 { "Cinco Networks NetXRay 1.x", "netxray1", "cap", NULL
,
780 /* WTAP_FILE_TYPE_SUBTYPE_NETXRAY_1_0 */
781 { "Cinco Networks NetXRay 2.0 or later", "netxray2", "cap", NULL
,
785 /* WTAP_FILE_TYPE_SUBTYPE_COSINE */
786 { "CoSine IPSX L2 capture", "cosine", "txt", NULL
,
790 /* WTAP_FILE_TYPE_SUBTYPE_CSIDS */
791 { "CSIDS IPLog", "csids", NULL
, NULL
,
795 /* WTAP_FILE_TYPE_SUBTYPE_DBS_ETHERWATCH */
796 { "DBS Etherwatch (VMS)", "etherwatch", "txt", NULL
,
800 /* WTAP_FILE_TYPE_SUBTYPE_ERF */
801 { "Endace ERF capture", "erf", "erf", NULL
,
803 erf_dump_can_write_encap
, erf_dump_open
},
805 /* WTAP_FILE_TYPE_SUBTYPE_EYESDN */
806 { "EyeSDN USB S0/E1 ISDN trace format", "eyesdn", "trc", NULL
,
808 eyesdn_dump_can_write_encap
, eyesdn_dump_open
},
810 /* WTAP_FILE_TYPE_SUBTYPE_NETTL */
811 { "HP-UX nettl trace", "nettl", "trc0", "trc1",
813 nettl_dump_can_write_encap
, nettl_dump_open
},
815 /* WTAP_FILE_TYPE_SUBTYPE_ISERIES */
816 { "IBM iSeries comm. trace (ASCII)", "iseries_ascii", "txt", NULL
,
820 /* WTAP_FILE_TYPE_SUBTYPE_ISERIES_UNICODE */
821 { "IBM iSeries comm. trace (UNICODE)", "iseries_unicode", "txt", NULL
,
825 /* WTAP_FILE_TYPE_SUBTYPE_I4BTRACE */
826 { "I4B ISDN trace", "i4btrace", NULL
, NULL
,
830 /* WTAP_FILE_TYPE_SUBTYPE_ASCEND */
831 { "Lucent/Ascend access server trace", "ascend", "txt", NULL
,
835 /* WTAP_FILE_TYPE_SUBTYPE_NETMON_1_x */
836 { "Microsoft NetMon 1.x", "netmon1", "cap", NULL
,
838 netmon_dump_can_write_encap_1_x
, netmon_dump_open
},
840 /* WTAP_FILE_TYPE_SUBTYPE_NETMON_2_x */
841 { "Microsoft NetMon 2.x", "netmon2", "cap", NULL
,
843 netmon_dump_can_write_encap_2_x
, netmon_dump_open
},
845 /* WTAP_FILE_TYPE_SUBTYPE_NGSNIFFER_UNCOMPRESSED */
846 { "Sniffer (DOS)", "ngsniffer", "cap", "enc;trc;fdc;syc",
848 ngsniffer_dump_can_write_encap
, ngsniffer_dump_open
},
850 /* WTAP_FILE_TYPE_SUBTYPE_NGSNIFFER_COMPRESSED */
851 { "Sniffer (DOS), compressed", "ngsniffer_comp", "cap", "enc;trc;fdc;syc",
855 /* WTAP_FILE_TYPE_SUBTYPE_NETXRAY_1_1 */
856 { "NetXray, Sniffer (Windows) 1.1", "ngwsniffer_1_1", "cap", NULL
,
858 netxray_dump_can_write_encap_1_1
, netxray_dump_open_1_1
},
860 /* WTAP_FILE_TYPE_SUBTYPE_NETXRAY_2_00x */
861 { "Sniffer (Windows) 2.00x", "ngwsniffer_2_0", "cap", "caz",
863 netxray_dump_can_write_encap_2_0
, netxray_dump_open_2_0
},
865 /* WTAP_FILE_TYPE_SUBTYPE_NETWORK_INSTRUMENTS */
866 { "Network Instruments Observer", "niobserver", "bfr", NULL
,
868 network_instruments_dump_can_write_encap
, network_instruments_dump_open
},
870 /* WTAP_FILE_TYPE_SUBTYPE_LANALYZER */
871 { "Novell LANalyzer","lanalyzer", "tr1", NULL
,
873 lanalyzer_dump_can_write_encap
, lanalyzer_dump_open
},
875 /* WTAP_FILE_TYPE_SUBTYPE_PPPDUMP */
876 { "pppd log (pppdump format)", "pppd", NULL
, NULL
,
880 /* WTAP_FILE_TYPE_SUBTYPE_RADCOM */
881 { "RADCOM WAN/LAN analyzer", "radcom", NULL
, NULL
,
885 /* WTAP_FILE_TYPE_SUBTYPE_SNOOP */
886 { "Sun snoop", "snoop", "snoop", "cap",
888 snoop_dump_can_write_encap
, snoop_dump_open
},
890 /* WTAP_FILE_TYPE_SUBTYPE_SHOMITI */
891 { "Shomiti/Finisar Surveyor", "shomiti", "cap", NULL
,
895 /* WTAP_FILE_TYPE_SUBTYPE_VMS */
896 { "TCPIPtrace (VMS)", "tcpiptrace", "txt", NULL
,
900 /* WTAP_FILE_TYPE_SUBTYPE_K12 */
901 { "Tektronix K12xx 32-bit .rf5 format", "rf5", "rf5", NULL
,
903 k12_dump_can_write_encap
, k12_dump_open
},
905 /* WTAP_FILE_TYPE_SUBTYPE_TOSHIBA */
906 { "Toshiba Compact ISDN Router snoop", "toshiba", "txt", NULL
,
910 /* WTAP_FILE_TYPE_SUBTYPE_VISUAL_NETWORKS */
911 { "Visual Networks traffic capture", "visual", NULL
, NULL
,
913 visual_dump_can_write_encap
, visual_dump_open
},
915 /* WTAP_FILE_TYPE_SUBTYPE_PEEKCLASSIC_V56 */
916 { "WildPackets classic (V5 and V6)", "peekclassic56", "pkt", "tpc;apc;wpz",
920 /* WTAP_FILE_TYPE_SUBTYPE_PEEKCLASSIC_V7 */
921 { "WildPackets classic (V7)", "peekclassic7", "pkt", "tpc;apc;wpz",
925 /* WTAP_FILE_TYPE_SUBTYPE_PEEKTAGGED */
926 { "WildPackets tagged", "peektagged", "pkt", "tpc;apc;wpz",
930 /* WTAP_FILE_TYPE_SUBTYPE_MPEG */
931 { "MPEG", "mpeg", "mpeg", "mpg;mp3",
935 /* WTAP_FILE_TYPE_SUBTYPE_K12TEXT */
936 { "K12 text file", "k12text", "txt", NULL
,
938 k12text_dump_can_write_encap
, k12text_dump_open
},
940 /* WTAP_FILE_TYPE_SUBTYPE_NETSCREEN */
941 { "NetScreen snoop text file", "netscreen", "txt", NULL
,
945 /* WTAP_FILE_TYPE_SUBTYPE_COMMVIEW */
946 { "TamoSoft CommView", "commview", "ncf", NULL
,
948 commview_dump_can_write_encap
, commview_dump_open
},
950 /* WTAP_FILE_TYPE_SUBTYPE_BTSNOOP */
951 { "Symbian OS btsnoop", "btsnoop", "log", NULL
,
953 btsnoop_dump_can_write_encap
, btsnoop_dump_open_h4
},
955 /* WTAP_FILE_TYPE_SUBTYPE_TNEF */
956 { "Transport-Neutral Encapsulation Format", "tnef", NULL
, NULL
,
960 /* WTAP_FILE_TYPE_SUBTYPE_DCT3TRACE */
961 { "Gammu DCT3 trace", "dct3trace", "xml", NULL
,
965 /* WTAP_FILE_TYPE_SUBTYPE_PACKETLOGGER */
966 { "PacketLogger", "pklg", "pklg", NULL
,
970 /* WTAP_FILE_TYPE_SUBTYPE_DAINTREE_SNA */
971 { "Daintree SNA", "dsna", "dcf", NULL
,
975 /* WTAP_FILE_TYPE_SUBTYPE_NETSCALER_1_0 */
976 { "NetScaler Trace (Version 1.0)", "nstrace10", NULL
, NULL
,
978 nstrace_10_dump_can_write_encap
, nstrace_dump_open
},
980 /* WTAP_FILE_TYPE_SUBTYPE_NETSCALER_2_0 */
981 { "NetScaler Trace (Version 2.0)", "nstrace20", "cap", NULL
,
983 nstrace_20_dump_can_write_encap
, nstrace_dump_open
},
985 /* WTAP_FILE_TYPE_SUBTYPE_JPEG_JFIF */
986 { "JPEG/JFIF", "jpeg", "jpg", "jpeg;jfif",
990 /* WTAP_FILE_TYPE_SUBTYPE_IPFIX */
991 { "IPFIX File Format", "ipfix", "pfx", "ipfix",
995 /* WTAP_ENCAP_MIME */
996 { "MIME File Format", "mime", NULL
, NULL
,
1000 /* WTAP_FILE_TYPE_SUBTYPE_AETHRA */
1001 { "Aethra .aps file", "aethra", "aps", NULL
,
1005 /* WTAP_FILE_TYPE_SUBTYPE_MPEG_2_TS */
1006 { "MPEG2 transport stream", "mp2t", "mp2t", "ts;mpg",
1010 /* WTAP_FILE_TYPE_SUBTYPE_VWR_80211 */
1011 { "Ixia IxVeriWave .vwr Raw 802.11 Capture", "vwr80211", "vwr", NULL
,
1015 /* WTAP_FILE_TYPE_SUBTYPE_VWR_ETH */
1016 { "Ixia IxVeriWave .vwr Raw Ethernet Capture", "vwreth", "vwr", NULL
,
1020 /* WTAP_FILE_TYPE_SUBTYPE_CAMINS */
1021 { "CAM Inspector file", "camins", "camins", NULL
,
1025 /* WTAP_FILE_TYPE_SUBTYPE_STANAG_4607 */
1026 { "STANAG 4607 Format", "stanag4607", NULL
, NULL
,
1032 gint wtap_num_file_types_subtypes
= sizeof(dump_open_table_base
) / sizeof(struct file_type_subtype_info
);
1034 static GArray
* dump_open_table_arr
= NULL
;
1035 static const struct file_type_subtype_info
* dump_open_table
= dump_open_table_base
;
1037 /* initialize the file types array if it has not being initialized yet */
1038 static void init_file_types_subtypes(void) {
1040 if (dump_open_table_arr
) return;
1042 dump_open_table_arr
= g_array_new(FALSE
,TRUE
,sizeof(struct file_type_subtype_info
));
1044 g_array_append_vals(dump_open_table_arr
,dump_open_table_base
,wtap_num_file_types_subtypes
);
1046 dump_open_table
= (const struct file_type_subtype_info
*)(void *)dump_open_table_arr
->data
;
1049 int wtap_register_file_type_subtypes(const struct file_type_subtype_info
* fi
) {
1050 init_file_types_subtypes();
1052 g_array_append_val(dump_open_table_arr
,*fi
);
1054 dump_open_table
= (const struct file_type_subtype_info
*)(void *)dump_open_table_arr
->data
;
1056 return wtap_num_file_types_subtypes
++;
1059 int wtap_get_num_file_types_subtypes(void)
1061 return wtap_num_file_types_subtypes
;
1065 * Given a GArray of WTAP_ENCAP_ types, return the per-file encapsulation
1066 * type that would be needed to write out a file with those types. If
1067 * there's only one type, it's that type, otherwise it's
1068 * WTAP_ENCAP_PER_PACKET.
1071 wtap_dump_file_encap_type(const GArray
*file_encaps
)
1075 encap
= WTAP_ENCAP_PER_PACKET
;
1076 if (file_encaps
->len
== 1) {
1077 /* OK, use the one-and-only encapsulation type. */
1078 encap
= g_array_index(file_encaps
, gint
, 0);
1084 wtap_dump_can_write_encap(int filetype
, int encap
)
1086 if (filetype
< 0 || filetype
>= wtap_num_file_types_subtypes
1087 || dump_open_table
[filetype
].can_write_encap
== NULL
)
1090 if ((*dump_open_table
[filetype
].can_write_encap
)(encap
) != 0)
1097 * Return TRUE if a capture with a given GArray of encapsulation types
1098 * and a given bitset of comment types can be written in a specified
1099 * format, and FALSE if it can't.
1102 wtap_dump_can_write_format(int ft
, const GArray
*file_encaps
,
1103 guint32 required_comment_types
)
1108 * Can we write in this format?
1110 if (!wtap_dump_can_open(ft
)) {
1116 * Yes. Can we write out all the required comments in this
1119 if (!wtap_dump_supports_comment_types(ft
, required_comment_types
)) {
1125 * Yes. Is the required per-file encapsulation type supported?
1126 * This might be WTAP_ENCAP_PER_PACKET.
1128 if (!wtap_dump_can_write_encap(ft
, wtap_dump_file_encap_type(file_encaps
))) {
1134 * Yes. Are all the individual encapsulation types supported?
1136 for (i
= 0; i
< file_encaps
->len
; i
++) {
1137 if (!wtap_dump_can_write_encap(ft
,
1138 g_array_index(file_encaps
, int, i
))) {
1139 /* No - one of them isn't. */
1144 /* Yes - we're OK. */
1149 * Return TRUE if we can write a file with the given GArray of
1150 * encapsulation types and the given bitmask of comment types.
1153 wtap_dump_can_write(const GArray
*file_encaps
, guint32 required_comment_types
)
1157 for (ft
= 0; ft
< WTAP_NUM_FILE_TYPES_SUBTYPES
; ft
++) {
1158 /* To save a file with Wiretap, Wiretap has to handle that format,
1159 and its code to handle that format must be able to write a file
1160 with this file's encapsulation types. */
1161 if (wtap_dump_can_write_format(ft
, file_encaps
, required_comment_types
)) {
1162 /* OK, we can write it out in this type. */
1167 /* No, we couldn't save it in any format. */
1172 * Get a GArray of WTAP_FILE_TYPE_SUBTYPE_ values for file types/subtypes
1173 * that can be used to save a file of a given type/subtype with a given
1174 * GArray of encapsulation types and the given bitmask of comment types.
1177 wtap_get_savable_file_types_subtypes(int file_type_subtype
,
1178 const GArray
*file_encaps
, guint32 required_comment_types
)
1180 GArray
*savable_file_types_subtypes
;
1182 int default_file_type_subtype
= -1;
1183 int other_file_type_subtype
= -1;
1185 /* Can we save this file in its own file type/subtype? */
1186 if (wtap_dump_can_write_format(file_type_subtype
, file_encaps
,
1187 required_comment_types
)) {
1188 /* Yes - make that the default file type/subtype. */
1189 default_file_type_subtype
= file_type_subtype
;
1191 /* OK, find the first file type/subtype we *can* save it as. */
1192 default_file_type_subtype
= -1;
1193 for (ft
= 0; ft
< WTAP_NUM_FILE_TYPES_SUBTYPES
; ft
++) {
1194 if (wtap_dump_can_write_format(ft
, file_encaps
,
1195 required_comment_types
)) {
1197 default_file_type_subtype
= ft
;
1202 if (default_file_type_subtype
== -1) {
1203 /* We don't support writing this file as any file type/subtype. */
1207 /* Allocate the array. */
1208 savable_file_types_subtypes
= g_array_new(FALSE
, FALSE
, (guint
)sizeof (int));
1210 /* Put the default file type/subtype first in the list. */
1211 g_array_append_val(savable_file_types_subtypes
, default_file_type_subtype
);
1213 /* If the default is pcap, put pcap-NG right after it if we can
1214 also write it in pcap-NG format; otherwise, if the default is
1215 pcap-NG, put pcap right after it if we can also write it in
1217 if (default_file_type_subtype
== WTAP_FILE_TYPE_SUBTYPE_PCAP
) {
1218 if (wtap_dump_can_write_format(WTAP_FILE_TYPE_SUBTYPE_PCAPNG
, file_encaps
,
1219 required_comment_types
))
1220 other_file_type_subtype
= WTAP_FILE_TYPE_SUBTYPE_PCAPNG
;
1221 } else if (default_file_type_subtype
== WTAP_FILE_TYPE_SUBTYPE_PCAPNG
) {
1222 if (wtap_dump_can_write_format(WTAP_FILE_TYPE_SUBTYPE_PCAP
, file_encaps
,
1223 required_comment_types
))
1224 other_file_type_subtype
= WTAP_FILE_TYPE_SUBTYPE_PCAP
;
1226 if (other_file_type_subtype
!= -1)
1227 g_array_append_val(savable_file_types_subtypes
, other_file_type_subtype
);
1229 /* Add all the other file types/subtypes that work. */
1230 for (ft
= 0; ft
< WTAP_NUM_FILE_TYPES_SUBTYPES
; ft
++) {
1231 if (ft
== WTAP_FILE_TYPE_SUBTYPE_UNKNOWN
)
1232 continue; /* not a real file type */
1233 if (ft
== default_file_type_subtype
|| ft
== other_file_type_subtype
)
1234 continue; /* we've already done this one */
1235 if (wtap_dump_can_write_format(ft
, file_encaps
,
1236 required_comment_types
)) {
1237 /* OK, we can write it out in this type. */
1238 g_array_append_val(savable_file_types_subtypes
, ft
);
1242 return savable_file_types_subtypes
;
1245 /* Name that should be somewhat descriptive. */
1246 const char *wtap_file_type_subtype_string(int file_type_subtype
)
1248 if (file_type_subtype
< 0 || file_type_subtype
>= wtap_num_file_types_subtypes
) {
1249 g_error("Unknown capture file type %d", file_type_subtype
);
1250 /** g_error() does an abort() and thus never returns **/
1253 return dump_open_table
[file_type_subtype
].name
;
1256 /* Name to use in, say, a command-line flag specifying the type/subtype. */
1257 const char *wtap_file_type_subtype_short_string(int file_type_subtype
)
1259 if (file_type_subtype
< 0 || file_type_subtype
>= wtap_num_file_types_subtypes
)
1262 return dump_open_table
[file_type_subtype
].short_name
;
1265 /* Translate a short name to a capture file type/subtype. */
1266 int wtap_short_string_to_file_type_subtype(const char *short_name
)
1268 int file_type_subtype
;
1270 for (file_type_subtype
= 0; file_type_subtype
< wtap_num_file_types_subtypes
; file_type_subtype
++) {
1271 if (dump_open_table
[file_type_subtype
].short_name
!= NULL
&&
1272 strcmp(short_name
, dump_open_table
[file_type_subtype
].short_name
) == 0)
1273 return file_type_subtype
;
1277 * We now call the "libpcap" file format just "pcap", but we
1278 * allow it to be specified as "libpcap" as well, for
1279 * backwards compatibility.
1281 if (strcmp(short_name
, "libpcap") == 0)
1282 return WTAP_FILE_TYPE_SUBTYPE_PCAP
;
1284 return -1; /* no such file type, or we can't write it */
1288 add_extensions_for_file_type_subtype(int file_type_subtype
, GSList
*extensions
,
1289 GSList
*compressed_file_extensions
)
1291 gchar
**extensions_set
, **extensionp
;
1295 * Add the default extension, and all compressed variants of
1298 extensions
= add_extensions(extensions
,
1299 dump_open_table
[file_type_subtype
].default_file_extension
,
1300 compressed_file_extensions
);
1302 if (dump_open_table
[file_type_subtype
].additional_file_extensions
!= NULL
) {
1304 * We have additional extensions; add them.
1306 * First, split the extension-list string into a set of
1309 extensions_set
= g_strsplit(dump_open_table
[file_type_subtype
].additional_file_extensions
,
1313 * Add each of those extensions to the list.
1315 for (extensionp
= extensions_set
; *extensionp
!= NULL
;
1317 extension
= *extensionp
;
1320 * Add the extension, and all compressed variants
1323 extensions
= add_extensions(extensions
, extension
,
1324 compressed_file_extensions
);
1327 g_strfreev(extensions_set
);
1332 /* Return a list of file extensions that are used by the specified file type.
1334 If include_compressed is TRUE, the list will include compressed
1335 extensions, e.g. not just "pcap" but also "pcap.gz" if we can read
1338 All strings in the list are allocated with g_malloc() and must be freed
1340 GSList
*wtap_get_file_extensions_list(int file_type_subtype
, gboolean include_compressed
)
1342 GSList
*compressed_file_extensions
;
1345 if (file_type_subtype
< 0 || file_type_subtype
>= wtap_num_file_types_subtypes
)
1346 return NULL
; /* not a valid file type */
1348 if (dump_open_table
[file_type_subtype
].default_file_extension
== NULL
)
1349 return NULL
; /* valid, but no extensions known */
1351 extensions
= NULL
; /* empty list, to start with */
1354 * If include_compressions is true, get the list of compressed-file
1357 if (include_compressed
)
1358 compressed_file_extensions
= wtap_get_compressed_file_extensions();
1360 compressed_file_extensions
= NULL
;
1363 * Add all this file type's extensions, with compressed
1366 extensions
= add_extensions_for_file_type_subtype(file_type_subtype
, extensions
,
1367 compressed_file_extensions
);
1369 g_slist_free(compressed_file_extensions
);
1374 * Free a list returned by wtap_get_file_extension_type_extensions(),
1375 * wtap_get_all_file_extensions_list, or wtap_get_file_extensions_list().
1377 void wtap_free_extensions_list(GSList
*extensions
)
1381 for (extension
= extensions
; extension
!= NULL
;
1382 extension
= g_slist_next(extension
)) {
1383 g_free(extension
->data
);
1385 g_slist_free(extensions
);
1388 /* Return the default file extension to use with the specified file type;
1389 that's just the extension, without any ".". */
1390 const char *wtap_default_file_extension(int file_type_subtype
)
1392 if (file_type_subtype
< 0 || file_type_subtype
>= wtap_num_file_types_subtypes
)
1395 return dump_open_table
[file_type_subtype
].default_file_extension
;
1398 gboolean
wtap_dump_can_open(int file_type_subtype
)
1400 if (file_type_subtype
< 0 || file_type_subtype
>= wtap_num_file_types_subtypes
1401 || dump_open_table
[file_type_subtype
].dump_open
== NULL
)
1408 gboolean
wtap_dump_can_compress(int file_type_subtype
)
1411 * If this is an unknown file type, or if we have to
1412 * seek when writing out a file with this file type,
1415 if (file_type_subtype
< 0 || file_type_subtype
>= wtap_num_file_types_subtypes
1416 || dump_open_table
[file_type_subtype
].writing_must_seek
)
1422 gboolean
wtap_dump_can_compress(int file_type_subtype _U_
)
1428 gboolean
wtap_dump_has_name_resolution(int file_type_subtype
)
1430 if (file_type_subtype
< 0 || file_type_subtype
>= wtap_num_file_types_subtypes
1431 || dump_open_table
[file_type_subtype
].has_name_resolution
== FALSE
)
1437 gboolean
wtap_dump_supports_comment_types(int file_type_subtype
, guint32 comment_types
)
1439 guint32 supported_comment_types
;
1441 if (file_type_subtype
< 0 || file_type_subtype
>= wtap_num_file_types_subtypes
)
1444 supported_comment_types
= dump_open_table
[file_type_subtype
].supported_comment_types
;
1446 if ((comment_types
& supported_comment_types
) == comment_types
)
1451 static gboolean
wtap_dump_open_check(int file_type_subtype
, int encap
, gboolean comressed
, int *err
);
1452 static wtap_dumper
* wtap_dump_alloc_wdh(int file_type_subtype
, int encap
, int snaplen
,
1453 gboolean compressed
, int *err
);
1454 static gboolean
wtap_dump_open_finish(wtap_dumper
*wdh
, int file_type_subtype
, gboolean compressed
, int *err
);
1456 static WFILE_T
wtap_dump_file_open(wtap_dumper
*wdh
, const char *filename
);
1457 static WFILE_T
wtap_dump_file_fdopen(wtap_dumper
*wdh
, int fd
);
1458 static int wtap_dump_file_close(wtap_dumper
*wdh
);
1460 wtap_dumper
* wtap_dump_open(const char *filename
, int file_type_subtype
, int encap
,
1461 int snaplen
, gboolean compressed
, int *err
)
1463 return wtap_dump_open_ng(filename
, file_type_subtype
, encap
,snaplen
, compressed
, NULL
, NULL
, err
);
1466 static wtap_dumper
*
1467 wtap_dump_init_dumper(int file_type_subtype
, int encap
, int snaplen
, gboolean compressed
,
1468 wtapng_section_t
*shb_hdr
, wtapng_iface_descriptions_t
*idb_inf
, int *err
)
1472 /* Allocate a data structure for the output stream. */
1473 wdh
= wtap_dump_alloc_wdh(file_type_subtype
, encap
, snaplen
, compressed
, err
);
1475 return NULL
; /* couldn't allocate it */
1477 /* Set Section Header Block data */
1478 wdh
->shb_hdr
= shb_hdr
;
1479 /* Set Interface Description Block data */
1480 if ((idb_inf
!= NULL
) && (idb_inf
->number_of_interfaces
> 0)) {
1481 wdh
->number_of_interfaces
= idb_inf
->number_of_interfaces
;
1482 wdh
->interface_data
= idb_inf
->interface_data
;
1484 wtapng_if_descr_t descr
;
1486 descr
.wtap_encap
= encap
;
1487 descr
.time_units_per_second
= 1000000; /* default microsecond resolution */
1488 descr
.link_type
= wtap_wtap_encap_to_pcap_encap(encap
);
1489 descr
.snap_len
= snaplen
;
1490 descr
.opt_comment
= NULL
;
1491 descr
.if_name
= g_strdup("Unknown/not available in original file format(libpcap)");
1492 descr
.if_description
= NULL
;
1494 descr
.if_tsresol
= 6;
1495 descr
.if_filter_str
= NULL
;
1496 descr
.bpf_filter_len
= 0;
1497 descr
.if_filter_bpf_bytes
= NULL
;
1499 descr
.if_fcslen
= -1;
1500 descr
.num_stat_entries
= 0; /* Number of ISB:s */
1501 descr
.interface_statistics
= NULL
;
1502 wdh
->number_of_interfaces
= 1;
1503 wdh
->interface_data
= g_array_new(FALSE
, FALSE
, sizeof(wtapng_if_descr_t
));
1504 g_array_append_val(wdh
->interface_data
, descr
);
1509 wtap_dumper
* wtap_dump_open_ng(const char *filename
, int file_type_subtype
, int encap
,
1510 int snaplen
, gboolean compressed
, wtapng_section_t
*shb_hdr
, wtapng_iface_descriptions_t
*idb_inf
, int *err
)
1515 /* Check whether we can open a capture file with that file type
1516 and that encapsulation. */
1517 if (!wtap_dump_open_check(file_type_subtype
, encap
, compressed
, err
))
1520 /* Allocate and initialize a data structure for the output stream. */
1521 wdh
= wtap_dump_init_dumper(file_type_subtype
, encap
, snaplen
, compressed
,
1522 shb_hdr
, idb_inf
, err
);
1526 /* "-" means stdout */
1527 if (strcmp(filename
, "-") == 0) {
1529 *err
= EINVAL
; /* XXX - return a Wiretap error code for this */
1531 return NULL
; /* compress won't work on stdout */
1534 if (_setmode(fileno(stdout
), O_BINARY
) == -1) {
1535 /* "Should not happen" */
1538 return NULL
; /* couldn't put standard output in binary mode */
1543 /* In case "fopen()" fails but doesn't set "errno", set "errno"
1544 to a generic "the open failed" error. */
1545 errno
= WTAP_ERR_CANT_OPEN
;
1546 fh
= wtap_dump_file_open(wdh
, filename
);
1550 return NULL
; /* can't create file */
1555 if (!wtap_dump_open_finish(wdh
, file_type_subtype
, compressed
, err
)) {
1556 /* Get rid of the file we created; we couldn't finish
1558 if (wdh
->fh
!= stdout
) {
1559 wtap_dump_file_close(wdh
);
1560 ws_unlink(filename
);
1568 wtap_dumper
* wtap_dump_fdopen(int fd
, int file_type_subtype
, int encap
, int snaplen
,
1569 gboolean compressed
, int *err
)
1571 return wtap_dump_fdopen_ng(fd
, file_type_subtype
, encap
, snaplen
, compressed
, NULL
, NULL
, err
);
1574 wtap_dumper
* wtap_dump_fdopen_ng(int fd
, int file_type_subtype
, int encap
, int snaplen
,
1575 gboolean compressed
, wtapng_section_t
*shb_hdr
, wtapng_iface_descriptions_t
*idb_inf
, int *err
)
1580 /* Check whether we can open a capture file with that file type
1581 and that encapsulation. */
1582 if (!wtap_dump_open_check(file_type_subtype
, encap
, compressed
, err
))
1585 /* Allocate and initialize a data structure for the output stream. */
1586 wdh
= wtap_dump_init_dumper(file_type_subtype
, encap
, snaplen
, compressed
,
1587 shb_hdr
, idb_inf
, err
);
1593 if (_setmode(fileno(stdout
), O_BINARY
) == -1) {
1594 /* "Should not happen" */
1597 return NULL
; /* couldn't put standard output in binary mode */
1602 /* In case "fopen()" fails but doesn't set "errno", set "errno"
1603 to a generic "the open failed" error. */
1604 errno
= WTAP_ERR_CANT_OPEN
;
1605 fh
= wtap_dump_file_fdopen(wdh
, fd
);
1609 return NULL
; /* can't create standard I/O stream */
1613 if (!wtap_dump_open_finish(wdh
, file_type_subtype
, compressed
, err
)) {
1614 wtap_dump_file_close(wdh
);
1621 static gboolean
wtap_dump_open_check(int file_type_subtype
, int encap
, gboolean compressed
, int *err
)
1623 if (!wtap_dump_can_open(file_type_subtype
)) {
1624 /* Invalid type, or type we don't know how to write. */
1625 *err
= WTAP_ERR_UNSUPPORTED_FILE_TYPE
;
1629 /* OK, we know how to write that type; can we write the specified
1630 encapsulation type? */
1631 *err
= (*dump_open_table
[file_type_subtype
].can_write_encap
)(encap
);
1635 /* if compression is wanted, do we support this for this file_type_subtype? */
1636 if(compressed
&& !wtap_dump_can_compress(file_type_subtype
)) {
1637 *err
= WTAP_ERR_COMPRESSION_NOT_SUPPORTED
;
1641 *err
= (*dump_open_table
[file_type_subtype
].can_write_encap
)(encap
);
1645 /* All systems go! */
1649 static wtap_dumper
* wtap_dump_alloc_wdh(int file_type_subtype
, int encap
, int snaplen
,
1650 gboolean compressed
, int *err
)
1654 wdh
= (wtap_dumper
*)g_malloc0(sizeof (wtap_dumper
));
1660 wdh
->file_type_subtype
= file_type_subtype
;
1661 wdh
->snaplen
= snaplen
;
1663 wdh
->compressed
= compressed
;
1667 static gboolean
wtap_dump_open_finish(wtap_dumper
*wdh
, int file_type_subtype
, gboolean compressed
, int *err
)
1672 /* Can we do a seek on the file descriptor?
1673 If not, note that fact. */
1677 fd
= fileno((FILE *)wdh
->fh
);
1678 if (lseek(fd
, 1, SEEK_CUR
) == -1)
1681 /* Undo the seek. */
1682 lseek(fd
, 0, SEEK_SET
);
1687 /* If this file type requires seeking, and we can't seek, fail. */
1688 if (dump_open_table
[file_type_subtype
].writing_must_seek
&& cant_seek
) {
1689 *err
= WTAP_ERR_CANT_WRITE_TO_PIPE
;
1693 /* Now try to open the file for writing. */
1694 if (!(*dump_open_table
[file_type_subtype
].dump_open
)(wdh
, err
)) {
1698 return TRUE
; /* success! */
1701 gboolean
wtap_dump(wtap_dumper
*wdh
, const struct wtap_pkthdr
*phdr
,
1702 const guint8
*pd
, int *err
)
1704 return (wdh
->subtype_write
)(wdh
, phdr
, pd
, err
);
1707 void wtap_dump_flush(wtap_dumper
*wdh
)
1710 if(wdh
->compressed
) {
1711 gzwfile_flush((GZWFILE_T
)wdh
->fh
);
1715 fflush((FILE *)wdh
->fh
);
1719 gboolean
wtap_dump_close(wtap_dumper
*wdh
, int *err
)
1721 gboolean ret
= TRUE
;
1723 if (wdh
->subtype_close
!= NULL
) {
1724 /* There's a close routine for this dump stream. */
1725 if (!(wdh
->subtype_close
)(wdh
, err
))
1728 errno
= WTAP_ERR_CANT_CLOSE
;
1729 /* Don't close stdout */
1730 if (wdh
->fh
!= stdout
) {
1731 if (wtap_dump_file_close(wdh
) == EOF
) {
1733 /* The per-format close function succeeded,
1734 but the fclose didn't. Save the reason
1735 why, if our caller asked for it. */
1742 /* as we don't close stdout, at least try to flush it */
1743 wtap_dump_flush(wdh
);
1745 if (wdh
->priv
!= NULL
)
1751 gint64
wtap_get_bytes_dumped(wtap_dumper
*wdh
)
1753 return wdh
->bytes_dumped
;
1756 void wtap_set_bytes_dumped(wtap_dumper
*wdh
, gint64 bytes_dumped
)
1758 wdh
->bytes_dumped
= bytes_dumped
;
1761 gboolean
wtap_dump_set_addrinfo_list(wtap_dumper
*wdh
, addrinfo_lists_t
*addrinfo_lists
)
1763 if (!wdh
|| wdh
->file_type_subtype
< 0 || wdh
->file_type_subtype
>= wtap_num_file_types_subtypes
1764 || dump_open_table
[wdh
->file_type_subtype
].has_name_resolution
== FALSE
)
1766 wdh
->addrinfo_lists
= addrinfo_lists
;
1770 /* internally open a file for writing (compressed or not) */
1772 static WFILE_T
wtap_dump_file_open(wtap_dumper
*wdh
, const char *filename
)
1774 if(wdh
->compressed
) {
1775 return gzwfile_open(filename
);
1777 return ws_fopen(filename
, "wb");
1781 static WFILE_T
wtap_dump_file_open(wtap_dumper
*wdh _U_
, const char *filename
)
1783 return ws_fopen(filename
, "wb");
1787 /* internally open a file for writing (compressed or not) */
1789 static WFILE_T
wtap_dump_file_fdopen(wtap_dumper
*wdh
, int fd
)
1791 if(wdh
->compressed
) {
1792 return gzwfile_fdopen(fd
);
1794 return fdopen(fd
, "wb");
1798 static WFILE_T
wtap_dump_file_fdopen(wtap_dumper
*wdh _U_
, int fd
)
1800 return fdopen(fd
, "wb");
1804 /* internally writing raw bytes (compressed or not) */
1805 gboolean
wtap_dump_file_write(wtap_dumper
*wdh
, const void *buf
, size_t bufsize
,
1811 if (wdh
->compressed
) {
1812 nwritten
= gzwfile_write((GZWFILE_T
)wdh
->fh
, buf
, (unsigned) bufsize
);
1814 * gzwfile_write() returns 0 on error.
1816 if (nwritten
== 0) {
1817 *err
= gzwfile_geterr((GZWFILE_T
)wdh
->fh
);
1823 nwritten
= fwrite(buf
, 1, bufsize
, (FILE *)wdh
->fh
);
1825 * At least according to the Mac OS X man page,
1826 * this can return a short count on an error.
1828 if (nwritten
!= bufsize
) {
1829 if (ferror((FILE *)wdh
->fh
))
1832 *err
= WTAP_ERR_SHORT_WRITE
;
1839 /* internally close a file for writing (compressed or not) */
1840 static int wtap_dump_file_close(wtap_dumper
*wdh
)
1843 if(wdh
->compressed
) {
1844 return gzwfile_close((GZWFILE_T
)wdh
->fh
);
1848 return fclose((FILE *)wdh
->fh
);
1852 gint64
wtap_dump_file_seek(wtap_dumper
*wdh
, gint64 offset
, int whence
, int *err
)
1855 if(wdh
->compressed
) {
1856 *err
= WTAP_ERR_CANT_SEEK_COMPRESSED
;
1861 if (-1 == fseek((FILE *)wdh
->fh
, (long)offset
, whence
)) {
1870 gint64
wtap_dump_file_tell(wtap_dumper
*wdh
, int *err
)
1874 if(wdh
->compressed
) {
1875 *err
= WTAP_ERR_CANT_SEEK_COMPRESSED
;
1880 if (-1 == (rval
= ftell((FILE *)wdh
->fh
))) {