HACK: pinfo->private_data points to smb_info again
[wireshark-wip.git] / wiretap / file_access.c
blob9a5993853b568db231321339701a6a93f6a8b161
1 /* file_access.c
3 * $Id$
5 * Wiretap Library
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.
23 #include "config.h"
25 #include <stdio.h>
26 #include <string.h>
27 #include <stdlib.h>
29 #ifdef HAVE_FCNTL_H
30 #include <fcntl.h>
31 #endif
33 #ifdef HAVE_UNISTD_H
34 #include <unistd.h>
35 #endif
37 #include <errno.h>
39 #include <wsutil/file_util.h>
41 #include "wtap-int.h"
42 #include "file_wrappers.h"
43 #include "buffer.h"
44 #include "lanalyzer.h"
45 #include "ngsniffer.h"
46 #include "radcom.h"
47 #include "ascendtext.h"
48 #include "nettl.h"
49 #include "libpcap.h"
50 #include "snoop.h"
51 #include "iptrace.h"
52 #include "iseries.h"
53 #include "netmon.h"
54 #include "netxray.h"
55 #include "toshiba.h"
56 #include "eyesdn.h"
57 #include "i4btrace.h"
58 #include "csids.h"
59 #include "pppdump.h"
60 #include "peekclassic.h"
61 #include "peektagged.h"
62 #include "vms.h"
63 #include "dbs-etherwatch.h"
64 #include "visual.h"
65 #include "cosine.h"
66 #include "5views.h"
67 #include "erf.h"
68 #include "hcidump.h"
69 #include "network_instruments.h"
70 #include "k12.h"
71 #include "ber.h"
72 #include "catapult_dct2000.h"
73 #include "mp2t.h"
74 #include "mpeg.h"
75 #include "netscreen.h"
76 #include "commview.h"
77 #include "pcapng.h"
78 #include "aethra.h"
79 #include "btsnoop.h"
80 #include "tnef.h"
81 #include "dct3trace.h"
82 #include "packetlogger.h"
83 #include "daintree-sna.h"
84 #include "netscaler.h"
85 #include "mime_file.h"
86 #include "ipfix.h"
87 #include "vwr.h"
88 #include "camins.h"
89 #include "stanag4607.h"
90 #include "pcap-encap.h"
93 * Add an extension, and all compressed versions thereof, to a GSList
94 * of extensions.
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
108 * that extension.
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));
118 return extensions;
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,
199 ";", 0);
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
209 * of it.
211 extensions = add_extensions(extensions, extension,
212 compressed_file_extensions);
215 g_strfreev(extensions_set);
216 return extensions;
219 /* Return a list of file extensions that are used by the specified file
220 extension type.
222 All strings in the list are allocated with g_malloc() and must be freed
223 with g_free(). */
224 GSList *wtap_get_file_extension_type_extensions(guint extension_type)
226 GSList *compressed_file_extensions;
227 GSList *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
241 * variants.
243 extensions = add_extensions_for_file_extensions_type(extension_type,
244 extensions, compressed_file_extensions);
246 g_slist_free(compressed_file_extensions);
247 return 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
255 with g_free(). */
256 GSList *wtap_get_all_file_extensions_list(void)
258 GSList *compressed_file_extensions;
259 GSList *extensions;
260 unsigned int i;
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);
281 return 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.
314 libpcap_open,
315 pcapng_open,
316 lanalyzer_open,
317 ngsniffer_open,
318 snoop_open,
319 iptrace_open,
320 netmon_open,
321 netxray_open,
322 radcom_open,
323 nettl_open,
324 visual_open,
325 _5views_open,
326 network_instruments_open,
327 peektagged_open,
328 dbs_etherwatch_open,
329 k12_open,
330 catapult_dct2000_open,
331 ber_open, /* XXX - this is really a heuristic */
332 aethra_open,
333 btsnoop_open,
334 eyesdn_open,
335 packetlogger_open, /* This type does not have a magic number, but its
336 * files are sometimes grabbed by mpeg_open. */
337 mpeg_open,
338 tnef_open,
339 dct3trace_open,
340 daintree_sna_open,
341 mime_file_open,
342 stanag4607_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
347 * to some box.
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)
357 netscreen_open,
358 erf_open,
359 vwr_open,
360 ipfix_open,
361 k12text_open,
362 peekclassic_open,
363 pppdump_open,
364 iseries_open,
365 ascend_open,
366 toshiba_open,
367 i4btrace_open,
368 mp2t_open,
369 csids_open,
370 vms_open,
371 cosine_open,
372 hcidump_open,
373 commview_open,
374 nstrace_open,
375 camins_open
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();
400 if (has_magic)
401 g_array_prepend_val(open_routines_arr,open_routine);
402 else
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.
414 #ifndef S_ISREG
415 #define S_ISREG(mode) (((mode) & S_IFMT) == S_IFREG)
416 #endif
417 #ifndef S_IFIFO
418 #define S_IFIFO _S_IFIFO
419 #endif
420 #ifndef S_ISFIFO
421 #define S_ISFIFO(mode) (((mode) & S_IFMT) == S_IFIFO)
422 #endif
423 #ifndef S_ISDIR
424 #define S_ISDIR(mode) (((mode) & S_IFMT) == S_IFDIR)
425 #endif
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,
435 gboolean do_random)
437 int fd;
438 ws_statb64 statb;
439 wtap *wth;
440 unsigned int i;
441 gboolean use_stdin = FALSE;
443 /* open standard input if filename is '-' */
444 if (strcmp(filename, "-") == 0)
445 use_stdin = TRUE;
447 /* First, make sure the file is valid */
448 if (use_stdin) {
449 if (ws_fstat64(0, &statb) < 0) {
450 *err = errno;
451 return NULL;
453 } else {
454 if (ws_stat64(filename, &statb) < 0) {
455 *err = errno;
456 return NULL;
459 if (S_ISFIFO(statb.st_mode)) {
461 * Opens of FIFOs are allowed only when not opening
462 * for random access.
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
470 * we try to seek.
472 if (do_random) {
473 *err = WTAP_ERR_RANDOM_OPEN_PIPE;
474 return NULL;
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.
482 *err = EISDIR;
483 return NULL;
484 } else if (! S_ISREG(statb.st_mode)) {
485 *err = WTAP_ERR_NOT_REGULAR_FILE;
486 return NULL;
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;
498 return NULL;
501 errno = ENOMEM;
502 wth = (wtap *)g_malloc0(sizeof(wtap));
504 /* Open the file */
505 errno = WTAP_ERR_CANT_OPEN;
506 if (use_stdin) {
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.
512 fd = ws_dup(0);
513 if (fd < 0) {
514 *err = errno;
515 g_free(wth);
516 return NULL;
518 #ifdef _WIN32
519 if (_setmode(fd, O_BINARY) == -1) {
520 /* "Shouldn't happen" */
521 *err = errno;
522 g_free(wth);
523 return NULL;
525 #endif
526 if (!(wth->fh = file_fdopen(fd))) {
527 *err = errno;
528 ws_close(fd);
529 g_free(wth);
530 return NULL;
532 } else {
533 if (!(wth->fh = file_open(filename))) {
534 *err = errno;
535 g_free(wth);
536 return NULL;
540 if (do_random) {
541 if (!(wth->random_fh = file_open(filename))) {
542 *err = errno;
543 file_close(wth->fh);
544 g_free(wth);
545 return NULL;
547 } else
548 wth->random_fh = NULL;
550 /* initialization */
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;
555 wth->priv = NULL;
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 */
576 wtap_close(wth);
577 return NULL;
580 switch ((*open_routines[i])(wth, err, err_info)) {
582 case -1:
583 /* I/O error - give up */
584 wtap_close(wth);
585 return NULL;
587 case 0:
588 /* No I/O error, but not that type of file */
589 break;
591 case 1:
592 /* We found the file type */
593 goto success;
597 /* Well, it's not one of the types of file we know about. */
598 wtap_close(wth);
599 *err = WTAP_ERR_FILE_UNKNOWN_FORMAT;
600 return NULL;
602 success:
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;
617 descr.if_speed = 0;
618 descr.if_tsresol = 6;
619 descr.if_filter_str= NULL;
620 descr.bpf_filter_len= 0;
621 descr.if_filter_bpf_bytes= NULL;
622 descr.if_os = 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);
631 return wth;
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.
646 gboolean
647 wtap_fdreopen(wtap *wth, const char *filename, int *err)
649 ws_statb64 statb;
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;
660 return FALSE;
663 /* First, make sure the file is valid */
664 if (ws_stat64(filename, &statb) < 0) {
665 *err = errno;
666 return FALSE;
668 if (S_ISFIFO(statb.st_mode)) {
670 * Opens of FIFOs are not allowed; see above.
672 *err = WTAP_ERR_RANDOM_OPEN_PIPE;
673 return FALSE;
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.
680 *err = EISDIR;
681 return FALSE;
682 } else if (! S_ISREG(statb.st_mode)) {
683 *err = WTAP_ERR_NOT_REGULAR_FILE;
684 return FALSE;
687 /* Open the file */
688 errno = WTAP_ERR_CANT_OPEN;
689 if (!file_fdreopen(wth->random_fh, filename)) {
690 *err = errno;
691 return FALSE;
693 return TRUE;
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,
701 FALSE, FALSE, 0,
702 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",
707 FALSE, FALSE, 0,
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",
717 FALSE, FALSE, 0,
718 libpcap_dump_can_write_encap, libpcap_dump_open },
720 /* WTAP_FILE_TYPE_SUBTYPE_PCAP_AIX */
721 { "AIX tcpdump - libpcap", "aixlibpcap", "pcap", "cap;dmp",
722 FALSE, FALSE, 0,
723 NULL, NULL },
725 /* WTAP_FILE_TYPE_SUBTYPE_PCAP_SS991029 */
726 { "Modified tcpdump - libpcap", "modlibpcap", "pcap", "cap;dmp",
727 FALSE, FALSE, 0,
728 libpcap_dump_can_write_encap, libpcap_dump_open },
730 /* WTAP_FILE_TYPE_SUBTYPE_PCAP_NOKIA */
731 { "Nokia tcpdump - libpcap ", "nokialibpcap", "pcap", "cap;dmp",
732 FALSE, FALSE, 0,
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",
737 FALSE, FALSE, 0,
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",
742 FALSE, FALSE, 0,
743 libpcap_dump_can_write_encap, libpcap_dump_open },
745 /* WTAP_FILE_TYPE_SUBTYPE_5VIEWS */
746 { "InfoVista 5View capture", "5views", "5vw", NULL,
747 TRUE, FALSE, 0,
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,
752 FALSE, FALSE, 0,
753 NULL, NULL },
755 /* WTAP_FILE_TYPE_SUBTYPE_IPTRACE_2_0 */
756 { "AIX iptrace 2.0", "iptrace_2", NULL, NULL,
757 FALSE, FALSE, 0,
758 NULL, NULL },
760 /* WTAP_FILE_TYPE_SUBTYPE_BER */
761 { "ASN.1 Basic Encoding Rules", "ber", NULL, NULL,
762 FALSE, FALSE, 0,
763 NULL, NULL },
765 /* WTAP_FILE_TYPE_SUBTYPE_HCIDUMP */
766 { "Bluetooth HCI dump", "hcidump", NULL, NULL,
767 FALSE, FALSE, 0,
768 NULL, NULL },
770 /* WTAP_FILE_TYPE_SUBTYPE_CATAPULT_DCT2000 */
771 { "Catapult DCT2000 trace (.out format)", "dct2000", "out", NULL,
772 FALSE, FALSE, 0,
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,
777 TRUE, FALSE, 0,
778 NULL, NULL },
780 /* WTAP_FILE_TYPE_SUBTYPE_NETXRAY_1_0 */
781 { "Cinco Networks NetXRay 2.0 or later", "netxray2", "cap", NULL,
782 TRUE, FALSE, 0,
783 NULL, NULL },
785 /* WTAP_FILE_TYPE_SUBTYPE_COSINE */
786 { "CoSine IPSX L2 capture", "cosine", "txt", NULL,
787 FALSE, FALSE, 0,
788 NULL, NULL },
790 /* WTAP_FILE_TYPE_SUBTYPE_CSIDS */
791 { "CSIDS IPLog", "csids", NULL, NULL,
792 FALSE, FALSE, 0,
793 NULL, NULL },
795 /* WTAP_FILE_TYPE_SUBTYPE_DBS_ETHERWATCH */
796 { "DBS Etherwatch (VMS)", "etherwatch", "txt", NULL,
797 FALSE, FALSE, 0,
798 NULL, NULL},
800 /* WTAP_FILE_TYPE_SUBTYPE_ERF */
801 { "Endace ERF capture", "erf", "erf", NULL,
802 FALSE, FALSE, 0,
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,
807 FALSE, FALSE, 0,
808 eyesdn_dump_can_write_encap, eyesdn_dump_open },
810 /* WTAP_FILE_TYPE_SUBTYPE_NETTL */
811 { "HP-UX nettl trace", "nettl", "trc0", "trc1",
812 FALSE, FALSE, 0,
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,
817 FALSE, FALSE, 0,
818 NULL, NULL },
820 /* WTAP_FILE_TYPE_SUBTYPE_ISERIES_UNICODE */
821 { "IBM iSeries comm. trace (UNICODE)", "iseries_unicode", "txt", NULL,
822 FALSE, FALSE, 0,
823 NULL, NULL },
825 /* WTAP_FILE_TYPE_SUBTYPE_I4BTRACE */
826 { "I4B ISDN trace", "i4btrace", NULL, NULL,
827 FALSE, FALSE, 0,
828 NULL, NULL },
830 /* WTAP_FILE_TYPE_SUBTYPE_ASCEND */
831 { "Lucent/Ascend access server trace", "ascend", "txt", NULL,
832 FALSE, FALSE, 0,
833 NULL, NULL },
835 /* WTAP_FILE_TYPE_SUBTYPE_NETMON_1_x */
836 { "Microsoft NetMon 1.x", "netmon1", "cap", NULL,
837 TRUE, FALSE, 0,
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,
842 TRUE, FALSE, 0,
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",
847 FALSE, FALSE, 0,
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",
852 FALSE, FALSE, 0,
853 NULL, NULL },
855 /* WTAP_FILE_TYPE_SUBTYPE_NETXRAY_1_1 */
856 { "NetXray, Sniffer (Windows) 1.1", "ngwsniffer_1_1", "cap", NULL,
857 TRUE, FALSE, 0,
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",
862 TRUE, FALSE, 0,
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,
867 FALSE, FALSE, 0,
868 network_instruments_dump_can_write_encap, network_instruments_dump_open },
870 /* WTAP_FILE_TYPE_SUBTYPE_LANALYZER */
871 { "Novell LANalyzer","lanalyzer", "tr1", NULL,
872 TRUE, FALSE, 0,
873 lanalyzer_dump_can_write_encap, lanalyzer_dump_open },
875 /* WTAP_FILE_TYPE_SUBTYPE_PPPDUMP */
876 { "pppd log (pppdump format)", "pppd", NULL, NULL,
877 FALSE, FALSE, 0,
878 NULL, NULL },
880 /* WTAP_FILE_TYPE_SUBTYPE_RADCOM */
881 { "RADCOM WAN/LAN analyzer", "radcom", NULL, NULL,
882 FALSE, FALSE, 0,
883 NULL, NULL },
885 /* WTAP_FILE_TYPE_SUBTYPE_SNOOP */
886 { "Sun snoop", "snoop", "snoop", "cap",
887 FALSE, FALSE, 0,
888 snoop_dump_can_write_encap, snoop_dump_open },
890 /* WTAP_FILE_TYPE_SUBTYPE_SHOMITI */
891 { "Shomiti/Finisar Surveyor", "shomiti", "cap", NULL,
892 FALSE, FALSE, 0,
893 NULL, NULL },
895 /* WTAP_FILE_TYPE_SUBTYPE_VMS */
896 { "TCPIPtrace (VMS)", "tcpiptrace", "txt", NULL,
897 FALSE, FALSE, 0,
898 NULL, NULL},
900 /* WTAP_FILE_TYPE_SUBTYPE_K12 */
901 { "Tektronix K12xx 32-bit .rf5 format", "rf5", "rf5", NULL,
902 TRUE, FALSE, 0,
903 k12_dump_can_write_encap, k12_dump_open },
905 /* WTAP_FILE_TYPE_SUBTYPE_TOSHIBA */
906 { "Toshiba Compact ISDN Router snoop", "toshiba", "txt", NULL,
907 FALSE, FALSE, 0,
908 NULL, NULL },
910 /* WTAP_FILE_TYPE_SUBTYPE_VISUAL_NETWORKS */
911 { "Visual Networks traffic capture", "visual", NULL, NULL,
912 TRUE, FALSE, 0,
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",
917 FALSE, FALSE, 0,
918 NULL, NULL },
920 /* WTAP_FILE_TYPE_SUBTYPE_PEEKCLASSIC_V7 */
921 { "WildPackets classic (V7)", "peekclassic7", "pkt", "tpc;apc;wpz",
922 FALSE, FALSE, 0,
923 NULL, NULL },
925 /* WTAP_FILE_TYPE_SUBTYPE_PEEKTAGGED */
926 { "WildPackets tagged", "peektagged", "pkt", "tpc;apc;wpz",
927 FALSE, FALSE, 0,
928 NULL, NULL },
930 /* WTAP_FILE_TYPE_SUBTYPE_MPEG */
931 { "MPEG", "mpeg", "mpeg", "mpg;mp3",
932 FALSE, FALSE, 0,
933 NULL, NULL },
935 /* WTAP_FILE_TYPE_SUBTYPE_K12TEXT */
936 { "K12 text file", "k12text", "txt", NULL,
937 FALSE, FALSE, 0,
938 k12text_dump_can_write_encap, k12text_dump_open },
940 /* WTAP_FILE_TYPE_SUBTYPE_NETSCREEN */
941 { "NetScreen snoop text file", "netscreen", "txt", NULL,
942 FALSE, FALSE, 0,
943 NULL, NULL },
945 /* WTAP_FILE_TYPE_SUBTYPE_COMMVIEW */
946 { "TamoSoft CommView", "commview", "ncf", NULL,
947 FALSE, FALSE, 0,
948 commview_dump_can_write_encap, commview_dump_open },
950 /* WTAP_FILE_TYPE_SUBTYPE_BTSNOOP */
951 { "Symbian OS btsnoop", "btsnoop", "log", NULL,
952 FALSE, FALSE, 0,
953 btsnoop_dump_can_write_encap, btsnoop_dump_open_h4 },
955 /* WTAP_FILE_TYPE_SUBTYPE_TNEF */
956 { "Transport-Neutral Encapsulation Format", "tnef", NULL, NULL,
957 FALSE, FALSE, 0,
958 NULL, NULL },
960 /* WTAP_FILE_TYPE_SUBTYPE_DCT3TRACE */
961 { "Gammu DCT3 trace", "dct3trace", "xml", NULL,
962 FALSE, FALSE, 0,
963 NULL, NULL },
965 /* WTAP_FILE_TYPE_SUBTYPE_PACKETLOGGER */
966 { "PacketLogger", "pklg", "pklg", NULL,
967 FALSE, FALSE, 0,
968 NULL, NULL },
970 /* WTAP_FILE_TYPE_SUBTYPE_DAINTREE_SNA */
971 { "Daintree SNA", "dsna", "dcf", NULL,
972 FALSE, FALSE, 0,
973 NULL, NULL },
975 /* WTAP_FILE_TYPE_SUBTYPE_NETSCALER_1_0 */
976 { "NetScaler Trace (Version 1.0)", "nstrace10", NULL, NULL,
977 TRUE, FALSE, 0,
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,
982 TRUE, FALSE, 0,
983 nstrace_20_dump_can_write_encap, nstrace_dump_open },
985 /* WTAP_FILE_TYPE_SUBTYPE_JPEG_JFIF */
986 { "JPEG/JFIF", "jpeg", "jpg", "jpeg;jfif",
987 FALSE, FALSE, 0,
988 NULL, NULL },
990 /* WTAP_FILE_TYPE_SUBTYPE_IPFIX */
991 { "IPFIX File Format", "ipfix", "pfx", "ipfix",
992 FALSE, FALSE, 0,
993 NULL, NULL },
995 /* WTAP_ENCAP_MIME */
996 { "MIME File Format", "mime", NULL, NULL,
997 FALSE, FALSE, 0,
998 NULL, NULL },
1000 /* WTAP_FILE_TYPE_SUBTYPE_AETHRA */
1001 { "Aethra .aps file", "aethra", "aps", NULL,
1002 FALSE, FALSE, 0,
1003 NULL, NULL },
1005 /* WTAP_FILE_TYPE_SUBTYPE_MPEG_2_TS */
1006 { "MPEG2 transport stream", "mp2t", "mp2t", "ts;mpg",
1007 FALSE, FALSE, 0,
1008 NULL, NULL },
1010 /* WTAP_FILE_TYPE_SUBTYPE_VWR_80211 */
1011 { "Ixia IxVeriWave .vwr Raw 802.11 Capture", "vwr80211", "vwr", NULL,
1012 FALSE, FALSE, 0,
1013 NULL, NULL },
1015 /* WTAP_FILE_TYPE_SUBTYPE_VWR_ETH */
1016 { "Ixia IxVeriWave .vwr Raw Ethernet Capture", "vwreth", "vwr", NULL,
1017 FALSE, FALSE, 0,
1018 NULL, NULL },
1020 /* WTAP_FILE_TYPE_SUBTYPE_CAMINS */
1021 { "CAM Inspector file", "camins", "camins", NULL,
1022 FALSE, FALSE, 0,
1023 NULL, NULL },
1025 /* WTAP_FILE_TYPE_SUBTYPE_STANAG_4607 */
1026 { "STANAG 4607 Format", "stanag4607", NULL, NULL,
1027 FALSE, FALSE, 0,
1028 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)
1073 int encap;
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);
1080 return encap;
1083 static gboolean
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)
1088 return FALSE;
1090 if ((*dump_open_table[filetype].can_write_encap)(encap) != 0)
1091 return FALSE;
1093 return TRUE;
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.
1101 static gboolean
1102 wtap_dump_can_write_format(int ft, const GArray *file_encaps,
1103 guint32 required_comment_types)
1105 guint i;
1108 * Can we write in this format?
1110 if (!wtap_dump_can_open(ft)) {
1111 /* No. */
1112 return FALSE;
1116 * Yes. Can we write out all the required comments in this
1117 * format?
1119 if (!wtap_dump_supports_comment_types(ft, required_comment_types)) {
1120 /* No. */
1121 return FALSE;
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))) {
1129 /* No. */
1130 return FALSE;
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. */
1140 return FALSE;
1144 /* Yes - we're OK. */
1145 return TRUE;
1149 * Return TRUE if we can write a file with the given GArray of
1150 * encapsulation types and the given bitmask of comment types.
1152 gboolean
1153 wtap_dump_can_write(const GArray *file_encaps, guint32 required_comment_types)
1155 int ft;
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. */
1163 return TRUE;
1167 /* No, we couldn't save it in any format. */
1168 return FALSE;
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.
1176 GArray *
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;
1181 int ft;
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;
1190 } else {
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)) {
1196 /* OK, got it. */
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. */
1204 return NULL;
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
1216 pcap format. */
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 **/
1251 return "";
1252 } else
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)
1260 return NULL;
1261 else
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 */
1287 static GSList *
1288 add_extensions_for_file_type_subtype(int file_type_subtype, GSList *extensions,
1289 GSList *compressed_file_extensions)
1291 gchar **extensions_set, **extensionp;
1292 gchar *extension;
1295 * Add the default extension, and all compressed variants of
1296 * it.
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
1307 * extensions.
1309 extensions_set = g_strsplit(dump_open_table[file_type_subtype].additional_file_extensions,
1310 ";", 0);
1313 * Add each of those extensions to the list.
1315 for (extensionp = extensions_set; *extensionp != NULL;
1316 extensionp++) {
1317 extension = *extensionp;
1320 * Add the extension, and all compressed variants
1321 * of it.
1323 extensions = add_extensions(extensions, extension,
1324 compressed_file_extensions);
1327 g_strfreev(extensions_set);
1329 return extensions;
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
1336 gzipped files.
1338 All strings in the list are allocated with g_malloc() and must be freed
1339 with g_free(). */
1340 GSList *wtap_get_file_extensions_list(int file_type_subtype, gboolean include_compressed)
1342 GSList *compressed_file_extensions;
1343 GSList *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
1355 * extensions.
1357 if (include_compressed)
1358 compressed_file_extensions = wtap_get_compressed_file_extensions();
1359 else
1360 compressed_file_extensions = NULL;
1363 * Add all this file type's extensions, with compressed
1364 * variants.
1366 extensions = add_extensions_for_file_type_subtype(file_type_subtype, extensions,
1367 compressed_file_extensions);
1369 g_slist_free(compressed_file_extensions);
1370 return 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)
1379 GSList *extension;
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)
1393 return NULL;
1394 else
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)
1402 return FALSE;
1404 return TRUE;
1407 #ifdef HAVE_LIBZ
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,
1413 * return FALSE.
1415 if (file_type_subtype < 0 || file_type_subtype >= wtap_num_file_types_subtypes
1416 || dump_open_table[file_type_subtype].writing_must_seek)
1417 return FALSE;
1419 return TRUE;
1421 #else
1422 gboolean wtap_dump_can_compress(int file_type_subtype _U_)
1424 return FALSE;
1426 #endif
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)
1432 return FALSE;
1434 return TRUE;
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)
1442 return FALSE;
1444 supported_comment_types = dump_open_table[file_type_subtype].supported_comment_types;
1446 if ((comment_types & supported_comment_types) == comment_types)
1447 return TRUE;
1448 return FALSE;
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)
1470 wtap_dumper *wdh;
1472 /* Allocate a data structure for the output stream. */
1473 wdh = wtap_dump_alloc_wdh(file_type_subtype, encap, snaplen, compressed, err);
1474 if (wdh == NULL)
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;
1483 } else {
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;
1493 descr.if_speed = 0;
1494 descr.if_tsresol = 6;
1495 descr.if_filter_str= NULL;
1496 descr.bpf_filter_len= 0;
1497 descr.if_filter_bpf_bytes= NULL;
1498 descr.if_os = 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);
1506 return wdh;
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)
1512 wtap_dumper *wdh;
1513 WFILE_T fh;
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))
1518 return NULL;
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);
1523 if (wdh == NULL)
1524 return NULL;
1526 /* "-" means stdout */
1527 if (strcmp(filename, "-") == 0) {
1528 if (compressed) {
1529 *err = EINVAL; /* XXX - return a Wiretap error code for this */
1530 g_free(wdh);
1531 return NULL; /* compress won't work on stdout */
1533 #ifdef _WIN32
1534 if (_setmode(fileno(stdout), O_BINARY) == -1) {
1535 /* "Should not happen" */
1536 *err = errno;
1537 g_free(wdh);
1538 return NULL; /* couldn't put standard output in binary mode */
1540 #endif
1541 wdh->fh = stdout;
1542 } else {
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);
1547 if (fh == NULL) {
1548 *err = errno;
1549 g_free(wdh);
1550 return NULL; /* can't create file */
1552 wdh->fh = fh;
1555 if (!wtap_dump_open_finish(wdh, file_type_subtype, compressed, err)) {
1556 /* Get rid of the file we created; we couldn't finish
1557 opening it. */
1558 if (wdh->fh != stdout) {
1559 wtap_dump_file_close(wdh);
1560 ws_unlink(filename);
1562 g_free(wdh);
1563 return NULL;
1565 return wdh;
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)
1577 wtap_dumper *wdh;
1578 WFILE_T fh;
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))
1583 return NULL;
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);
1588 if (wdh == NULL)
1589 return NULL;
1591 #ifdef _WIN32
1592 if (fd == 1) {
1593 if (_setmode(fileno(stdout), O_BINARY) == -1) {
1594 /* "Should not happen" */
1595 *err = errno;
1596 g_free(wdh);
1597 return NULL; /* couldn't put standard output in binary mode */
1600 #endif
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);
1606 if (fh == NULL) {
1607 *err = errno;
1608 g_free(wdh);
1609 return NULL; /* can't create standard I/O stream */
1611 wdh->fh = fh;
1613 if (!wtap_dump_open_finish(wdh, file_type_subtype, compressed, err)) {
1614 wtap_dump_file_close(wdh);
1615 g_free(wdh);
1616 return NULL;
1618 return 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;
1626 return FALSE;
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);
1632 if (*err != 0)
1633 return FALSE;
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;
1638 return FALSE;
1641 *err = (*dump_open_table[file_type_subtype].can_write_encap)(encap);
1642 if (*err != 0)
1643 return FALSE;
1645 /* All systems go! */
1646 return TRUE;
1649 static wtap_dumper* wtap_dump_alloc_wdh(int file_type_subtype, int encap, int snaplen,
1650 gboolean compressed, int *err)
1652 wtap_dumper *wdh;
1654 wdh = (wtap_dumper *)g_malloc0(sizeof (wtap_dumper));
1655 if (wdh == NULL) {
1656 *err = errno;
1657 return NULL;
1660 wdh->file_type_subtype = file_type_subtype;
1661 wdh->snaplen = snaplen;
1662 wdh->encap = encap;
1663 wdh->compressed = compressed;
1664 return wdh;
1667 static gboolean wtap_dump_open_finish(wtap_dumper *wdh, int file_type_subtype, gboolean compressed, int *err)
1669 int fd;
1670 gboolean cant_seek;
1672 /* Can we do a seek on the file descriptor?
1673 If not, note that fact. */
1674 if(compressed) {
1675 cant_seek = TRUE;
1676 } else {
1677 fd = fileno((FILE *)wdh->fh);
1678 if (lseek(fd, 1, SEEK_CUR) == -1)
1679 cant_seek = TRUE;
1680 else {
1681 /* Undo the seek. */
1682 lseek(fd, 0, SEEK_SET);
1683 cant_seek = FALSE;
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;
1690 return FALSE;
1693 /* Now try to open the file for writing. */
1694 if (!(*dump_open_table[file_type_subtype].dump_open)(wdh, err)) {
1695 return FALSE;
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)
1709 #ifdef HAVE_LIBZ
1710 if(wdh->compressed) {
1711 gzwfile_flush((GZWFILE_T)wdh->fh);
1712 } else
1713 #endif
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))
1726 ret = FALSE;
1728 errno = WTAP_ERR_CANT_CLOSE;
1729 /* Don't close stdout */
1730 if (wdh->fh != stdout) {
1731 if (wtap_dump_file_close(wdh) == EOF) {
1732 if (ret) {
1733 /* The per-format close function succeeded,
1734 but the fclose didn't. Save the reason
1735 why, if our caller asked for it. */
1736 if (err != NULL)
1737 *err = errno;
1739 ret = FALSE;
1741 } else {
1742 /* as we don't close stdout, at least try to flush it */
1743 wtap_dump_flush(wdh);
1745 if (wdh->priv != NULL)
1746 g_free(wdh->priv);
1747 g_free(wdh);
1748 return ret;
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)
1765 return FALSE;
1766 wdh->addrinfo_lists = addrinfo_lists;
1767 return TRUE;
1770 /* internally open a file for writing (compressed or not) */
1771 #ifdef HAVE_LIBZ
1772 static WFILE_T wtap_dump_file_open(wtap_dumper *wdh, const char *filename)
1774 if(wdh->compressed) {
1775 return gzwfile_open(filename);
1776 } else {
1777 return ws_fopen(filename, "wb");
1780 #else
1781 static WFILE_T wtap_dump_file_open(wtap_dumper *wdh _U_, const char *filename)
1783 return ws_fopen(filename, "wb");
1785 #endif
1787 /* internally open a file for writing (compressed or not) */
1788 #ifdef HAVE_LIBZ
1789 static WFILE_T wtap_dump_file_fdopen(wtap_dumper *wdh, int fd)
1791 if(wdh->compressed) {
1792 return gzwfile_fdopen(fd);
1793 } else {
1794 return fdopen(fd, "wb");
1797 #else
1798 static WFILE_T wtap_dump_file_fdopen(wtap_dumper *wdh _U_, int fd)
1800 return fdopen(fd, "wb");
1802 #endif
1804 /* internally writing raw bytes (compressed or not) */
1805 gboolean wtap_dump_file_write(wtap_dumper *wdh, const void *buf, size_t bufsize,
1806 int *err)
1808 size_t nwritten;
1810 #ifdef HAVE_LIBZ
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);
1818 return FALSE;
1820 } else
1821 #endif
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))
1830 *err = errno;
1831 else
1832 *err = WTAP_ERR_SHORT_WRITE;
1833 return FALSE;
1836 return TRUE;
1839 /* internally close a file for writing (compressed or not) */
1840 static int wtap_dump_file_close(wtap_dumper *wdh)
1842 #ifdef HAVE_LIBZ
1843 if(wdh->compressed) {
1844 return gzwfile_close((GZWFILE_T)wdh->fh);
1845 } else
1846 #endif
1848 return fclose((FILE *)wdh->fh);
1852 gint64 wtap_dump_file_seek(wtap_dumper *wdh, gint64 offset, int whence, int *err)
1854 #ifdef HAVE_LIBZ
1855 if(wdh->compressed) {
1856 *err = WTAP_ERR_CANT_SEEK_COMPRESSED;
1857 return -1;
1858 } else
1859 #endif
1861 if (-1 == fseek((FILE *)wdh->fh, (long)offset, whence)) {
1862 *err = errno;
1863 return -1;
1864 } else
1866 return 0;
1870 gint64 wtap_dump_file_tell(wtap_dumper *wdh, int *err)
1872 gint64 rval;
1873 #ifdef HAVE_LIBZ
1874 if(wdh->compressed) {
1875 *err = WTAP_ERR_CANT_SEEK_COMPRESSED;
1876 return -1;
1877 } else
1878 #endif
1880 if (-1 == (rval = ftell((FILE *)wdh->fh))) {
1881 *err = errno;
1882 return -1;
1883 } else
1885 return rval;