4f79e60328e2039727d8afb227508266b82ef88a
[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 int wtap_get_num_file_type_extensions(void)
181 {
182         return file_type_extensions_arr->len;
183 }
184
185 const char *wtap_get_file_extension_type_name(int extension_type)
186 {
187         return file_type_extensions[extension_type].name;
188 }
189
190 static GSList *add_extensions_for_file_extensions_type(int extension_type,
191     GSList *extensions, GSList *compressed_file_extensions)
192 {
193         gchar **extensions_set, **extensionp, *extension;
194
195         /*
196          * Split the extension-list string into a set of extensions.
197          */
198         extensions_set = g_strsplit(file_type_extensions[extension_type].extensions,
199             ";", 0);
200
201         /*
202          * Add each of those extensions to the list.
203          */
204         for (extensionp = extensions_set; *extensionp != NULL; extensionp++) {
205                 extension = *extensionp;
206
207                 /*
208                  * Add the extension, and all compressed variants
209                  * of it.
210                  */
211                 extensions = add_extensions(extensions, extension,
212                     compressed_file_extensions);
213         }
214
215         g_strfreev(extensions_set);
216         return extensions;
217 }
218
219 /* Return a list of file extensions that are used by the specified file
220    extension type.
221
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)
225 {
226         GSList *compressed_file_extensions;
227         GSList *extensions;
228
229         if (extension_type >= file_type_extensions_arr->len)
230                 return NULL;    /* not a valid extension type */
231
232         extensions = NULL;      /* empty list, to start with */
233
234         /*
235          * Get the list of compressed-file extensions.
236          */
237         compressed_file_extensions = wtap_get_compressed_file_extensions();
238
239         /*
240          * Add all this file extension type's extensions, with compressed
241          * variants.
242          */
243         extensions = add_extensions_for_file_extensions_type(extension_type,
244             extensions, compressed_file_extensions);
245
246         g_slist_free(compressed_file_extensions);
247         return extensions;
248 }
249
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.
253
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)
257 {
258         GSList *compressed_file_extensions;
259         GSList *extensions;
260         unsigned int i;
261
262         init_file_type_extensions();
263
264         extensions = NULL;      /* empty list, to start with */
265
266         /*
267          * Get the list of compressed-file extensions.
268          */
269         compressed_file_extensions = wtap_get_compressed_file_extensions();
270
271         for (i = 0; i < file_type_extensions_arr->len; i++) {
272                 /*
273                  * Add all this file extension type's extensions, with
274                  * compressed variants.
275                  */
276                 extensions = add_extensions_for_file_extensions_type(i,
277                     extensions, compressed_file_extensions);
278         }
279
280         g_slist_free(compressed_file_extensions);
281         return extensions;
282 }
283
284 /* The open_file_* routines should return:
285  *
286  *      -1 on an I/O error;
287  *
288  *      1 if the file they're reading is one of the types it handles;
289  *
290  *      0 if the file they're reading isn't the type they're checking for.
291  *
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.
294  *
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)
298  *
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.
302  *
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.
307  */
308
309
310 static wtap_open_routine_t open_routines_base[] = {
311         /* Files that have magic bytes in fixed locations. These
312          * are easy to identify.
313          */
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.
348          */
349
350         /* I put NetScreen *before* erf, because there were some
351          * false positives with my test-files (Sake Blok, July 2007)
352          *
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)
356          */
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
376 };
377
378 #define N_FILE_TYPES    (sizeof open_routines_base / sizeof open_routines_base[0])
379
380 static wtap_open_routine_t* open_routines = NULL;
381
382 static GArray* open_routines_arr = NULL;
383
384
385 /* initialize the open routines array if it has not been initialized yet */
386 static void init_open_routines(void) {
387
388         if (open_routines_arr) return;
389
390         open_routines_arr = g_array_new(FALSE,TRUE,sizeof(wtap_open_routine_t));
391
392         g_array_append_vals(open_routines_arr,open_routines_base,N_FILE_TYPES);
393
394         open_routines = (wtap_open_routine_t*)(void *)open_routines_arr->data;
395 }
396
397 void wtap_register_open_routine(wtap_open_routine_t open_routine, gboolean has_magic) {
398         init_open_routines();
399
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);
404
405         open_routines = (wtap_open_routine_t*)(void *)open_routines_arr->data;
406 }
407
408 /*
409  * Visual C++ on Win32 systems doesn't define these.  (Old UNIX systems don't
410  * define them either.)
411  *
412  * Visual C++ on Win32 systems doesn't define S_IFIFO, it defines _S_IFIFO.
413  */
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
426
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)
436 {
437         int     fd;
438         ws_statb64 statb;
439         wtap    *wth;
440         unsigned int    i;
441         gboolean use_stdin = FALSE;
442
443         /* open standard input if filename is '-' */
444         if (strcmp(filename, "-") == 0)
445                 use_stdin = TRUE;
446
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;
452                 }
453         } else {
454                 if (ws_stat64(filename, &statb) < 0) {
455                         *err = errno;
456                         return NULL;
457                 }
458         }
459         if (S_ISFIFO(statb.st_mode)) {
460                 /*
461                  * Opens of FIFOs are allowed only when not opening
462                  * for random access.
463                  *
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.
471                  */
472                 if (do_random) {
473                         *err = WTAP_ERR_RANDOM_OPEN_PIPE;
474                         return NULL;
475                 }
476         } else if (S_ISDIR(statb.st_mode)) {
477                 /*
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.
481                  */
482                 *err = EISDIR;
483                 return NULL;
484         } else if (! S_ISREG(statb.st_mode)) {
485                 *err = WTAP_ERR_NOT_REGULAR_FILE;
486                 return NULL;
487         }
488
489         /*
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.
495          */
496         if (use_stdin && do_random) {
497                 *err = WTAP_ERR_RANDOM_OPEN_STDIN;
498                 return NULL;
499         }
500
501         errno = ENOMEM;
502         wth = (wtap *)g_malloc0(sizeof(wtap));
503
504         /* Open the file */
505         errno = WTAP_ERR_CANT_OPEN;
506         if (use_stdin) {
507                 /*
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.
511                  */
512                 fd = ws_dup(0);
513                 if (fd < 0) {
514                         *err = errno;
515                         g_free(wth);
516                         return NULL;
517                 }
518 #ifdef _WIN32
519                 if (_setmode(fd, O_BINARY) == -1) {
520                         /* "Shouldn't happen" */
521                         *err = errno;
522                         g_free(wth);
523                         return NULL;
524                 }
525 #endif
526                 if (!(wth->fh = file_fdopen(fd))) {
527                         *err = errno;
528                         ws_close(fd);
529                         g_free(wth);
530                         return NULL;
531                 }
532         } else {
533                 if (!(wth->fh = file_open(filename))) {
534                         *err = errno;
535                         g_free(wth);
536                         return NULL;
537                 }
538         }
539
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;
546                 }
547         } else
548                 wth->random_fh = NULL;
549
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;
556
557         init_open_routines();
558         if (wth->random_fh) {
559                 wth->fast_seek = g_ptr_array_new();
560
561                 file_set_random_access(wth->fh, FALSE, wth->fast_seek);
562                 file_set_random_access(wth->random_fh, TRUE, wth->fast_seek);
563         }
564
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.
572
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;
578                 }
579
580                 switch ((*open_routines[i])(wth, err, err_info)) {
581
582                 case -1:
583                         /* I/O error - give up */
584                         wtap_close(wth);
585                         return NULL;
586
587                 case 0:
588                         /* No I/O error, but not that type of file */
589                         break;
590
591                 case 1:
592                         /* We found the file type */
593                         goto success;
594                 }
595         }
596
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;
601
602 success:
603         wth->frame_buffer = (struct Buffer *)g_malloc(sizeof(struct Buffer));
604         buffer_init(wth->frame_buffer, 1500);
605
606         if(wth->file_type == WTAP_FILE_PCAP){
607
608                 wtapng_if_descr_t descr;
609
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);
629
630         }
631         return wth;
632 }
633
634 /*
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.
640  *
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.
645  */
646 gboolean
647 wtap_fdreopen(wtap *wth, const char *filename, int *err)
648 {
649         ws_statb64 statb;
650
651         /*
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.
657          */
658         if (strcmp(filename, "-") == 0) {
659                 *err = WTAP_ERR_RANDOM_OPEN_STDIN;
660                 return FALSE;
661         }
662
663         /* First, make sure the file is valid */
664         if (ws_stat64(filename, &statb) < 0) {
665                 *err = errno;
666                 return FALSE;
667         }
668         if (S_ISFIFO(statb.st_mode)) {
669                 /*
670                  * Opens of FIFOs are not allowed; see above.
671                  */
672                 *err = WTAP_ERR_RANDOM_OPEN_PIPE;
673                 return FALSE;
674         } else if (S_ISDIR(statb.st_mode)) {
675                 /*
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.
679                  */
680                 *err = EISDIR;
681                 return FALSE;
682         } else if (! S_ISREG(statb.st_mode)) {
683                 *err = WTAP_ERR_NOT_REGULAR_FILE;
684                 return FALSE;
685         }
686
687         /* Open the file */
688         errno = WTAP_ERR_CANT_OPEN;
689         if (!file_fdreopen(wth->random_fh, filename)) {
690                 *err = errno;
691                 return FALSE;
692         }
693         return TRUE;
694 }
695
696 /* Table of the file types we know about.
697    Entries must be sorted by WTAP_FILE_xxx values in ascending order */
698 static const struct file_type_info dump_open_table_base[] = {
699         /* WTAP_FILE_UNKNOWN (only used internally for initialization) */
700         { NULL, NULL, NULL, NULL,
701           FALSE, FALSE, 0,
702           NULL, NULL },
703
704         /* WTAP_FILE_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 },
709
710         /* WTAP_FILE_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 },
714
715         /* WTAP_FILE_PCAP_NSEC */
716         { "Wireshark - nanosecond libpcap", "nseclibpcap", "pcap", "cap;dmp",
717           FALSE, FALSE, 0,
718           libpcap_dump_can_write_encap, libpcap_dump_open },
719
720         /* WTAP_FILE_PCAP_AIX */
721         { "AIX tcpdump - libpcap", "aixlibpcap", "pcap", "cap;dmp",
722           FALSE, FALSE, 0,
723           NULL, NULL },
724
725         /* WTAP_FILE_PCAP_SS991029 */
726         { "Modified tcpdump - libpcap", "modlibpcap", "pcap", "cap;dmp",
727           FALSE, FALSE, 0,
728           libpcap_dump_can_write_encap, libpcap_dump_open },
729
730         /* WTAP_FILE_PCAP_NOKIA */
731         { "Nokia tcpdump - libpcap ", "nokialibpcap", "pcap", "cap;dmp",
732           FALSE, FALSE, 0,
733           libpcap_dump_can_write_encap, libpcap_dump_open },
734
735         /* WTAP_FILE_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 },
739
740         /* WTAP_FILE_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 },
744
745         /* WTAP_FILE_5VIEWS */
746         { "InfoVista 5View capture", "5views", "5vw", NULL,
747            TRUE, FALSE, 0,
748           _5views_dump_can_write_encap, _5views_dump_open },
749
750         /* WTAP_FILE_IPTRACE_1_0 */
751         { "AIX iptrace 1.0", "iptrace_1", NULL, NULL,
752           FALSE, FALSE, 0,
753           NULL, NULL },
754
755         /* WTAP_FILE_IPTRACE_2_0 */
756         { "AIX iptrace 2.0", "iptrace_2", NULL, NULL,
757           FALSE, FALSE, 0,
758           NULL, NULL },
759
760         /* WTAP_FILE_BER */
761         { "ASN.1 Basic Encoding Rules", "ber", NULL, NULL,
762           FALSE, FALSE, 0,
763           NULL, NULL },
764
765         /* WTAP_FILE_HCIDUMP */
766         { "Bluetooth HCI dump", "hcidump", NULL, NULL,
767           FALSE, FALSE, 0,
768           NULL, NULL },
769
770         /* WTAP_FILE_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 },
774
775         /* WTAP_FILE_NETXRAY_OLD */
776         { "Cinco Networks NetXRay 1.x", "netxray1", "cap", NULL,
777           TRUE, FALSE, 0,
778           NULL, NULL },
779
780         /* WTAP_FILE_NETXRAY_1_0 */
781         { "Cinco Networks NetXRay 2.0 or later", "netxray2", "cap", NULL,
782           TRUE, FALSE, 0,
783           NULL, NULL },
784
785         /* WTAP_FILE_COSINE */
786         { "CoSine IPSX L2 capture", "cosine", "txt", NULL,
787           FALSE, FALSE, 0,
788           NULL, NULL },
789
790         /* WTAP_FILE_CSIDS */
791         { "CSIDS IPLog", "csids", NULL, NULL,
792           FALSE, FALSE, 0,
793           NULL, NULL },
794
795         /* WTAP_FILE_DBS_ETHERWATCH */
796         { "DBS Etherwatch (VMS)", "etherwatch", "txt", NULL,
797           FALSE, FALSE, 0,
798           NULL, NULL},
799
800         /* WTAP_FILE_ERF */
801         { "Endace ERF capture", "erf", "erf", NULL,
802           FALSE, FALSE, 0,
803           erf_dump_can_write_encap, erf_dump_open },
804
805         /* WTAP_FILE_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 },
809
810         /* WTAP_FILE_NETTL */
811         { "HP-UX nettl trace", "nettl", "trc0", "trc1",
812           FALSE, FALSE, 0,
813           nettl_dump_can_write_encap, nettl_dump_open },
814
815         /* WTAP_FILE_ISERIES */
816         { "IBM iSeries comm. trace (ASCII)", "iseries_ascii", "txt", NULL,
817           FALSE, FALSE, 0,
818           NULL, NULL },
819
820         /* WTAP_FILE_ISERIES_UNICODE */
821         { "IBM iSeries comm. trace (UNICODE)", "iseries_unicode", "txt", NULL,
822           FALSE, FALSE, 0,
823           NULL, NULL },
824
825         /* WTAP_FILE_I4BTRACE */
826         { "I4B ISDN trace", "i4btrace", NULL, NULL,
827           FALSE, FALSE, 0,
828           NULL, NULL },
829
830         /* WTAP_FILE_ASCEND */
831         { "Lucent/Ascend access server trace", "ascend", "txt", NULL,
832           FALSE, FALSE, 0,
833           NULL, NULL },
834
835         /* WTAP_FILE_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 },
839
840         /* WTAP_FILE_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 },
844
845         /* WTAP_FILE_NGSNIFFER_UNCOMPRESSED */
846         { "Sniffer (DOS)", "ngsniffer", "cap", "enc;trc;fdc;syc",
847           FALSE, FALSE, 0,
848           ngsniffer_dump_can_write_encap, ngsniffer_dump_open },
849
850         /* WTAP_FILE_NGSNIFFER_COMPRESSED */
851         { "Sniffer (DOS), compressed", "ngsniffer_comp", "cap", "enc;trc;fdc;syc",
852           FALSE, FALSE, 0,
853           NULL, NULL },
854
855         /* WTAP_FILE_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 },
859
860         /* WTAP_FILE_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 },
864
865         /* WTAP_FILE_NETWORK_INSTRUMENTS */
866         { "Network Instruments Observer", "niobserver", "bfr", NULL,
867           FALSE, FALSE, 0,
868           network_instruments_dump_can_write_encap, network_instruments_dump_open },
869
870         /* WTAP_FILE_LANALYZER */
871         { "Novell LANalyzer","lanalyzer", "tr1", NULL,
872           TRUE, FALSE, 0,
873           lanalyzer_dump_can_write_encap, lanalyzer_dump_open },
874
875         /* WTAP_FILE_PPPDUMP */
876         { "pppd log (pppdump format)", "pppd", NULL, NULL,
877           FALSE, FALSE, 0,
878           NULL, NULL },
879
880         /* WTAP_FILE_RADCOM */
881         { "RADCOM WAN/LAN analyzer", "radcom", NULL, NULL,
882           FALSE, FALSE, 0,
883           NULL, NULL },
884
885         /* WTAP_FILE_SNOOP */
886         { "Sun snoop", "snoop", "snoop", "cap",
887           FALSE, FALSE, 0,
888           snoop_dump_can_write_encap, snoop_dump_open },
889
890         /* WTAP_FILE_SHOMITI */
891         { "Shomiti/Finisar Surveyor", "shomiti", "cap", NULL,
892           FALSE, FALSE, 0,
893           NULL, NULL },
894
895         /* WTAP_FILE_VMS */
896         { "TCPIPtrace (VMS)", "tcpiptrace", "txt", NULL,
897           FALSE, FALSE, 0,
898           NULL, NULL},
899
900         /* WTAP_FILE_K12 */
901         { "Tektronix K12xx 32-bit .rf5 format", "rf5", "rf5", NULL,
902            TRUE, FALSE, 0,
903            k12_dump_can_write_encap, k12_dump_open },
904
905         /* WTAP_FILE_TOSHIBA */
906         { "Toshiba Compact ISDN Router snoop", "toshiba", "txt", NULL,
907           FALSE, FALSE, 0,
908           NULL, NULL },
909
910         /* WTAP_FILE_VISUAL_NETWORKS */
911         { "Visual Networks traffic capture", "visual", NULL, NULL,
912           TRUE, FALSE, 0,
913           visual_dump_can_write_encap, visual_dump_open },
914
915         /* WTAP_FILE_PEEKCLASSIC_V56 */
916         { "WildPackets classic (V5 and V6)", "peekclassic56", "pkt", "tpc;apc;wpz",
917           FALSE, FALSE, 0,
918           NULL, NULL },
919
920         /* WTAP_FILE_PEEKCLASSIC_V7 */
921         { "WildPackets classic (V7)", "peekclassic7", "pkt", "tpc;apc;wpz",
922           FALSE, FALSE, 0,
923           NULL, NULL },
924
925         /* WTAP_FILE_PEEKTAGGED */
926         { "WildPackets tagged", "peektagged", "pkt", "tpc;apc;wpz",
927           FALSE, FALSE, 0,
928           NULL, NULL },
929
930         /* WTAP_FILE_MPEG */
931         { "MPEG", "mpeg", "mpeg", "mpg;mp3",
932           FALSE, FALSE, 0,
933           NULL, NULL },
934
935         /* WTAP_FILE_K12TEXT  */
936         { "K12 text file", "k12text", "txt", NULL,
937           FALSE, FALSE, 0,
938           k12text_dump_can_write_encap, k12text_dump_open },
939
940         /* WTAP_FILE_NETSCREEN */
941         { "NetScreen snoop text file", "netscreen", "txt", NULL,
942           FALSE, FALSE, 0,
943           NULL, NULL },
944
945         /* WTAP_FILE_COMMVIEW */
946         { "TamoSoft CommView", "commview", "ncf", NULL,
947           FALSE, FALSE, 0,
948           commview_dump_can_write_encap, commview_dump_open },
949
950         /* WTAP_FILE_BTSNOOP */
951         { "Symbian OS btsnoop", "btsnoop", "log", NULL,
952           FALSE, FALSE, 0,
953           btsnoop_dump_can_write_encap, btsnoop_dump_open_h4 },
954
955         /* WTAP_FILE_TNEF */
956         { "Transport-Neutral Encapsulation Format", "tnef", NULL, NULL,
957           FALSE, FALSE, 0,
958           NULL, NULL },
959
960         /* WTAP_FILE_DCT3TRACE */
961         { "Gammu DCT3 trace", "dct3trace", "xml", NULL,
962           FALSE, FALSE, 0,
963           NULL, NULL },
964
965         /* WTAP_FILE_PACKETLOGGER */
966         { "PacketLogger", "pklg", "pklg", NULL,
967           FALSE, FALSE, 0,
968           NULL, NULL },
969
970         /* WTAP_FILE_DAINTREE_SNA */
971         { "Daintree SNA", "dsna", "dcf", NULL,
972           FALSE, FALSE, 0,
973           NULL, NULL },
974
975         /* WTAP_FILE_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 },
979
980         /* WTAP_FILE_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 },
984
985         /* WTAP_FILE_JPEG_JFIF */
986         { "JPEG/JFIF", "jpeg", "jpg", "jpeg;jfif",
987           FALSE, FALSE, 0,
988           NULL, NULL },
989
990         /* WTAP_FILE_IPFIX */
991         { "IPFIX File Format", "ipfix", "pfx", "ipfix",
992           FALSE, FALSE, 0,
993           NULL, NULL },
994
995         /* WTAP_ENCAP_MIME */
996         { "MIME File Format", "mime", NULL, NULL,
997            FALSE, FALSE, 0,
998            NULL, NULL },
999
1000         /* WTAP_FILE_AETHRA */
1001         { "Aethra .aps file", "aethra", "aps", NULL,
1002           FALSE, FALSE, 0,
1003           NULL, NULL },
1004
1005         /* WTAP_FILE_MPEG_2_TS */
1006         { "MPEG2 transport stream", "mp2t", "mp2t", "ts;mpg",
1007           FALSE, FALSE, 0,
1008           NULL, NULL },
1009
1010         /* WTAP_FILE_VWR_80211 */
1011         { "Ixia IxVeriWave .vwr Raw 802.11 Capture", "vwr80211", "vwr", NULL,
1012           FALSE, FALSE, 0,
1013           NULL, NULL },
1014
1015         /* WTAP_FILE_VWR_ETH */
1016         { "Ixia IxVeriWave .vwr Raw Ethernet Capture", "vwreth", "vwr", NULL,
1017           FALSE, FALSE, 0,
1018           NULL, NULL },
1019
1020         /* WTAP_FILE_CAMINS */
1021         { "CAM Inspector file", "camins", "camins", NULL,
1022           FALSE, FALSE, 0,
1023           NULL, NULL },
1024
1025         /* WTAP_FILE_STANAG_4607 */
1026         { "STANAG 4607 Format", "stanag4607", NULL, NULL,
1027           FALSE, FALSE, 0,
1028           NULL, NULL }
1029
1030 };
1031
1032 gint wtap_num_file_types = sizeof(dump_open_table_base) / sizeof(struct file_type_info);
1033
1034 static GArray*  dump_open_table_arr = NULL;
1035 static const struct file_type_info* dump_open_table = dump_open_table_base;
1036
1037 /* initialize the file types array if it has not being initialized yet */
1038 static void init_file_types(void) {
1039
1040         if (dump_open_table_arr) return;
1041
1042         dump_open_table_arr = g_array_new(FALSE,TRUE,sizeof(struct file_type_info));
1043
1044         g_array_append_vals(dump_open_table_arr,dump_open_table_base,wtap_num_file_types);
1045
1046         dump_open_table = (const struct file_type_info*)(void *)dump_open_table_arr->data;
1047 }
1048
1049 int wtap_register_file_type(const struct file_type_info* fi) {
1050         init_file_types();
1051
1052         g_array_append_val(dump_open_table_arr,*fi);
1053
1054         dump_open_table = (const struct file_type_info*)(void *)dump_open_table_arr->data;
1055
1056         return wtap_num_file_types++;
1057 }
1058
1059 int wtap_get_num_file_types(void)
1060 {
1061         return wtap_num_file_types;
1062 }
1063
1064 /*
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.
1069  */
1070 int
1071 wtap_dump_file_encap_type(const GArray *file_encaps)
1072 {
1073         int encap;
1074
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);
1079         }
1080         return encap;
1081 }
1082
1083 static gboolean
1084 wtap_dump_can_write_encap(int filetype, int encap)
1085 {
1086         if (filetype < 0 || filetype >= wtap_num_file_types
1087             || dump_open_table[filetype].can_write_encap == NULL)
1088                 return FALSE;
1089
1090         if ((*dump_open_table[filetype].can_write_encap)(encap) != 0)
1091                 return FALSE;
1092
1093         return TRUE;
1094 }
1095
1096 /*
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.
1100  */
1101 static gboolean
1102 wtap_dump_can_write_format(int ft, const GArray *file_encaps,
1103     guint32 required_comment_types)
1104 {
1105         guint i;
1106
1107         /*
1108          * Can we write in this format?
1109          */
1110         if (!wtap_dump_can_open(ft)) {
1111                 /* No. */
1112                 return FALSE;
1113         }
1114
1115         /*
1116          * Yes.  Can we write out all the required comments in this
1117          * format?
1118          */
1119         if (!wtap_dump_supports_comment_types(ft, required_comment_types)) {
1120                 /* No. */
1121                 return FALSE;
1122         }
1123
1124         /*
1125          * Yes.  Is the required per-file encapsulation type supported?
1126          * This might be WTAP_ENCAP_PER_PACKET.
1127          */
1128         if (!wtap_dump_can_write_encap(ft, wtap_dump_file_encap_type(file_encaps))) {
1129                 /* No. */
1130                 return FALSE;
1131         }
1132
1133         /*
1134          * Yes.  Are all the individual encapsulation types supported?
1135          */
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;
1141                 }
1142         }
1143
1144         /* Yes - we're OK. */
1145         return TRUE;
1146 }
1147
1148 /**
1149  * Return TRUE if we can write a file with the given GArray of
1150  * encapsulation types and the given bitmask of comment types.
1151  */
1152 gboolean
1153 wtap_dump_can_write(const GArray *file_encaps, guint32 required_comment_types)
1154 {
1155   int ft;
1156
1157   for (ft = 0; ft < WTAP_NUM_FILE_TYPES; 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;
1164     }
1165   }
1166
1167   /* No, we couldn't save it in any format. */
1168   return FALSE;
1169 }
1170
1171 /**
1172  * Get a GArray of WTAP_FILE_ values for file types that can be used
1173  * to save a file of a given type with a given GArray of encapsulation
1174  * types and the given bitmask of comment types.
1175  */
1176 GArray *
1177 wtap_get_savable_file_types(int file_type, const GArray *file_encaps,
1178     guint32 required_comment_types)
1179 {
1180         GArray *savable_file_types;
1181         int ft;
1182         int default_file_type = -1;
1183         int other_file_type = -1;
1184
1185         /* Can we save this file in its own file type? */
1186         if (wtap_dump_can_write_format(file_type, file_encaps,
1187                                        required_comment_types)) {
1188                 /* Yes - make that the default file type. */
1189                 default_file_type = file_type;
1190         } else {
1191                 /* OK, find the first file type we *can* save it as. */
1192                 default_file_type = -1;
1193                 for (ft = 0; ft < WTAP_NUM_FILE_TYPES; ft++) {
1194                         if (wtap_dump_can_write_format(ft, file_encaps,
1195                                                        required_comment_types)) {
1196                                 /* OK, got it. */
1197                                 default_file_type = ft;
1198                         }
1199                 }
1200         }
1201
1202         if (default_file_type == -1) {
1203                 /* We don't support writing this file as any file type. */
1204                 return NULL;
1205         }
1206
1207         /* Allocate the array. */
1208         savable_file_types = g_array_new(FALSE, FALSE, (guint)sizeof (int));
1209
1210         /* Put the default file format first in the list. */
1211         g_array_append_val(savable_file_types, default_file_type);
1212
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 == WTAP_FILE_PCAP) {
1218                 if (wtap_dump_can_write_format(WTAP_FILE_PCAPNG, file_encaps,
1219                                                required_comment_types))
1220                         other_file_type = WTAP_FILE_PCAPNG;
1221         } else if (default_file_type == WTAP_FILE_PCAPNG) {
1222                 if (wtap_dump_can_write_format(WTAP_FILE_PCAP, file_encaps,
1223                                                required_comment_types))
1224                         other_file_type = WTAP_FILE_PCAP;
1225         }
1226         if (other_file_type != -1)
1227                 g_array_append_val(savable_file_types, other_file_type);
1228
1229         /* Add all the other file types that work. */
1230         for (ft = 0; ft < WTAP_NUM_FILE_TYPES; ft++) {
1231                 if (ft == WTAP_FILE_UNKNOWN)
1232                         continue;       /* not a real file type */
1233                 if (ft == default_file_type || ft == other_file_type)
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, ft);
1239                 }
1240         }
1241
1242         return savable_file_types;
1243 }
1244
1245 /* Name that should be somewhat descriptive. */
1246 const char *wtap_file_type_string(int filetype)
1247 {
1248         if (filetype < 0 || filetype >= wtap_num_file_types) {
1249                 g_error("Unknown capture file type %d", filetype);
1250                 /** g_error() does an abort() and thus never returns **/
1251                 return "";
1252         } else
1253                 return dump_open_table[filetype].name;
1254 }
1255
1256 /* Name to use in, say, a command-line flag specifying the type. */
1257 const char *wtap_file_type_short_string(int filetype)
1258 {
1259         if (filetype < 0 || filetype >= wtap_num_file_types)
1260                 return NULL;
1261         else
1262                 return dump_open_table[filetype].short_name;
1263 }
1264
1265 /* Translate a short name to a capture file type. */
1266 int wtap_short_string_to_file_type(const char *short_name)
1267 {
1268         int filetype;
1269
1270         for (filetype = 0; filetype < wtap_num_file_types; filetype++) {
1271                 if (dump_open_table[filetype].short_name != NULL &&
1272                     strcmp(short_name, dump_open_table[filetype].short_name) == 0)
1273                         return filetype;
1274         }
1275
1276         /*
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.
1280          */
1281         if (strcmp(short_name, "libpcap") == 0)
1282                 return WTAP_FILE_PCAP;
1283
1284         return -1;      /* no such file type, or we can't write it */
1285 }
1286
1287 static GSList *
1288 add_extensions_for_filetype(int filetype, GSList *extensions,
1289     GSList *compressed_file_extensions)
1290 {
1291         gchar **extensions_set, **extensionp;
1292         gchar *extension;
1293
1294         /*
1295          * Add the default extension, and all compressed variants of
1296          * it.
1297          */
1298         extensions = add_extensions(extensions,
1299             dump_open_table[filetype].default_file_extension,
1300             compressed_file_extensions);
1301
1302         if (dump_open_table[filetype].additional_file_extensions != NULL) {
1303                 /*
1304                  * We have additional extensions; add them.
1305                  *
1306                  * First, split the extension-list string into a set of
1307                  * extensions.
1308                  */
1309                 extensions_set = g_strsplit(dump_open_table[filetype].additional_file_extensions,
1310                     ";", 0);
1311
1312                 /*
1313                  * Add each of those extensions to the list.
1314                  */
1315                 for (extensionp = extensions_set; *extensionp != NULL;
1316                     extensionp++) {
1317                         extension = *extensionp;
1318
1319                         /*
1320                          * Add the extension, and all compressed variants
1321                          * of it.
1322                          */
1323                         extensions = add_extensions(extensions, extension,
1324                             compressed_file_extensions);
1325                 }
1326
1327                 g_strfreev(extensions_set);
1328         }
1329         return extensions;
1330 }
1331
1332 /* Return a list of file extensions that are used by the specified file type.
1333
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.
1337
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 filetype, gboolean include_compressed)
1341 {
1342         GSList *compressed_file_extensions;
1343         GSList *extensions;
1344
1345         if (filetype < 0 || filetype >= wtap_num_file_types)
1346                 return NULL;    /* not a valid file type */
1347
1348         if (dump_open_table[filetype].default_file_extension == NULL)
1349                 return NULL;    /* valid, but no extensions known */
1350
1351         extensions = NULL;      /* empty list, to start with */
1352
1353         /*
1354          * If include_compressions is true, get the list of compressed-file
1355          * extensions.
1356          */
1357         if (include_compressed)
1358                 compressed_file_extensions = wtap_get_compressed_file_extensions();
1359         else
1360                 compressed_file_extensions = NULL;
1361
1362         /*
1363          * Add all this file type's extensions, with compressed
1364          * variants.
1365          */
1366         extensions = add_extensions_for_filetype(filetype, extensions,
1367             compressed_file_extensions);
1368
1369         g_slist_free(compressed_file_extensions);
1370         return extensions;
1371 }
1372
1373 /*
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().
1376  */
1377 void wtap_free_extensions_list(GSList *extensions)
1378 {
1379         GSList *extension;
1380
1381         for (extension = extensions; extension != NULL;
1382             extension = g_slist_next(extension)) {
1383                 g_free(extension->data);
1384         }
1385         g_slist_free(extensions);
1386 }
1387
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 filetype)
1391 {
1392         if (filetype < 0 || filetype >= wtap_num_file_types)
1393                 return NULL;
1394         else
1395                 return dump_open_table[filetype].default_file_extension;
1396 }
1397
1398 gboolean wtap_dump_can_open(int filetype)
1399 {
1400         if (filetype < 0 || filetype >= wtap_num_file_types
1401             || dump_open_table[filetype].dump_open == NULL)
1402                 return FALSE;
1403
1404         return TRUE;
1405 }
1406
1407 #ifdef HAVE_LIBZ
1408 gboolean wtap_dump_can_compress(int filetype)
1409 {
1410         /*
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.
1414          */
1415         if (filetype < 0 || filetype >= wtap_num_file_types
1416             || dump_open_table[filetype].writing_must_seek)
1417                 return FALSE;
1418
1419         return TRUE;
1420 }
1421 #else
1422 gboolean wtap_dump_can_compress(int filetype _U_)
1423 {
1424         return FALSE;
1425 }
1426 #endif
1427
1428 gboolean wtap_dump_has_name_resolution(int filetype)
1429 {
1430         if (filetype < 0 || filetype >= wtap_num_file_types
1431             || dump_open_table[filetype].has_name_resolution == FALSE)
1432                 return FALSE;
1433
1434         return TRUE;
1435 }
1436
1437 gboolean wtap_dump_supports_comment_types(int filetype, guint32 comment_types)
1438 {
1439         guint32 supported_comment_types;
1440
1441         if (filetype < 0 || filetype >= wtap_num_file_types)
1442                 return FALSE;
1443
1444         supported_comment_types = dump_open_table[filetype].supported_comment_types;
1445
1446         if ((comment_types & supported_comment_types) == comment_types)
1447                 return TRUE;
1448         return FALSE;
1449 }
1450
1451 static gboolean wtap_dump_open_check(int filetype, int encap, gboolean comressed, int *err);
1452 static wtap_dumper* wtap_dump_alloc_wdh(int filetype, int encap, int snaplen,
1453                                         gboolean compressed, int *err);
1454 static gboolean wtap_dump_open_finish(wtap_dumper *wdh, int filetype, gboolean compressed, int *err);
1455
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);
1459
1460 wtap_dumper* wtap_dump_open(const char *filename, int filetype, int encap,
1461                                 int snaplen, gboolean compressed, int *err)
1462 {
1463         return wtap_dump_open_ng(filename, filetype, encap,snaplen, compressed, NULL, NULL, err);
1464 }
1465
1466 static wtap_dumper *
1467 wtap_dump_init_dumper(int filetype, int encap, int snaplen, gboolean compressed,
1468     wtapng_section_t *shb_hdr, wtapng_iface_descriptions_t *idb_inf, int *err)
1469 {
1470         wtap_dumper *wdh;
1471
1472         /* Allocate a data structure for the output stream. */
1473         wdh = wtap_dump_alloc_wdh(filetype, encap, snaplen, compressed, err);
1474         if (wdh == NULL)
1475                 return NULL;    /* couldn't allocate it */
1476
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;
1485
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);
1505         }
1506         return wdh;
1507 }
1508
1509 wtap_dumper* wtap_dump_open_ng(const char *filename, int filetype, int encap,
1510                                 int snaplen, gboolean compressed, wtapng_section_t *shb_hdr, wtapng_iface_descriptions_t *idb_inf, int *err)
1511 {
1512         wtap_dumper *wdh;
1513         WFILE_T fh;
1514
1515         /* Check whether we can open a capture file with that file type
1516            and that encapsulation. */
1517         if (!wtap_dump_open_check(filetype, encap, compressed, err))
1518                 return NULL;
1519
1520         /* Allocate and initialize a data structure for the output stream. */
1521         wdh = wtap_dump_init_dumper(filetype, encap, snaplen, compressed,
1522             shb_hdr, idb_inf, err);
1523         if (wdh == NULL)
1524                 return NULL;
1525
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 */
1532                 }
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 */
1539                 }
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 */
1551                 }
1552                 wdh->fh = fh;
1553         }
1554
1555         if (!wtap_dump_open_finish(wdh, filetype, 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);
1561                 }
1562                 g_free(wdh);
1563                 return NULL;
1564         }
1565         return wdh;
1566 }
1567
1568 wtap_dumper* wtap_dump_fdopen(int fd, int filetype, int encap, int snaplen,
1569                                 gboolean compressed, int *err)
1570 {
1571         return wtap_dump_fdopen_ng(fd, filetype, encap, snaplen, compressed, NULL, NULL, err);
1572 }
1573
1574 wtap_dumper* wtap_dump_fdopen_ng(int fd, int filetype, int encap, int snaplen,
1575                                 gboolean compressed, wtapng_section_t *shb_hdr, wtapng_iface_descriptions_t *idb_inf, int *err)
1576 {
1577         wtap_dumper *wdh;
1578         WFILE_T fh;
1579
1580         /* Check whether we can open a capture file with that file type
1581            and that encapsulation. */
1582         if (!wtap_dump_open_check(filetype, encap, compressed, err))
1583                 return NULL;
1584
1585         /* Allocate and initialize a data structure for the output stream. */
1586         wdh = wtap_dump_init_dumper(filetype, encap, snaplen, compressed,
1587             shb_hdr, idb_inf, err);
1588         if (wdh == NULL)
1589                 return NULL;
1590
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 */
1598                 }
1599         }
1600 #endif
1601
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 */
1610         }
1611         wdh->fh = fh;
1612
1613         if (!wtap_dump_open_finish(wdh, filetype, compressed, err)) {
1614                 wtap_dump_file_close(wdh);
1615                 g_free(wdh);
1616                 return NULL;
1617         }
1618         return wdh;
1619 }
1620
1621 static gboolean wtap_dump_open_check(int filetype, int encap, gboolean compressed, int *err)
1622 {
1623         if (!wtap_dump_can_open(filetype)) {
1624                 /* Invalid type, or type we don't know how to write. */
1625                 *err = WTAP_ERR_UNSUPPORTED_FILE_TYPE;
1626                 return FALSE;
1627         }
1628
1629         /* OK, we know how to write that type; can we write the specified
1630            encapsulation type? */
1631         *err = (*dump_open_table[filetype].can_write_encap)(encap);
1632         if (*err != 0)
1633                 return FALSE;
1634
1635         /* if compression is wanted, do we support this for this filetype? */
1636         if(compressed && !wtap_dump_can_compress(filetype)) {
1637                 *err = WTAP_ERR_COMPRESSION_NOT_SUPPORTED;
1638                 return FALSE;
1639         }
1640
1641         *err = (*dump_open_table[filetype].can_write_encap)(encap);
1642         if (*err != 0)
1643                 return FALSE;
1644
1645         /* All systems go! */
1646         return TRUE;
1647 }
1648
1649 static wtap_dumper* wtap_dump_alloc_wdh(int filetype, int encap, int snaplen,
1650                                         gboolean compressed, int *err)
1651 {
1652         wtap_dumper *wdh;
1653
1654         wdh = (wtap_dumper *)g_malloc0(sizeof (wtap_dumper));
1655         if (wdh == NULL) {
1656                 *err = errno;
1657                 return NULL;
1658         }
1659
1660         wdh->file_type = filetype;
1661         wdh->snaplen = snaplen;
1662         wdh->encap = encap;
1663         wdh->compressed = compressed;
1664         return wdh;
1665 }
1666
1667 static gboolean wtap_dump_open_finish(wtap_dumper *wdh, int filetype, gboolean compressed, int *err)
1668 {
1669         int fd;
1670         gboolean cant_seek;
1671
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;
1684                 }
1685         }
1686
1687         /* If this file type requires seeking, and we can't seek, fail. */
1688         if (dump_open_table[filetype].writing_must_seek && cant_seek) {
1689                 *err = WTAP_ERR_CANT_WRITE_TO_PIPE;
1690                 return FALSE;
1691         }
1692
1693         /* Now try to open the file for writing. */
1694         if (!(*dump_open_table[filetype].dump_open)(wdh, err)) {
1695                 return FALSE;
1696         }
1697
1698         return TRUE;    /* success! */
1699 }
1700
1701 gboolean wtap_dump(wtap_dumper *wdh, const struct wtap_pkthdr *phdr,
1702                    const guint8 *pd, int *err)
1703 {
1704         return (wdh->subtype_write)(wdh, phdr, pd, err);
1705 }
1706
1707 void wtap_dump_flush(wtap_dumper *wdh)
1708 {
1709 #ifdef HAVE_LIBZ
1710         if(wdh->compressed) {
1711                 gzwfile_flush((GZWFILE_T)wdh->fh);
1712         } else
1713 #endif
1714         {
1715                 fflush((FILE *)wdh->fh);
1716         }
1717 }
1718
1719 gboolean wtap_dump_close(wtap_dumper *wdh, int *err)
1720 {
1721         gboolean ret = TRUE;
1722
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;
1727         }
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;
1738                         }
1739                         ret = FALSE;
1740                 }
1741         } else {
1742                 /* as we don't close stdout, at least try to flush it */
1743                 wtap_dump_flush(wdh);
1744         }
1745         if (wdh->priv != NULL)
1746                 g_free(wdh->priv);
1747         g_free(wdh);
1748         return ret;
1749 }
1750
1751 gint64 wtap_get_bytes_dumped(wtap_dumper *wdh)
1752 {
1753         return wdh->bytes_dumped;
1754 }
1755
1756 void wtap_set_bytes_dumped(wtap_dumper *wdh, gint64 bytes_dumped)
1757 {
1758         wdh->bytes_dumped = bytes_dumped;
1759 }
1760
1761 gboolean wtap_dump_set_addrinfo_list(wtap_dumper *wdh, addrinfo_lists_t *addrinfo_lists)
1762 {
1763         if (!wdh || wdh->file_type < 0 || wdh->file_type >= wtap_num_file_types
1764                 || dump_open_table[wdh->file_type].has_name_resolution == FALSE)
1765                         return FALSE;
1766         wdh->addrinfo_lists = addrinfo_lists;
1767         return TRUE;
1768 }
1769
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)
1773 {
1774         if(wdh->compressed) {
1775                 return gzwfile_open(filename);
1776         } else {
1777                 return ws_fopen(filename, "wb");
1778         }
1779 }
1780 #else
1781 static WFILE_T wtap_dump_file_open(wtap_dumper *wdh _U_, const char *filename)
1782 {
1783         return ws_fopen(filename, "wb");
1784 }
1785 #endif
1786
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)
1790 {
1791         if(wdh->compressed) {
1792                 return gzwfile_fdopen(fd);
1793         } else {
1794                 return fdopen(fd, "wb");
1795         }
1796 }
1797 #else
1798 static WFILE_T wtap_dump_file_fdopen(wtap_dumper *wdh _U_, int fd)
1799 {
1800         return fdopen(fd, "wb");
1801 }
1802 #endif
1803
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)
1807 {
1808         size_t nwritten;
1809
1810 #ifdef HAVE_LIBZ
1811         if (wdh->compressed) {
1812                 nwritten = gzwfile_write((GZWFILE_T)wdh->fh, buf, (unsigned) bufsize);
1813                 /*
1814                  * gzwfile_write() returns 0 on error.
1815                  */
1816                 if (nwritten == 0) {
1817                         *err = gzwfile_geterr((GZWFILE_T)wdh->fh);
1818                         return FALSE;
1819                 }
1820         } else
1821 #endif
1822         {
1823                 nwritten = fwrite(buf, 1, bufsize, (FILE *)wdh->fh);
1824                 /*
1825                  * At least according to the Mac OS X man page,
1826                  * this can return a short count on an error.
1827                  */
1828                 if (nwritten != bufsize) {
1829                         if (ferror((FILE *)wdh->fh))
1830                                 *err = errno;
1831                         else
1832                                 *err = WTAP_ERR_SHORT_WRITE;
1833                         return FALSE;
1834                 }
1835         }
1836         return TRUE;
1837 }
1838
1839 /* internally close a file for writing (compressed or not) */
1840 static int wtap_dump_file_close(wtap_dumper *wdh)
1841 {
1842 #ifdef HAVE_LIBZ
1843         if(wdh->compressed) {
1844                 return gzwfile_close((GZWFILE_T)wdh->fh);
1845         } else
1846 #endif
1847         {
1848                 return fclose((FILE *)wdh->fh);
1849         }
1850 }
1851
1852 gint64 wtap_dump_file_seek(wtap_dumper *wdh, gint64 offset, int whence, int *err)
1853 {
1854 #ifdef HAVE_LIBZ
1855         if(wdh->compressed) {
1856                 *err = WTAP_ERR_CANT_SEEK_COMPRESSED;
1857                 return -1;
1858         } else
1859 #endif
1860         {
1861                 if (-1 == fseek((FILE *)wdh->fh, (long)offset, whence)) {
1862                         *err = errno;
1863                         return -1;
1864                 } else
1865                 {
1866                         return 0;
1867                 }       
1868         }
1869 }
1870 gint64 wtap_dump_file_tell(wtap_dumper *wdh, int *err)
1871 {
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
1879         {
1880                 if (-1 == (rval = ftell((FILE *)wdh->fh))) {
1881                         *err = errno;
1882                         return -1;
1883                 } else
1884                 {
1885                         return rval;
1886                 }       
1887         }
1888 }