From Shekhar Chandra: support for version 3.0 of netscaler packet wire format.
[metze/wireshark/wip.git] / wiretap / file_access.c
1 /* file_access.c
2  *
3  * $Id$
4  *
5  * Wiretap Library
6  * Copyright (c) 1998 by Gilbert Ramirez <gram@alumni.rice.edu>
7  *
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.
12  *
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.
17  *
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.
21  */
22
23 #include "config.h"
24
25 #include <stdio.h>
26 #include <string.h>
27 #include <stdlib.h>
28
29 #ifdef HAVE_FCNTL_H
30 #include <fcntl.h>
31 #endif
32
33 #ifdef HAVE_UNISTD_H
34 #include <unistd.h>
35 #endif
36
37 #include <errno.h>
38
39 #include <wsutil/file_util.h>
40
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"
91
92 /*
93  * Add an extension, and all compressed versions thereof, to a GSList
94  * of extensions.
95  */
96 static GSList *add_extensions(GSList *extensions, const gchar *extension,
97     GSList *compressed_file_extensions)
98 {
99         GSList *compressed_file_extension;
100
101         /*
102          * Add the specified extension.
103          */
104         extensions = g_slist_append(extensions, g_strdup(extension));
105
106         /*
107          * Now add the extensions for compressed-file versions of
108          * that extension.
109          */
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));
116         }
117
118         return extensions;
119 }
120
121 /*
122  * File types that can be identified by file extensions.
123  */
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" },
152 };
153
154 #define N_FILE_TYPE_EXTENSIONS  (sizeof file_type_extensions_base / sizeof file_type_extensions_base[0])
155
156 static const struct file_extension_info* file_type_extensions = NULL;
157
158 static GArray* file_type_extensions_arr = NULL;
159
160 /* initialize the extensions array if it has not been initialized yet */
161 static void init_file_type_extensions(void) {
162
163         if (file_type_extensions_arr) return;
164
165         file_type_extensions_arr = g_array_new(FALSE,TRUE,sizeof(struct file_extension_info));
166
167         g_array_append_vals(file_type_extensions_arr,file_type_extensions_base,N_FILE_TYPE_EXTENSIONS);
168
169         file_type_extensions = (struct file_extension_info*)(void *)file_type_extensions_arr->data;
170 }
171
172 void wtap_register_file_type_extension(const struct file_extension_info *ei) {
173         init_file_type_extensions();
174
175         g_array_append_val(file_type_extensions_arr,*ei);
176
177         file_type_extensions = (const struct file_extension_info*)(void *)file_type_extensions_arr->data;
178 }
179
180 /* Return a list of all extensions that are used by all file types,
181    including compressed extensions, e.g. not just "pcap" but also
182    "pcap.gz" if we can read gzipped files.
183
184    All strings in the list are allocated with g_malloc() and must be freed
185    with g_free(). */
186 GSList *wtap_get_all_file_extensions_list(void)
187 {
188         GSList *compressed_file_extensions;
189         GSList *extensions;
190         unsigned int i;
191         gchar **extensions_set, **extensionp, *extension;
192
193         init_file_type_extensions();
194
195         extensions = NULL;      /* empty list, to start with */
196
197         /*
198          * Get the list of compressed-file extensions.
199          */
200         compressed_file_extensions = wtap_get_compressed_file_extensions();
201
202         for (i = 0; i < file_type_extensions_arr->len; i++) {
203                 /*
204                  * Split the extension-list string into a set of extensions.
205                  */
206                 extensions_set = g_strsplit(file_type_extensions[i].extensions,
207                     ";", 0);
208
209                 /*
210                  * Add each of those extensions to the list.
211                  */
212                 for (extensionp = extensions_set; *extensionp != NULL;
213                     extensionp++) {
214                         extension = *extensionp;
215
216                         /*
217                          * Add the extension, and all compressed variants
218                          * of it.
219                          */
220                         extensions = add_extensions(extensions, extension,
221                             compressed_file_extensions);
222                 }
223
224                 g_strfreev(extensions_set);
225         }
226
227         g_slist_free(compressed_file_extensions);
228         return extensions;
229 }
230
231 /* The open_file_* routines should return:
232  *
233  *      -1 on an I/O error;
234  *
235  *      1 if the file they're reading is one of the types it handles;
236  *
237  *      0 if the file they're reading isn't the type they're checking for.
238  *
239  * If the routine handles this type of file, it should set the "file_type"
240  * field in the "struct wtap" to the type of the file.
241  *
242  * Note that the routine does not have to free the private data pointer on
243  * error. The caller takes care of that by calling wtap_close on error.
244  * (See https://bugs.wireshark.org/bugzilla/show_bug.cgi?id=8518)
245  *
246  * However, the caller does have to free the private data pointer when
247  * returning 0, since the next file type will be called and will likely
248  * just overwrite the pointer.
249  *
250  * Put the trace files that are merely saved telnet-sessions last, since it's
251  * possible that you could have captured someone a router telnet-session
252  * using another tool. So, a libpcap trace of an toshiba "snoop" session
253  * should be discovered as a libpcap file, not a toshiba file.
254  */
255
256
257 static wtap_open_routine_t open_routines_base[] = {
258         /* Files that have magic bytes in fixed locations. These
259          * are easy to identify.
260          */
261         libpcap_open,
262         pcapng_open,
263         lanalyzer_open,
264         ngsniffer_open,
265         snoop_open,
266         iptrace_open,
267         netmon_open,
268         netxray_open,
269         radcom_open,
270         nettl_open,
271         visual_open,
272         _5views_open,
273         network_instruments_open,
274         peektagged_open,
275         dbs_etherwatch_open,
276         k12_open,
277         catapult_dct2000_open,
278         ber_open,          /* XXX - this is really a heuristic */
279         aethra_open,
280         btsnoop_open,
281         eyesdn_open,
282         packetlogger_open, /* This type does not have a magic number, but its
283                             * files are sometimes grabbed by mpeg_open. */
284         mpeg_open,
285         tnef_open,
286         dct3trace_open,
287         daintree_sna_open,
288         mime_file_open,
289         stanag4607_open,
290         /* Files that don't have magic bytes at a fixed location,
291          * but that instead require a heuristic of some sort to
292          * identify them.  This includes the ASCII trace files that
293          * would be, for example, saved copies of a Telnet session
294          * to some box.
295          */
296
297         /* I put NetScreen *before* erf, because there were some
298          * false positives with my test-files (Sake Blok, July 2007)
299          *
300          * I put VWR *after* ERF, because there were some cases where
301          * ERF files were misidentified as vwr files (Stephen
302          * Donnelly, August 2013; see bug 9054)
303          */
304         netscreen_open,
305         erf_open,
306         vwr_open,
307         ipfix_open,
308         k12text_open,
309         peekclassic_open,
310         pppdump_open,
311         iseries_open,
312         ascend_open,
313         toshiba_open,
314         i4btrace_open,
315         mp2t_open,
316         csids_open,
317         vms_open,
318         cosine_open,
319         hcidump_open,
320         commview_open,
321         nstrace_open,
322         camins_open
323 };
324
325 #define N_FILE_TYPES    (sizeof open_routines_base / sizeof open_routines_base[0])
326
327 static wtap_open_routine_t* open_routines = NULL;
328
329 static GArray* open_routines_arr = NULL;
330
331
332 /* initialize the open routines array if it has not been initialized yet */
333 static void init_open_routines(void) {
334
335         if (open_routines_arr) return;
336
337         open_routines_arr = g_array_new(FALSE,TRUE,sizeof(wtap_open_routine_t));
338
339         g_array_append_vals(open_routines_arr,open_routines_base,N_FILE_TYPES);
340
341         open_routines = (wtap_open_routine_t*)(void *)open_routines_arr->data;
342 }
343
344 void wtap_register_open_routine(wtap_open_routine_t open_routine, gboolean has_magic) {
345         init_open_routines();
346
347         if (has_magic)
348                 g_array_prepend_val(open_routines_arr,open_routine);
349         else
350                 g_array_append_val(open_routines_arr,open_routine);
351
352         open_routines = (wtap_open_routine_t*)(void *)open_routines_arr->data;
353 }
354
355 /*
356  * Visual C++ on Win32 systems doesn't define these.  (Old UNIX systems don't
357  * define them either.)
358  *
359  * Visual C++ on Win32 systems doesn't define S_IFIFO, it defines _S_IFIFO.
360  */
361 #ifndef S_ISREG
362 #define S_ISREG(mode)   (((mode) & S_IFMT) == S_IFREG)
363 #endif
364 #ifndef S_IFIFO
365 #define S_IFIFO _S_IFIFO
366 #endif
367 #ifndef S_ISFIFO
368 #define S_ISFIFO(mode)  (((mode) & S_IFMT) == S_IFIFO)
369 #endif
370 #ifndef S_ISDIR
371 #define S_ISDIR(mode)   (((mode) & S_IFMT) == S_IFDIR)
372 #endif
373
374 /* Opens a file and prepares a wtap struct.
375    If "do_random" is TRUE, it opens the file twice; the second open
376    allows the application to do random-access I/O without moving
377    the seek offset for sequential I/O, which is used by Wireshark
378    so that it can do sequential I/O to a capture file that's being
379    written to as new packets arrive independently of random I/O done
380    to display protocol trees for packets when they're selected. */
381 wtap* wtap_open_offline(const char *filename, int *err, char **err_info,
382                         gboolean do_random)
383 {
384         int     fd;
385         ws_statb64 statb;
386         wtap    *wth;
387         unsigned int    i;
388         gboolean use_stdin = FALSE;
389
390         /* open standard input if filename is '-' */
391         if (strcmp(filename, "-") == 0)
392                 use_stdin = TRUE;
393
394         /* First, make sure the file is valid */
395         if (use_stdin) {
396                 if (ws_fstat64(0, &statb) < 0) {
397                         *err = errno;
398                         return NULL;
399                 }
400         } else {
401                 if (ws_stat64(filename, &statb) < 0) {
402                         *err = errno;
403                         return NULL;
404                 }
405         }
406         if (S_ISFIFO(statb.st_mode)) {
407                 /*
408                  * Opens of FIFOs are allowed only when not opening
409                  * for random access.
410                  *
411                  * XXX - currently, we do seeking when trying to find
412                  * out the file type, so we don't actually support
413                  * opening FIFOs.  However, we may eventually
414                  * do buffering that allows us to do at least some
415                  * file type determination even on pipes, so we
416                  * allow FIFO opens and let things fail later when
417                  * we try to seek.
418                  */
419                 if (do_random) {
420                         *err = WTAP_ERR_RANDOM_OPEN_PIPE;
421                         return NULL;
422                 }
423         } else if (S_ISDIR(statb.st_mode)) {
424                 /*
425                  * Return different errors for "this is a directory"
426                  * and "this is some random special file type", so
427                  * the user can get a potentially more helpful error.
428                  */
429                 *err = EISDIR;
430                 return NULL;
431         } else if (! S_ISREG(statb.st_mode)) {
432                 *err = WTAP_ERR_NOT_REGULAR_FILE;
433                 return NULL;
434         }
435
436         /*
437          * We need two independent descriptors for random access, so
438          * they have different file positions.  If we're opening the
439          * standard input, we can only dup it to get additional
440          * descriptors, so we can't have two independent descriptors,
441          * and thus can't do random access.
442          */
443         if (use_stdin && do_random) {
444                 *err = WTAP_ERR_RANDOM_OPEN_STDIN;
445                 return NULL;
446         }
447
448         errno = ENOMEM;
449         wth = (wtap *)g_malloc0(sizeof(wtap));
450
451         /* Open the file */
452         errno = WTAP_ERR_CANT_OPEN;
453         if (use_stdin) {
454                 /*
455                  * We dup FD 0, so that we don't have to worry about
456                  * a file_close of wth->fh closing the standard
457                  * input of the process.
458                  */
459                 fd = ws_dup(0);
460                 if (fd < 0) {
461                         *err = errno;
462                         g_free(wth);
463                         return NULL;
464                 }
465 #ifdef _WIN32
466                 if (_setmode(fd, O_BINARY) == -1) {
467                         /* "Shouldn't happen" */
468                         *err = errno;
469                         g_free(wth);
470                         return NULL;
471                 }
472 #endif
473                 if (!(wth->fh = file_fdopen(fd))) {
474                         *err = errno;
475                         ws_close(fd);
476                         g_free(wth);
477                         return NULL;
478                 }
479         } else {
480                 if (!(wth->fh = file_open(filename))) {
481                         *err = errno;
482                         g_free(wth);
483                         return NULL;
484                 }
485         }
486
487         if (do_random) {
488                 if (!(wth->random_fh = file_open(filename))) {
489                         *err = errno;
490                         file_close(wth->fh);
491                         g_free(wth);
492                         return NULL;
493                 }
494         } else
495                 wth->random_fh = NULL;
496
497         /* initialization */
498         wth->file_encap = WTAP_ENCAP_UNKNOWN;
499         wth->subtype_sequential_close = NULL;
500         wth->subtype_close = NULL;
501         wth->tsprecision = WTAP_FILE_TSPREC_USEC;
502         wth->priv = NULL;
503
504         init_open_routines();
505         if (wth->random_fh) {
506                 wth->fast_seek = g_ptr_array_new();
507
508                 file_set_random_access(wth->fh, FALSE, wth->fast_seek);
509                 file_set_random_access(wth->random_fh, TRUE, wth->fast_seek);
510         }
511
512         /* Try all file types */
513         for (i = 0; i < open_routines_arr->len; i++) {
514                 /* Seek back to the beginning of the file; the open routine
515                    for the previous file type may have left the file
516                    position somewhere other than the beginning, and the
517                    open routine for this file type will probably want
518                    to start reading at the beginning.
519
520                    Initialize the data offset while we're at it. */
521                 if (file_seek(wth->fh, 0, SEEK_SET, err) == -1) {
522                         /* I/O error - give up */
523                         wtap_close(wth);
524                         return NULL;
525                 }
526
527                 switch ((*open_routines[i])(wth, err, err_info)) {
528
529                 case -1:
530                         /* I/O error - give up */
531                         wtap_close(wth);
532                         return NULL;
533
534                 case 0:
535                         /* No I/O error, but not that type of file */
536                         break;
537
538                 case 1:
539                         /* We found the file type */
540                         goto success;
541                 }
542         }
543
544         /* Well, it's not one of the types of file we know about. */
545         wtap_close(wth);
546         *err = WTAP_ERR_FILE_UNKNOWN_FORMAT;
547         return NULL;
548
549 success:
550         wth->frame_buffer = (struct Buffer *)g_malloc(sizeof(struct Buffer));
551         buffer_init(wth->frame_buffer, 1500);
552
553         if(wth->file_type == WTAP_FILE_PCAP){
554
555                 wtapng_if_descr_t descr;
556
557                 descr.wtap_encap = wth->file_encap;
558                 descr.time_units_per_second = 1000000; /* default microsecond resolution */
559                 descr.link_type = wtap_wtap_encap_to_pcap_encap(wth->file_encap);
560                 descr.snap_len = wth->snapshot_length;
561                 descr.opt_comment = NULL;
562                 descr.if_name = NULL;
563                 descr.if_description = NULL;
564                 descr.if_speed = 0;
565                 descr.if_tsresol = 6;
566                 descr.if_filter_str= NULL;
567                 descr.bpf_filter_len= 0;
568                 descr.if_filter_bpf_bytes= NULL;
569                 descr.if_os = NULL;
570                 descr.if_fcslen = -1;
571                 descr.num_stat_entries = 0;          /* Number of ISB:s */
572                 descr.interface_statistics = NULL;
573                 wth->number_of_interfaces= 1;
574                 wth->interface_data= g_array_new(FALSE, FALSE, sizeof(wtapng_if_descr_t));
575                 g_array_append_val(wth->interface_data, descr);
576
577         }
578         return wth;
579 }
580
581 /*
582  * Given the pathname of the file we just closed with wtap_fdclose(), attempt
583  * to reopen that file and assign the new file descriptor(s) to the sequential
584  * stream and, if do_random is TRUE, to the random stream.  Used on Windows
585  * after the rename of a file we had open was done or if the rename of a
586  * file on top of a file we had open failed.
587  *
588  * This is only required by Wireshark, not TShark, and, at the point that
589  * Wireshark is doing this, the sequential stream is closed, and the
590  * random stream is open, so this refuses to open pipes, and only
591  * reopens the random stream.
592  */
593 gboolean
594 wtap_fdreopen(wtap *wth, const char *filename, int *err)
595 {
596         ws_statb64 statb;
597
598         /*
599          * We need two independent descriptors for random access, so
600          * they have different file positions.  If we're opening the
601          * standard input, we can only dup it to get additional
602          * descriptors, so we can't have two independent descriptors,
603          * and thus can't do random access.
604          */
605         if (strcmp(filename, "-") == 0) {
606                 *err = WTAP_ERR_RANDOM_OPEN_STDIN;
607                 return FALSE;
608         }
609
610         /* First, make sure the file is valid */
611         if (ws_stat64(filename, &statb) < 0) {
612                 *err = errno;
613                 return FALSE;
614         }
615         if (S_ISFIFO(statb.st_mode)) {
616                 /*
617                  * Opens of FIFOs are not allowed; see above.
618                  */
619                 *err = WTAP_ERR_RANDOM_OPEN_PIPE;
620                 return FALSE;
621         } else if (S_ISDIR(statb.st_mode)) {
622                 /*
623                  * Return different errors for "this is a directory"
624                  * and "this is some random special file type", so
625                  * the user can get a potentially more helpful error.
626                  */
627                 *err = EISDIR;
628                 return FALSE;
629         } else if (! S_ISREG(statb.st_mode)) {
630                 *err = WTAP_ERR_NOT_REGULAR_FILE;
631                 return FALSE;
632         }
633
634         /* Open the file */
635         errno = WTAP_ERR_CANT_OPEN;
636         if (!file_fdreopen(wth->random_fh, filename)) {
637                 *err = errno;
638                 return FALSE;
639         }
640         return TRUE;
641 }
642
643 /* Table of the file types we know about.
644    Entries must be sorted by WTAP_FILE_xxx values in ascending order */
645 static const struct file_type_info dump_open_table_base[] = {
646         /* WTAP_FILE_UNKNOWN (only used internally for initialization) */
647         { NULL, NULL, NULL, NULL,
648           FALSE, FALSE, 0,
649           NULL, NULL },
650
651         /* WTAP_FILE_PCAP */
652         /* Gianluca Varenni suggests that we add "deprecated" to the description. */
653         { "Wireshark/tcpdump/... - pcap", "pcap", "pcap", "cap;dmp",
654           FALSE, FALSE, 0,
655           libpcap_dump_can_write_encap, libpcap_dump_open },
656
657         /* WTAP_FILE_PCAPNG */
658         { "Wireshark/... - pcapng", "pcapng", "pcapng", "ntar",
659           FALSE, TRUE, WTAP_COMMENT_PER_SECTION|WTAP_COMMENT_PER_INTERFACE|WTAP_COMMENT_PER_PACKET,
660           pcapng_dump_can_write_encap, pcapng_dump_open },
661
662         /* WTAP_FILE_PCAP_NSEC */
663         { "Wireshark - nanosecond libpcap", "nseclibpcap", "pcap", "cap;dmp",
664           FALSE, FALSE, 0,
665           libpcap_dump_can_write_encap, libpcap_dump_open },
666
667         /* WTAP_FILE_PCAP_AIX */
668         { "AIX tcpdump - libpcap", "aixlibpcap", "pcap", "cap;dmp",
669           FALSE, FALSE, 0,
670           NULL, NULL },
671
672         /* WTAP_FILE_PCAP_SS991029 */
673         { "Modified tcpdump - libpcap", "modlibpcap", "pcap", "cap;dmp",
674           FALSE, FALSE, 0,
675           libpcap_dump_can_write_encap, libpcap_dump_open },
676
677         /* WTAP_FILE_PCAP_NOKIA */
678         { "Nokia tcpdump - libpcap ", "nokialibpcap", "pcap", "cap;dmp",
679           FALSE, FALSE, 0,
680           libpcap_dump_can_write_encap, libpcap_dump_open },
681
682         /* WTAP_FILE_PCAP_SS990417 */
683         { "RedHat 6.1 tcpdump - libpcap", "rh6_1libpcap", "pcap", "cap;dmp",
684           FALSE, FALSE, 0,
685           libpcap_dump_can_write_encap, libpcap_dump_open },
686
687         /* WTAP_FILE_PCAP_SS990915 */
688         { "SuSE 6.3 tcpdump - libpcap", "suse6_3libpcap", "pcap", "cap;dmp",
689           FALSE, FALSE, 0,
690           libpcap_dump_can_write_encap, libpcap_dump_open },
691
692         /* WTAP_FILE_5VIEWS */
693         { "InfoVista 5View capture", "5views", "5vw", NULL,
694            TRUE, FALSE, 0,
695           _5views_dump_can_write_encap, _5views_dump_open },
696
697         /* WTAP_FILE_IPTRACE_1_0 */
698         { "AIX iptrace 1.0", "iptrace_1", NULL, NULL,
699           FALSE, FALSE, 0,
700           NULL, NULL },
701
702         /* WTAP_FILE_IPTRACE_2_0 */
703         { "AIX iptrace 2.0", "iptrace_2", NULL, NULL,
704           FALSE, FALSE, 0,
705           NULL, NULL },
706
707         /* WTAP_FILE_BER */
708         { "ASN.1 Basic Encoding Rules", "ber", NULL, NULL,
709           FALSE, FALSE, 0,
710           NULL, NULL },
711
712         /* WTAP_FILE_HCIDUMP */
713         { "Bluetooth HCI dump", "hcidump", NULL, NULL,
714           FALSE, FALSE, 0,
715           NULL, NULL },
716
717         /* WTAP_FILE_CATAPULT_DCT2000 */
718         { "Catapult DCT2000 trace (.out format)", "dct2000", "out", NULL,
719           FALSE, FALSE, 0,
720           catapult_dct2000_dump_can_write_encap, catapult_dct2000_dump_open },
721
722         /* WTAP_FILE_NETXRAY_OLD */
723         { "Cinco Networks NetXRay 1.x", "netxray1", "cap", NULL,
724           TRUE, FALSE, 0,
725           NULL, NULL },
726
727         /* WTAP_FILE_NETXRAY_1_0 */
728         { "Cinco Networks NetXRay 2.0 or later", "netxray2", "cap", NULL,
729           TRUE, FALSE, 0,
730           NULL, NULL },
731
732         /* WTAP_FILE_COSINE */
733         { "CoSine IPSX L2 capture", "cosine", "txt", NULL,
734           FALSE, FALSE, 0,
735           NULL, NULL },
736
737         /* WTAP_FILE_CSIDS */
738         { "CSIDS IPLog", "csids", NULL, NULL,
739           FALSE, FALSE, 0,
740           NULL, NULL },
741
742         /* WTAP_FILE_DBS_ETHERWATCH */
743         { "DBS Etherwatch (VMS)", "etherwatch", "txt", NULL,
744           FALSE, FALSE, 0,
745           NULL, NULL},
746
747         /* WTAP_FILE_ERF */
748         { "Endace ERF capture", "erf", "erf", NULL,
749           FALSE, FALSE, 0,
750           erf_dump_can_write_encap, erf_dump_open },
751
752         /* WTAP_FILE_EYESDN */
753         { "EyeSDN USB S0/E1 ISDN trace format", "eyesdn", "trc", NULL,
754            FALSE, FALSE, 0,
755            eyesdn_dump_can_write_encap, eyesdn_dump_open },
756
757         /* WTAP_FILE_NETTL */
758         { "HP-UX nettl trace", "nettl", "trc0", "trc1",
759           FALSE, FALSE, 0,
760           nettl_dump_can_write_encap, nettl_dump_open },
761
762         /* WTAP_FILE_ISERIES */
763         { "IBM iSeries comm. trace (ASCII)", "iseries_ascii", "txt", NULL,
764           FALSE, FALSE, 0,
765           NULL, NULL },
766
767         /* WTAP_FILE_ISERIES_UNICODE */
768         { "IBM iSeries comm. trace (UNICODE)", "iseries_unicode", "txt", NULL,
769           FALSE, FALSE, 0,
770           NULL, NULL },
771
772         /* WTAP_FILE_I4BTRACE */
773         { "I4B ISDN trace", "i4btrace", NULL, NULL,
774           FALSE, FALSE, 0,
775           NULL, NULL },
776
777         /* WTAP_FILE_ASCEND */
778         { "Lucent/Ascend access server trace", "ascend", "txt", NULL,
779           FALSE, FALSE, 0,
780           NULL, NULL },
781
782         /* WTAP_FILE_NETMON_1_x */
783         { "Microsoft NetMon 1.x", "netmon1", "cap", NULL,
784           TRUE, FALSE, 0,
785           netmon_dump_can_write_encap_1_x, netmon_dump_open },
786
787         /* WTAP_FILE_NETMON_2_x */
788         { "Microsoft NetMon 2.x", "netmon2", "cap", NULL,
789           TRUE, FALSE, 0,
790           netmon_dump_can_write_encap_2_x, netmon_dump_open },
791
792         /* WTAP_FILE_NGSNIFFER_UNCOMPRESSED */
793         { "Sniffer (DOS)", "ngsniffer", "cap", "enc;trc;fdc;syc",
794           FALSE, FALSE, 0,
795           ngsniffer_dump_can_write_encap, ngsniffer_dump_open },
796
797         /* WTAP_FILE_NGSNIFFER_COMPRESSED */
798         { "Sniffer (DOS), compressed", "ngsniffer_comp", "cap", "enc;trc;fdc;syc",
799           FALSE, FALSE, 0,
800           NULL, NULL },
801
802         /* WTAP_FILE_NETXRAY_1_1 */
803         { "NetXray, Sniffer (Windows) 1.1", "ngwsniffer_1_1", "cap", NULL,
804           TRUE, FALSE, 0,
805           netxray_dump_can_write_encap_1_1, netxray_dump_open_1_1 },
806
807         /* WTAP_FILE_NETXRAY_2_00x */
808         { "Sniffer (Windows) 2.00x", "ngwsniffer_2_0", "cap", "caz",
809           TRUE, FALSE, 0,
810           netxray_dump_can_write_encap_2_0, netxray_dump_open_2_0 },
811
812         /* WTAP_FILE_NETWORK_INSTRUMENTS */
813         { "Network Instruments Observer", "niobserver", "bfr", NULL,
814           FALSE, FALSE, 0,
815           network_instruments_dump_can_write_encap, network_instruments_dump_open },
816
817         /* WTAP_FILE_LANALYZER */
818         { "Novell LANalyzer","lanalyzer", "tr1", NULL,
819           TRUE, FALSE, 0,
820           lanalyzer_dump_can_write_encap, lanalyzer_dump_open },
821
822         /* WTAP_FILE_PPPDUMP */
823         { "pppd log (pppdump format)", "pppd", NULL, NULL,
824           FALSE, FALSE, 0,
825           NULL, NULL },
826
827         /* WTAP_FILE_RADCOM */
828         { "RADCOM WAN/LAN analyzer", "radcom", NULL, NULL,
829           FALSE, FALSE, 0,
830           NULL, NULL },
831
832         /* WTAP_FILE_SNOOP */
833         { "Sun snoop", "snoop", "snoop", "cap",
834           FALSE, FALSE, 0,
835           snoop_dump_can_write_encap, snoop_dump_open },
836
837         /* WTAP_FILE_SHOMITI */
838         { "Shomiti/Finisar Surveyor", "shomiti", "cap", NULL,
839           FALSE, FALSE, 0,
840           NULL, NULL },
841
842         /* WTAP_FILE_VMS */
843         { "TCPIPtrace (VMS)", "tcpiptrace", "txt", NULL,
844           FALSE, FALSE, 0,
845           NULL, NULL},
846
847         /* WTAP_FILE_K12 */
848         { "Tektronix K12xx 32-bit .rf5 format", "rf5", "rf5", NULL,
849            TRUE, FALSE, 0,
850            k12_dump_can_write_encap, k12_dump_open },
851
852         /* WTAP_FILE_TOSHIBA */
853         { "Toshiba Compact ISDN Router snoop", "toshiba", "txt", NULL,
854           FALSE, FALSE, 0,
855           NULL, NULL },
856
857         /* WTAP_FILE_VISUAL_NETWORKS */
858         { "Visual Networks traffic capture", "visual", NULL, NULL,
859           TRUE, FALSE, 0,
860           visual_dump_can_write_encap, visual_dump_open },
861
862         /* WTAP_FILE_PEEKCLASSIC_V56 */
863         { "WildPackets classic (V5 and V6)", "peekclassic56", "pkt", "tpc;apc;wpz",
864           FALSE, FALSE, 0,
865           NULL, NULL },
866
867         /* WTAP_FILE_PEEKCLASSIC_V7 */
868         { "WildPackets classic (V7)", "peekclassic7", "pkt", "tpc;apc;wpz",
869           FALSE, FALSE, 0,
870           NULL, NULL },
871
872         /* WTAP_FILE_PEEKTAGGED */
873         { "WildPackets tagged", "peektagged", "pkt", "tpc;apc;wpz",
874           FALSE, FALSE, 0,
875           NULL, NULL },
876
877         /* WTAP_FILE_MPEG */
878         { "MPEG", "mpeg", "mpeg", "mpg;mp3",
879           FALSE, FALSE, 0,
880           NULL, NULL },
881
882         /* WTAP_FILE_K12TEXT  */
883         { "K12 text file", "k12text", "txt", NULL,
884           FALSE, FALSE, 0,
885           k12text_dump_can_write_encap, k12text_dump_open },
886
887         /* WTAP_FILE_NETSCREEN */
888         { "NetScreen snoop text file", "netscreen", "txt", NULL,
889           FALSE, FALSE, 0,
890           NULL, NULL },
891
892         /* WTAP_FILE_COMMVIEW */
893         { "TamoSoft CommView", "commview", "ncf", NULL,
894           FALSE, FALSE, 0,
895           commview_dump_can_write_encap, commview_dump_open },
896
897         /* WTAP_FILE_BTSNOOP */
898         { "Symbian OS btsnoop", "btsnoop", "log", NULL,
899           FALSE, FALSE, 0,
900           btsnoop_dump_can_write_encap, btsnoop_dump_open_h4 },
901
902         /* WTAP_FILE_TNEF */
903         { "Transport-Neutral Encapsulation Format", "tnef", NULL, NULL,
904           FALSE, FALSE, 0,
905           NULL, NULL },
906
907         /* WTAP_FILE_DCT3TRACE */
908         { "Gammu DCT3 trace", "dct3trace", "xml", NULL,
909           FALSE, FALSE, 0,
910           NULL, NULL },
911
912         /* WTAP_FILE_PACKETLOGGER */
913         { "PacketLogger", "pklg", "pklg", NULL,
914           FALSE, FALSE, 0,
915           NULL, NULL },
916
917         /* WTAP_FILE_DAINTREE_SNA */
918         { "Daintree SNA", "dsna", "dcf", NULL,
919           FALSE, FALSE, 0,
920           NULL, NULL },
921
922         /* WTAP_FILE_NETSCALER_1_0 */
923         { "NetScaler Trace (Version 1.0)", "nstrace10", NULL, NULL,
924           TRUE, FALSE, 0,
925           nstrace_10_dump_can_write_encap, nstrace_dump_open },
926
927         /* WTAP_FILE_NETSCALER_2_0 */
928         { "NetScaler Trace (Version 2.0)", "nstrace20", "cap", NULL,
929           TRUE, FALSE, 0,
930           nstrace_20_dump_can_write_encap, nstrace_dump_open },
931
932         /* WTAP_FILE_JPEG_JFIF */
933         { "JPEG/JFIF", "jpeg", "jpg", "jpeg;jfif",
934           FALSE, FALSE, 0,
935           NULL, NULL },
936
937         /* WTAP_FILE_IPFIX */
938         { "IPFIX File Format", "ipfix", "pfx", "ipfix",
939           FALSE, FALSE, 0,
940           NULL, NULL },
941
942         /* WTAP_ENCAP_MIME */
943         { "MIME File Format", "mime", NULL, NULL,
944            FALSE, FALSE, 0,
945            NULL, NULL },
946
947         /* WTAP_FILE_AETHRA */
948         { "Aethra .aps file", "aethra", "aps", NULL,
949           FALSE, FALSE, 0,
950           NULL, NULL },
951
952         /* WTAP_FILE_MPEG_2_TS */
953         { "MPEG2 transport stream", "mp2t", "mp2t", "ts;mpg",
954           FALSE, FALSE, 0,
955           NULL, NULL },
956
957         /* WTAP_FILE_VWR_80211 */
958         { "Ixia IxVeriWave .vwr Raw 802.11 Capture", "vwr80211", "vwr", NULL,
959           FALSE, FALSE, 0,
960           NULL, NULL },
961
962         /* WTAP_FILE_VWR_ETH */
963         { "Ixia IxVeriWave .vwr Raw Ethernet Capture", "vwreth", "vwr", NULL,
964           FALSE, FALSE, 0,
965           NULL, NULL },
966
967         /* WTAP_FILE_CAMINS */
968         { "CAM Inspector file", "camins", "camins", NULL,
969           FALSE, FALSE, 0,
970           NULL, NULL },
971
972         /* WTAP_FILE_STANAG_4607 */
973         { "STANAG 4607 Format", "stanag4607", NULL, NULL,
974           FALSE, FALSE, 0,
975           NULL, NULL },
976
977         /* WTAP_FILE_NETSCALER_3_0 */
978         { "NetScaler Trace (Version 3.0)", "nstrace30", "cap", NULL,
979           TRUE, FALSE, 0,
980           nstrace_30_dump_can_write_encap, nstrace_dump_open }
981
982 };
983
984 gint wtap_num_file_types = sizeof(dump_open_table_base) / sizeof(struct file_type_info);
985
986 static GArray*  dump_open_table_arr = NULL;
987 static const struct file_type_info* dump_open_table = dump_open_table_base;
988
989 /* initialize the file types array if it has not being initialized yet */
990 static void init_file_types(void) {
991
992         if (dump_open_table_arr) return;
993
994         dump_open_table_arr = g_array_new(FALSE,TRUE,sizeof(struct file_type_info));
995
996         g_array_append_vals(dump_open_table_arr,dump_open_table_base,wtap_num_file_types);
997
998         dump_open_table = (const struct file_type_info*)(void *)dump_open_table_arr->data;
999 }
1000
1001 int wtap_register_file_type(const struct file_type_info* fi) {
1002         init_file_types();
1003
1004         g_array_append_val(dump_open_table_arr,*fi);
1005
1006         dump_open_table = (const struct file_type_info*)(void *)dump_open_table_arr->data;
1007
1008         return wtap_num_file_types++;
1009 }
1010
1011 int wtap_get_num_file_types(void)
1012 {
1013         return wtap_num_file_types;
1014 }
1015
1016 /*
1017  * Given a GArray of WTAP_ENCAP_ types, return the per-file encapsulation
1018  * type that would be needed to write out a file with those types.  If
1019  * there's only one type, it's that type, otherwise it's
1020  * WTAP_ENCAP_PER_PACKET.
1021  */
1022 int
1023 wtap_dump_file_encap_type(const GArray *file_encaps)
1024 {
1025         int encap;
1026
1027         encap = WTAP_ENCAP_PER_PACKET;
1028         if (file_encaps->len == 1) {
1029                 /* OK, use the one-and-only encapsulation type. */
1030                 encap = g_array_index(file_encaps, gint, 0);
1031         }
1032         return encap;
1033 }
1034
1035 static gboolean
1036 wtap_dump_can_write_encap(int filetype, int encap)
1037 {
1038         if (filetype < 0 || filetype >= wtap_num_file_types
1039             || dump_open_table[filetype].can_write_encap == NULL)
1040                 return FALSE;
1041
1042         if ((*dump_open_table[filetype].can_write_encap)(encap) != 0)
1043                 return FALSE;
1044
1045         return TRUE;
1046 }
1047
1048 /*
1049  * Return TRUE if a capture with a given GArray of encapsulation types
1050  * and a given bitset of comment types can be written in a specified
1051  * format, and FALSE if it can't.
1052  */
1053 static gboolean
1054 wtap_dump_can_write_format(int ft, const GArray *file_encaps,
1055     guint32 required_comment_types)
1056 {
1057         guint i;
1058
1059         /*
1060          * Can we write in this format?
1061          */
1062         if (!wtap_dump_can_open(ft)) {
1063                 /* No. */
1064                 return FALSE;
1065         }
1066
1067         /*
1068          * Yes.  Can we write out all the required comments in this
1069          * format?
1070          */
1071         if (!wtap_dump_supports_comment_types(ft, required_comment_types)) {
1072                 /* No. */
1073                 return FALSE;
1074         }
1075
1076         /*
1077          * Yes.  Is the required per-file encapsulation type supported?
1078          * This might be WTAP_ENCAP_PER_PACKET.
1079          */
1080         if (!wtap_dump_can_write_encap(ft, wtap_dump_file_encap_type(file_encaps))) {
1081                 /* No. */
1082                 return FALSE;
1083         }
1084
1085         /*
1086          * Yes.  Are all the individual encapsulation types supported?
1087          */
1088         for (i = 0; i < file_encaps->len; i++) {
1089                 if (!wtap_dump_can_write_encap(ft,
1090                     g_array_index(file_encaps, int, i))) {
1091                         /* No - one of them isn't. */
1092                         return FALSE;
1093                 }
1094         }
1095
1096         /* Yes - we're OK. */
1097         return TRUE;
1098 }
1099
1100 /**
1101  * Return TRUE if we can write a file with the given GArray of
1102  * encapsulation types and the given bitmask of comment types.
1103  */
1104 gboolean
1105 wtap_dump_can_write(const GArray *file_encaps, guint32 required_comment_types)
1106 {
1107   int ft;
1108
1109   for (ft = 0; ft < WTAP_NUM_FILE_TYPES; ft++) {
1110     /* To save a file with Wiretap, Wiretap has to handle that format,
1111        and its code to handle that format must be able to write a file
1112        with this file's encapsulation types. */
1113     if (wtap_dump_can_write_format(ft, file_encaps, required_comment_types)) {
1114       /* OK, we can write it out in this type. */
1115       return TRUE;
1116     }
1117   }
1118
1119   /* No, we couldn't save it in any format. */
1120   return FALSE;
1121 }
1122
1123 /**
1124  * Get a GArray of WTAP_FILE_ values for file types that can be used
1125  * to save a file of a given type with a given GArray of encapsulation
1126  * types and the given bitmask of comment types.
1127  */
1128 GArray *
1129 wtap_get_savable_file_types(int file_type, const GArray *file_encaps,
1130     guint32 required_comment_types)
1131 {
1132         GArray *savable_file_types;
1133         int ft;
1134         int default_file_type = -1;
1135         int other_file_type = -1;
1136
1137         /* Can we save this file in its own file type? */
1138         if (wtap_dump_can_write_format(file_type, file_encaps,
1139                                        required_comment_types)) {
1140                 /* Yes - make that the default file type. */
1141                 default_file_type = file_type;
1142         } else {
1143                 /* OK, find the first file type we *can* save it as. */
1144                 default_file_type = -1;
1145                 for (ft = 0; ft < WTAP_NUM_FILE_TYPES; ft++) {
1146                         if (wtap_dump_can_write_format(ft, file_encaps,
1147                                                        required_comment_types)) {
1148                                 /* OK, got it. */
1149                                 default_file_type = ft;
1150                         }
1151                 }
1152         }
1153
1154         if (default_file_type == -1) {
1155                 /* We don't support writing this file as any file type. */
1156                 return NULL;
1157         }
1158
1159         /* Allocate the array. */
1160         savable_file_types = g_array_new(FALSE, FALSE, (guint)sizeof (int));
1161
1162         /* Put the default file format first in the list. */
1163         g_array_append_val(savable_file_types, default_file_type);
1164
1165         /* If the default is pcap, put pcap-NG right after it if we can
1166            also write it in pcap-NG format; otherwise, if the default is
1167            pcap-NG, put pcap right after it if we can also write it in
1168            pcap format. */
1169         if (default_file_type == WTAP_FILE_PCAP) {
1170                 if (wtap_dump_can_write_format(WTAP_FILE_PCAPNG, file_encaps,
1171                                                required_comment_types))
1172                         other_file_type = WTAP_FILE_PCAPNG;
1173         } else if (default_file_type == WTAP_FILE_PCAPNG) {
1174                 if (wtap_dump_can_write_format(WTAP_FILE_PCAP, file_encaps,
1175                                                required_comment_types))
1176                         other_file_type = WTAP_FILE_PCAP;
1177         }
1178         if (other_file_type != -1)
1179                 g_array_append_val(savable_file_types, other_file_type);
1180
1181         /* Add all the other file types that work. */
1182         for (ft = 0; ft < WTAP_NUM_FILE_TYPES; ft++) {
1183                 if (ft == WTAP_FILE_UNKNOWN)
1184                         continue;       /* not a real file type */
1185                 if (ft == default_file_type || ft == other_file_type)
1186                         continue;       /* we've already done this one */
1187                 if (wtap_dump_can_write_format(ft, file_encaps,
1188                                                required_comment_types)) {
1189                         /* OK, we can write it out in this type. */
1190                         g_array_append_val(savable_file_types, ft);
1191                 }
1192         }
1193
1194         return savable_file_types;
1195 }
1196
1197 /* Name that should be somewhat descriptive. */
1198 const char *wtap_file_type_string(int filetype)
1199 {
1200         if (filetype < 0 || filetype >= wtap_num_file_types) {
1201                 g_error("Unknown capture file type %d", filetype);
1202                 /** g_error() does an abort() and thus never returns **/
1203                 return "";
1204         } else
1205                 return dump_open_table[filetype].name;
1206 }
1207
1208 /* Name to use in, say, a command-line flag specifying the type. */
1209 const char *wtap_file_type_short_string(int filetype)
1210 {
1211         if (filetype < 0 || filetype >= wtap_num_file_types)
1212                 return NULL;
1213         else
1214                 return dump_open_table[filetype].short_name;
1215 }
1216
1217 /* Translate a short name to a capture file type. */
1218 int wtap_short_string_to_file_type(const char *short_name)
1219 {
1220         int filetype;
1221
1222         for (filetype = 0; filetype < wtap_num_file_types; filetype++) {
1223                 if (dump_open_table[filetype].short_name != NULL &&
1224                     strcmp(short_name, dump_open_table[filetype].short_name) == 0)
1225                         return filetype;
1226         }
1227
1228         /*
1229          * We now call the "libpcap" file format just "pcap", but we
1230          * allow it to be specified as "libpcap" as well, for
1231          * backwards compatibility.
1232          */
1233         if (strcmp(short_name, "libpcap") == 0)
1234                 return WTAP_FILE_PCAP;
1235
1236         return -1;      /* no such file type, or we can't write it */
1237 }
1238
1239 static GSList *
1240 add_extensions_for_filetype(int filetype, GSList *extensions,
1241     GSList *compressed_file_extensions)
1242 {
1243         gchar **extensions_set, **extensionp;
1244         gchar *extension;
1245
1246         /*
1247          * Add the default extension, and all compressed variants of
1248          * it.
1249          */
1250         extensions = add_extensions(extensions,
1251             dump_open_table[filetype].default_file_extension,
1252             compressed_file_extensions);
1253
1254         if (dump_open_table[filetype].additional_file_extensions != NULL) {
1255                 /*
1256                  * We have additional extensions; add them.
1257                  *
1258                  * First, split the extension-list string into a set of
1259                  * extensions.
1260                  */
1261                 extensions_set = g_strsplit(dump_open_table[filetype].additional_file_extensions,
1262                     ";", 0);
1263
1264                 /*
1265                  * Add each of those extensions to the list.
1266                  */
1267                 for (extensionp = extensions_set; *extensionp != NULL;
1268                     extensionp++) {
1269                         extension = *extensionp;
1270
1271                         /*
1272                          * Add the extension, and all compressed variants
1273                          * of it.
1274                          */
1275                         extensions = add_extensions(extensions, extension,
1276                             compressed_file_extensions);
1277                 }
1278
1279                 g_strfreev(extensions_set);
1280         }
1281         return extensions;
1282 }
1283
1284 /* Return a list of file extensions that are used by the specified file type.
1285
1286    If include_compressed is TRUE, the list will include compressed
1287    extensions, e.g. not just "pcap" but also "pcap.gz" if we can read
1288    gzipped files.
1289
1290    All strings in the list are allocated with g_malloc() and must be freed
1291    with g_free(). */
1292 GSList *wtap_get_file_extensions_list(int filetype, gboolean include_compressed)
1293 {
1294         GSList *compressed_file_extensions;
1295         GSList *extensions;
1296
1297         if (filetype < 0 || filetype >= wtap_num_file_types)
1298                 return NULL;    /* not a valid file type */
1299
1300         if (dump_open_table[filetype].default_file_extension == NULL)
1301                 return NULL;    /* valid, but no extensions known */
1302
1303         extensions = NULL;      /* empty list, to start with */
1304
1305         /*
1306          * If include_compressions is true, get the list of compressed-file
1307          * extensions.
1308          */
1309         if (include_compressed)
1310                 compressed_file_extensions = wtap_get_compressed_file_extensions();
1311         else
1312                 compressed_file_extensions = NULL;
1313
1314         /*
1315          * Add all this file type's extensions, with compressed
1316          * variants.
1317          */
1318         extensions = add_extensions_for_filetype(filetype, extensions,
1319             compressed_file_extensions);
1320
1321         g_slist_free(compressed_file_extensions);
1322         return extensions;
1323 }
1324
1325 /*
1326  * Free a list returned by wtap_get_file_extensions_list().
1327  */
1328 void wtap_free_file_extensions_list(GSList *extensions)
1329 {
1330         GSList *extension;
1331
1332         for (extension = extensions; extension != NULL;
1333             extension = g_slist_next(extension)) {
1334                 g_free(extension->data);
1335         }
1336         g_slist_free(extensions);
1337 }
1338
1339 /* Return the default file extension to use with the specified file type;
1340    that's just the extension, without any ".". */
1341 const char *wtap_default_file_extension(int filetype)
1342 {
1343         if (filetype < 0 || filetype >= wtap_num_file_types)
1344                 return NULL;
1345         else
1346                 return dump_open_table[filetype].default_file_extension;
1347 }
1348
1349 gboolean wtap_dump_can_open(int filetype)
1350 {
1351         if (filetype < 0 || filetype >= wtap_num_file_types
1352             || dump_open_table[filetype].dump_open == NULL)
1353                 return FALSE;
1354
1355         return TRUE;
1356 }
1357
1358 #ifdef HAVE_LIBZ
1359 gboolean wtap_dump_can_compress(int filetype)
1360 {
1361         /*
1362          * If this is an unknown file type, or if we have to
1363          * seek when writing out a file with this file type,
1364          * return FALSE.
1365          */
1366         if (filetype < 0 || filetype >= wtap_num_file_types
1367             || dump_open_table[filetype].writing_must_seek)
1368                 return FALSE;
1369
1370         return TRUE;
1371 }
1372 #else
1373 gboolean wtap_dump_can_compress(int filetype _U_)
1374 {
1375         return FALSE;
1376 }
1377 #endif
1378
1379 gboolean wtap_dump_has_name_resolution(int filetype)
1380 {
1381         if (filetype < 0 || filetype >= wtap_num_file_types
1382             || dump_open_table[filetype].has_name_resolution == FALSE)
1383                 return FALSE;
1384
1385         return TRUE;
1386 }
1387
1388 gboolean wtap_dump_supports_comment_types(int filetype, guint32 comment_types)
1389 {
1390         guint32 supported_comment_types;
1391
1392         if (filetype < 0 || filetype >= wtap_num_file_types)
1393                 return FALSE;
1394
1395         supported_comment_types = dump_open_table[filetype].supported_comment_types;
1396
1397         if ((comment_types & supported_comment_types) == comment_types)
1398                 return TRUE;
1399         return FALSE;
1400 }
1401
1402 static gboolean wtap_dump_open_check(int filetype, int encap, gboolean comressed, int *err);
1403 static wtap_dumper* wtap_dump_alloc_wdh(int filetype, int encap, int snaplen,
1404                                         gboolean compressed, int *err);
1405 static gboolean wtap_dump_open_finish(wtap_dumper *wdh, int filetype, gboolean compressed, int *err);
1406
1407 static WFILE_T wtap_dump_file_open(wtap_dumper *wdh, const char *filename);
1408 static WFILE_T wtap_dump_file_fdopen(wtap_dumper *wdh, int fd);
1409 static int wtap_dump_file_close(wtap_dumper *wdh);
1410
1411 wtap_dumper* wtap_dump_open(const char *filename, int filetype, int encap,
1412                                 int snaplen, gboolean compressed, int *err)
1413 {
1414         return wtap_dump_open_ng(filename, filetype, encap,snaplen, compressed, NULL, NULL, err);
1415 }
1416
1417 static wtap_dumper *
1418 wtap_dump_init_dumper(int filetype, int encap, int snaplen, gboolean compressed,
1419     wtapng_section_t *shb_hdr, wtapng_iface_descriptions_t *idb_inf, int *err)
1420 {
1421         wtap_dumper *wdh;
1422
1423         /* Allocate a data structure for the output stream. */
1424         wdh = wtap_dump_alloc_wdh(filetype, encap, snaplen, compressed, err);
1425         if (wdh == NULL)
1426                 return NULL;    /* couldn't allocate it */
1427
1428         /* Set Section Header Block data */
1429         wdh->shb_hdr = shb_hdr;
1430         /* Set Interface Description Block data */
1431         if ((idb_inf != NULL) && (idb_inf->number_of_interfaces > 0)) {
1432                 wdh->number_of_interfaces = idb_inf->number_of_interfaces;
1433                 wdh->interface_data = idb_inf->interface_data;
1434         } else {
1435                 wtapng_if_descr_t descr;
1436
1437                 descr.wtap_encap = encap;
1438                 descr.time_units_per_second = 1000000; /* default microsecond resolution */
1439                 descr.link_type = wtap_wtap_encap_to_pcap_encap(encap);
1440                 descr.snap_len = snaplen;
1441                 descr.opt_comment = NULL;
1442                 descr.if_name = g_strdup("Unknown/not available in original file format(libpcap)");
1443                 descr.if_description = NULL;
1444                 descr.if_speed = 0;
1445                 descr.if_tsresol = 6;
1446                 descr.if_filter_str= NULL;
1447                 descr.bpf_filter_len= 0;
1448                 descr.if_filter_bpf_bytes= NULL;
1449                 descr.if_os = NULL;
1450                 descr.if_fcslen = -1;
1451                 descr.num_stat_entries = 0;          /* Number of ISB:s */
1452                 descr.interface_statistics = NULL;
1453                 wdh->number_of_interfaces= 1;
1454                 wdh->interface_data= g_array_new(FALSE, FALSE, sizeof(wtapng_if_descr_t));
1455                 g_array_append_val(wdh->interface_data, descr);
1456         }
1457         return wdh;
1458 }
1459
1460 wtap_dumper* wtap_dump_open_ng(const char *filename, int filetype, int encap,
1461                                 int snaplen, gboolean compressed, wtapng_section_t *shb_hdr, wtapng_iface_descriptions_t *idb_inf, int *err)
1462 {
1463         wtap_dumper *wdh;
1464         WFILE_T fh;
1465
1466         /* Check whether we can open a capture file with that file type
1467            and that encapsulation. */
1468         if (!wtap_dump_open_check(filetype, encap, compressed, err))
1469                 return NULL;
1470
1471         /* Allocate and initialize a data structure for the output stream. */
1472         wdh = wtap_dump_init_dumper(filetype, encap, snaplen, compressed,
1473             shb_hdr, idb_inf, err);
1474         if (wdh == NULL)
1475                 return NULL;
1476
1477         /* "-" means stdout */
1478         if (strcmp(filename, "-") == 0) {
1479                 if (compressed) {
1480                         *err = EINVAL;  /* XXX - return a Wiretap error code for this */
1481                         g_free(wdh);
1482                         return NULL;    /* compress won't work on stdout */
1483                 }
1484 #ifdef _WIN32
1485                 if (_setmode(fileno(stdout), O_BINARY) == -1) {
1486                         /* "Should not happen" */
1487                         *err = errno;
1488                         g_free(wdh);
1489                         return NULL;    /* couldn't put standard output in binary mode */
1490                 }
1491 #endif
1492                 wdh->fh = stdout;
1493         } else {
1494                 /* In case "fopen()" fails but doesn't set "errno", set "errno"
1495                    to a generic "the open failed" error. */
1496                 errno = WTAP_ERR_CANT_OPEN;
1497                 fh = wtap_dump_file_open(wdh, filename);
1498                 if (fh == NULL) {
1499                         *err = errno;
1500                         g_free(wdh);
1501                         return NULL;    /* can't create file */
1502                 }
1503                 wdh->fh = fh;
1504         }
1505
1506         if (!wtap_dump_open_finish(wdh, filetype, compressed, err)) {
1507                 /* Get rid of the file we created; we couldn't finish
1508                    opening it. */
1509                 if (wdh->fh != stdout) {
1510                         wtap_dump_file_close(wdh);
1511                         ws_unlink(filename);
1512                 }
1513                 g_free(wdh);
1514                 return NULL;
1515         }
1516         return wdh;
1517 }
1518
1519 wtap_dumper* wtap_dump_fdopen(int fd, int filetype, int encap, int snaplen,
1520                                 gboolean compressed, int *err)
1521 {
1522         return wtap_dump_fdopen_ng(fd, filetype, encap, snaplen, compressed, NULL, NULL, err);
1523 }
1524
1525 wtap_dumper* wtap_dump_fdopen_ng(int fd, int filetype, int encap, int snaplen,
1526                                 gboolean compressed, wtapng_section_t *shb_hdr, wtapng_iface_descriptions_t *idb_inf, int *err)
1527 {
1528         wtap_dumper *wdh;
1529         WFILE_T fh;
1530
1531         /* Check whether we can open a capture file with that file type
1532            and that encapsulation. */
1533         if (!wtap_dump_open_check(filetype, encap, compressed, err))
1534                 return NULL;
1535
1536         /* Allocate and initialize a data structure for the output stream. */
1537         wdh = wtap_dump_init_dumper(filetype, encap, snaplen, compressed,
1538             shb_hdr, idb_inf, err);
1539         if (wdh == NULL)
1540                 return NULL;
1541
1542 #ifdef _WIN32
1543         if (fd == 1) {
1544                 if (_setmode(fileno(stdout), O_BINARY) == -1) {
1545                         /* "Should not happen" */
1546                         *err = errno;
1547                         g_free(wdh);
1548                         return NULL;    /* couldn't put standard output in binary mode */
1549                 }
1550         }
1551 #endif
1552
1553         /* In case "fopen()" fails but doesn't set "errno", set "errno"
1554            to a generic "the open failed" error. */
1555         errno = WTAP_ERR_CANT_OPEN;
1556         fh = wtap_dump_file_fdopen(wdh, fd);
1557         if (fh == NULL) {
1558                 *err = errno;
1559                 g_free(wdh);
1560                 return NULL;    /* can't create standard I/O stream */
1561         }
1562         wdh->fh = fh;
1563
1564         if (!wtap_dump_open_finish(wdh, filetype, compressed, err)) {
1565                 wtap_dump_file_close(wdh);
1566                 g_free(wdh);
1567                 return NULL;
1568         }
1569         return wdh;
1570 }
1571
1572 static gboolean wtap_dump_open_check(int filetype, int encap, gboolean compressed, int *err)
1573 {
1574         if (!wtap_dump_can_open(filetype)) {
1575                 /* Invalid type, or type we don't know how to write. */
1576                 *err = WTAP_ERR_UNSUPPORTED_FILE_TYPE;
1577                 return FALSE;
1578         }
1579
1580         /* OK, we know how to write that type; can we write the specified
1581            encapsulation type? */
1582         *err = (*dump_open_table[filetype].can_write_encap)(encap);
1583         if (*err != 0)
1584                 return FALSE;
1585
1586         /* if compression is wanted, do we support this for this filetype? */
1587         if(compressed && !wtap_dump_can_compress(filetype)) {
1588                 *err = WTAP_ERR_COMPRESSION_NOT_SUPPORTED;
1589                 return FALSE;
1590         }
1591
1592         *err = (*dump_open_table[filetype].can_write_encap)(encap);
1593         if (*err != 0)
1594                 return FALSE;
1595
1596         /* All systems go! */
1597         return TRUE;
1598 }
1599
1600 static wtap_dumper* wtap_dump_alloc_wdh(int filetype, int encap, int snaplen,
1601                                         gboolean compressed, int *err)
1602 {
1603         wtap_dumper *wdh;
1604
1605         wdh = (wtap_dumper *)g_malloc0(sizeof (wtap_dumper));
1606         if (wdh == NULL) {
1607                 *err = errno;
1608                 return NULL;
1609         }
1610
1611         wdh->file_type = filetype;
1612         wdh->snaplen = snaplen;
1613         wdh->encap = encap;
1614         wdh->compressed = compressed;
1615         return wdh;
1616 }
1617
1618 static gboolean wtap_dump_open_finish(wtap_dumper *wdh, int filetype, gboolean compressed, int *err)
1619 {
1620         int fd;
1621         gboolean cant_seek;
1622
1623         /* Can we do a seek on the file descriptor?
1624            If not, note that fact. */
1625         if(compressed) {
1626                 cant_seek = TRUE;
1627         } else {
1628                 fd = fileno((FILE *)wdh->fh);
1629                 if (lseek(fd, 1, SEEK_CUR) == -1)
1630                         cant_seek = TRUE;
1631                 else {
1632                         /* Undo the seek. */
1633                         lseek(fd, 0, SEEK_SET);
1634                         cant_seek = FALSE;
1635                 }
1636         }
1637
1638         /* If this file type requires seeking, and we can't seek, fail. */
1639         if (dump_open_table[filetype].writing_must_seek && cant_seek) {
1640                 *err = WTAP_ERR_CANT_WRITE_TO_PIPE;
1641                 return FALSE;
1642         }
1643
1644         /* Now try to open the file for writing. */
1645         if (!(*dump_open_table[filetype].dump_open)(wdh, err)) {
1646                 return FALSE;
1647         }
1648
1649         return TRUE;    /* success! */
1650 }
1651
1652 gboolean wtap_dump(wtap_dumper *wdh, const struct wtap_pkthdr *phdr,
1653                    const guint8 *pd, int *err)
1654 {
1655         return (wdh->subtype_write)(wdh, phdr, pd, err);
1656 }
1657
1658 void wtap_dump_flush(wtap_dumper *wdh)
1659 {
1660 #ifdef HAVE_LIBZ
1661         if(wdh->compressed) {
1662                 gzwfile_flush((GZWFILE_T)wdh->fh);
1663         } else
1664 #endif
1665         {
1666                 fflush((FILE *)wdh->fh);
1667         }
1668 }
1669
1670 gboolean wtap_dump_close(wtap_dumper *wdh, int *err)
1671 {
1672         gboolean ret = TRUE;
1673
1674         if (wdh->subtype_close != NULL) {
1675                 /* There's a close routine for this dump stream. */
1676                 if (!(wdh->subtype_close)(wdh, err))
1677                         ret = FALSE;
1678         }
1679         errno = WTAP_ERR_CANT_CLOSE;
1680         /* Don't close stdout */
1681         if (wdh->fh != stdout) {
1682                 if (wtap_dump_file_close(wdh) == EOF) {
1683                         if (ret) {
1684                                 /* The per-format close function succeeded,
1685                                    but the fclose didn't.  Save the reason
1686                                    why, if our caller asked for it. */
1687                                 if (err != NULL)
1688                                         *err = errno;
1689                         }
1690                         ret = FALSE;
1691                 }
1692         } else {
1693                 /* as we don't close stdout, at least try to flush it */
1694                 wtap_dump_flush(wdh);
1695         }
1696         if (wdh->priv != NULL)
1697                 g_free(wdh->priv);
1698         g_free(wdh);
1699         return ret;
1700 }
1701
1702 gint64 wtap_get_bytes_dumped(wtap_dumper *wdh)
1703 {
1704         return wdh->bytes_dumped;
1705 }
1706
1707 void wtap_set_bytes_dumped(wtap_dumper *wdh, gint64 bytes_dumped)
1708 {
1709         wdh->bytes_dumped = bytes_dumped;
1710 }
1711
1712 gboolean wtap_dump_set_addrinfo_list(wtap_dumper *wdh, addrinfo_lists_t *addrinfo_lists)
1713 {
1714         if (!wdh || wdh->file_type < 0 || wdh->file_type >= wtap_num_file_types
1715                 || dump_open_table[wdh->file_type].has_name_resolution == FALSE)
1716                         return FALSE;
1717         wdh->addrinfo_lists = addrinfo_lists;
1718         return TRUE;
1719 }
1720
1721 /* internally open a file for writing (compressed or not) */
1722 #ifdef HAVE_LIBZ
1723 static WFILE_T wtap_dump_file_open(wtap_dumper *wdh, const char *filename)
1724 {
1725         if(wdh->compressed) {
1726                 return gzwfile_open(filename);
1727         } else {
1728                 return ws_fopen(filename, "wb");
1729         }
1730 }
1731 #else
1732 static WFILE_T wtap_dump_file_open(wtap_dumper *wdh _U_, const char *filename)
1733 {
1734         return ws_fopen(filename, "wb");
1735 }
1736 #endif
1737
1738 /* internally open a file for writing (compressed or not) */
1739 #ifdef HAVE_LIBZ
1740 static WFILE_T wtap_dump_file_fdopen(wtap_dumper *wdh, int fd)
1741 {
1742         if(wdh->compressed) {
1743                 return gzwfile_fdopen(fd);
1744         } else {
1745                 return fdopen(fd, "wb");
1746         }
1747 }
1748 #else
1749 static WFILE_T wtap_dump_file_fdopen(wtap_dumper *wdh _U_, int fd)
1750 {
1751         return fdopen(fd, "wb");
1752 }
1753 #endif
1754
1755 /* internally writing raw bytes (compressed or not) */
1756 gboolean wtap_dump_file_write(wtap_dumper *wdh, const void *buf, size_t bufsize,
1757                      int *err)
1758 {
1759         size_t nwritten;
1760
1761 #ifdef HAVE_LIBZ
1762         if (wdh->compressed) {
1763                 nwritten = gzwfile_write((GZWFILE_T)wdh->fh, buf, (unsigned) bufsize);
1764                 /*
1765                  * gzwfile_write() returns 0 on error.
1766                  */
1767                 if (nwritten == 0) {
1768                         *err = gzwfile_geterr((GZWFILE_T)wdh->fh);
1769                         return FALSE;
1770                 }
1771         } else
1772 #endif
1773         {
1774                 nwritten = fwrite(buf, 1, bufsize, (FILE *)wdh->fh);
1775                 /*
1776                  * At least according to the Mac OS X man page,
1777                  * this can return a short count on an error.
1778                  */
1779                 if (nwritten != bufsize) {
1780                         if (ferror((FILE *)wdh->fh))
1781                                 *err = errno;
1782                         else
1783                                 *err = WTAP_ERR_SHORT_WRITE;
1784                         return FALSE;
1785                 }
1786         }
1787         return TRUE;
1788 }
1789
1790 /* internally close a file for writing (compressed or not) */
1791 static int wtap_dump_file_close(wtap_dumper *wdh)
1792 {
1793 #ifdef HAVE_LIBZ
1794         if(wdh->compressed) {
1795                 return gzwfile_close((GZWFILE_T)wdh->fh);
1796         } else
1797 #endif
1798         {
1799                 return fclose((FILE *)wdh->fh);
1800         }
1801 }
1802
1803 gint64 wtap_dump_file_seek(wtap_dumper *wdh, gint64 offset, int whence, int *err)
1804 {
1805 #ifdef HAVE_LIBZ
1806         if(wdh->compressed) {
1807                 *err = WTAP_ERR_CANT_SEEK_COMPRESSED;
1808                 return -1;
1809         } else
1810 #endif
1811         {
1812                 if (-1 == fseek((FILE *)wdh->fh, (long)offset, whence)) {
1813                         *err = errno;
1814                         return -1;
1815                 } else
1816                 {
1817                         return 0;
1818                 }       
1819         }
1820 }
1821 gint64 wtap_dump_file_tell(wtap_dumper *wdh, int *err)
1822 {
1823         gint64 rval;
1824 #ifdef HAVE_LIBZ
1825         if(wdh->compressed) {
1826                 *err = WTAP_ERR_CANT_SEEK_COMPRESSED;
1827                 return -1;
1828         } else
1829 #endif
1830         {
1831                 if (-1 == (rval = ftell((FILE *)wdh->fh))) {
1832                         *err = errno;
1833                         return -1;
1834                 } else
1835                 {
1836                         return rval;
1837                 }       
1838         }
1839 }