Get rid of struct addrinfo, use the hastables for name resolution instead.
[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 };
978
979 gint wtap_num_file_types = sizeof(dump_open_table_base) / sizeof(struct file_type_info);
980
981 static GArray*  dump_open_table_arr = NULL;
982 static const struct file_type_info* dump_open_table = dump_open_table_base;
983
984 /* initialize the file types array if it has not being initialized yet */
985 static void init_file_types(void) {
986
987         if (dump_open_table_arr) return;
988
989         dump_open_table_arr = g_array_new(FALSE,TRUE,sizeof(struct file_type_info));
990
991         g_array_append_vals(dump_open_table_arr,dump_open_table_base,wtap_num_file_types);
992
993         dump_open_table = (const struct file_type_info*)(void *)dump_open_table_arr->data;
994 }
995
996 int wtap_register_file_type(const struct file_type_info* fi) {
997         init_file_types();
998
999         g_array_append_val(dump_open_table_arr,*fi);
1000
1001         dump_open_table = (const struct file_type_info*)(void *)dump_open_table_arr->data;
1002
1003         return wtap_num_file_types++;
1004 }
1005
1006 int wtap_get_num_file_types(void)
1007 {
1008         return wtap_num_file_types;
1009 }
1010
1011 /*
1012  * Given a GArray of WTAP_ENCAP_ types, return the per-file encapsulation
1013  * type that would be needed to write out a file with those types.  If
1014  * there's only one type, it's that type, otherwise it's
1015  * WTAP_ENCAP_PER_PACKET.
1016  */
1017 int
1018 wtap_dump_file_encap_type(const GArray *file_encaps)
1019 {
1020         int encap;
1021
1022         encap = WTAP_ENCAP_PER_PACKET;
1023         if (file_encaps->len == 1) {
1024                 /* OK, use the one-and-only encapsulation type. */
1025                 encap = g_array_index(file_encaps, gint, 0);
1026         }
1027         return encap;
1028 }
1029
1030 static gboolean
1031 wtap_dump_can_write_encap(int filetype, int encap)
1032 {
1033         if (filetype < 0 || filetype >= wtap_num_file_types
1034             || dump_open_table[filetype].can_write_encap == NULL)
1035                 return FALSE;
1036
1037         if ((*dump_open_table[filetype].can_write_encap)(encap) != 0)
1038                 return FALSE;
1039
1040         return TRUE;
1041 }
1042
1043 /*
1044  * Return TRUE if a capture with a given GArray of encapsulation types
1045  * and a given bitset of comment types can be written in a specified
1046  * format, and FALSE if it can't.
1047  */
1048 static gboolean
1049 wtap_dump_can_write_format(int ft, const GArray *file_encaps,
1050     guint32 required_comment_types)
1051 {
1052         guint i;
1053
1054         /*
1055          * Can we write in this format?
1056          */
1057         if (!wtap_dump_can_open(ft)) {
1058                 /* No. */
1059                 return FALSE;
1060         }
1061
1062         /*
1063          * Yes.  Can we write out all the required comments in this
1064          * format?
1065          */
1066         if (!wtap_dump_supports_comment_types(ft, required_comment_types)) {
1067                 /* No. */
1068                 return FALSE;
1069         }
1070
1071         /*
1072          * Yes.  Is the required per-file encapsulation type supported?
1073          * This might be WTAP_ENCAP_PER_PACKET.
1074          */
1075         if (!wtap_dump_can_write_encap(ft, wtap_dump_file_encap_type(file_encaps))) {
1076                 /* No. */
1077                 return FALSE;
1078         }
1079
1080         /*
1081          * Yes.  Are all the individual encapsulation types supported?
1082          */
1083         for (i = 0; i < file_encaps->len; i++) {
1084                 if (!wtap_dump_can_write_encap(ft,
1085                     g_array_index(file_encaps, int, i))) {
1086                         /* No - one of them isn't. */
1087                         return FALSE;
1088                 }
1089         }
1090
1091         /* Yes - we're OK. */
1092         return TRUE;
1093 }
1094
1095 /**
1096  * Return TRUE if we can write a file with the given GArray of
1097  * encapsulation types and the given bitmask of comment types.
1098  */
1099 gboolean
1100 wtap_dump_can_write(const GArray *file_encaps, guint32 required_comment_types)
1101 {
1102   int ft;
1103
1104   for (ft = 0; ft < WTAP_NUM_FILE_TYPES; ft++) {
1105     /* To save a file with Wiretap, Wiretap has to handle that format,
1106        and its code to handle that format must be able to write a file
1107        with this file's encapsulation types. */
1108     if (wtap_dump_can_write_format(ft, file_encaps, required_comment_types)) {
1109       /* OK, we can write it out in this type. */
1110       return TRUE;
1111     }
1112   }
1113
1114   /* No, we couldn't save it in any format. */
1115   return FALSE;
1116 }
1117
1118 /**
1119  * Get a GArray of WTAP_FILE_ values for file types that can be used
1120  * to save a file of a given type with a given GArray of encapsulation
1121  * types and the given bitmask of comment types.
1122  */
1123 GArray *
1124 wtap_get_savable_file_types(int file_type, const GArray *file_encaps,
1125     guint32 required_comment_types)
1126 {
1127         GArray *savable_file_types;
1128         int ft;
1129         int default_file_type = -1;
1130         int other_file_type = -1;
1131
1132         /* Can we save this file in its own file type? */
1133         if (wtap_dump_can_write_format(file_type, file_encaps,
1134                                        required_comment_types)) {
1135                 /* Yes - make that the default file type. */
1136                 default_file_type = file_type;
1137         } else {
1138                 /* OK, find the first file type we *can* save it as. */
1139                 default_file_type = -1;
1140                 for (ft = 0; ft < WTAP_NUM_FILE_TYPES; ft++) {
1141                         if (wtap_dump_can_write_format(ft, file_encaps,
1142                                                        required_comment_types)) {
1143                                 /* OK, got it. */
1144                                 default_file_type = ft;
1145                         }
1146                 }
1147         }
1148
1149         if (default_file_type == -1) {
1150                 /* We don't support writing this file as any file type. */
1151                 return NULL;
1152         }
1153
1154         /* Allocate the array. */
1155         savable_file_types = g_array_new(FALSE, FALSE, (guint)sizeof (int));
1156
1157         /* Put the default file format first in the list. */
1158         g_array_append_val(savable_file_types, default_file_type);
1159
1160         /* If the default is pcap, put pcap-NG right after it if we can
1161            also write it in pcap-NG format; otherwise, if the default is
1162            pcap-NG, put pcap right after it if we can also write it in
1163            pcap format. */
1164         if (default_file_type == WTAP_FILE_PCAP) {
1165                 if (wtap_dump_can_write_format(WTAP_FILE_PCAPNG, file_encaps,
1166                                                required_comment_types))
1167                         other_file_type = WTAP_FILE_PCAPNG;
1168         } else if (default_file_type == WTAP_FILE_PCAPNG) {
1169                 if (wtap_dump_can_write_format(WTAP_FILE_PCAP, file_encaps,
1170                                                required_comment_types))
1171                         other_file_type = WTAP_FILE_PCAP;
1172         }
1173         if (other_file_type != -1)
1174                 g_array_append_val(savable_file_types, other_file_type);
1175
1176         /* Add all the other file types that work. */
1177         for (ft = 0; ft < WTAP_NUM_FILE_TYPES; ft++) {
1178                 if (ft == WTAP_FILE_UNKNOWN)
1179                         continue;       /* not a real file type */
1180                 if (ft == default_file_type || ft == other_file_type)
1181                         continue;       /* we've already done this one */
1182                 if (wtap_dump_can_write_format(ft, file_encaps,
1183                                                required_comment_types)) {
1184                         /* OK, we can write it out in this type. */
1185                         g_array_append_val(savable_file_types, ft);
1186                 }
1187         }
1188
1189         return savable_file_types;
1190 }
1191
1192 /* Name that should be somewhat descriptive. */
1193 const char *wtap_file_type_string(int filetype)
1194 {
1195         if (filetype < 0 || filetype >= wtap_num_file_types) {
1196                 g_error("Unknown capture file type %d", filetype);
1197                 /** g_error() does an abort() and thus never returns **/
1198                 return "";
1199         } else
1200                 return dump_open_table[filetype].name;
1201 }
1202
1203 /* Name to use in, say, a command-line flag specifying the type. */
1204 const char *wtap_file_type_short_string(int filetype)
1205 {
1206         if (filetype < 0 || filetype >= wtap_num_file_types)
1207                 return NULL;
1208         else
1209                 return dump_open_table[filetype].short_name;
1210 }
1211
1212 /* Translate a short name to a capture file type. */
1213 int wtap_short_string_to_file_type(const char *short_name)
1214 {
1215         int filetype;
1216
1217         for (filetype = 0; filetype < wtap_num_file_types; filetype++) {
1218                 if (dump_open_table[filetype].short_name != NULL &&
1219                     strcmp(short_name, dump_open_table[filetype].short_name) == 0)
1220                         return filetype;
1221         }
1222
1223         /*
1224          * We now call the "libpcap" file format just "pcap", but we
1225          * allow it to be specified as "libpcap" as well, for
1226          * backwards compatibility.
1227          */
1228         if (strcmp(short_name, "libpcap") == 0)
1229                 return WTAP_FILE_PCAP;
1230
1231         return -1;      /* no such file type, or we can't write it */
1232 }
1233
1234 static GSList *
1235 add_extensions_for_filetype(int filetype, GSList *extensions,
1236     GSList *compressed_file_extensions)
1237 {
1238         gchar **extensions_set, **extensionp;
1239         gchar *extension;
1240
1241         /*
1242          * Add the default extension, and all compressed variants of
1243          * it.
1244          */
1245         extensions = add_extensions(extensions,
1246             dump_open_table[filetype].default_file_extension,
1247             compressed_file_extensions);
1248
1249         if (dump_open_table[filetype].additional_file_extensions != NULL) {
1250                 /*
1251                  * We have additional extensions; add them.
1252                  *
1253                  * First, split the extension-list string into a set of
1254                  * extensions.
1255                  */
1256                 extensions_set = g_strsplit(dump_open_table[filetype].additional_file_extensions,
1257                     ";", 0);
1258
1259                 /*
1260                  * Add each of those extensions to the list.
1261                  */
1262                 for (extensionp = extensions_set; *extensionp != NULL;
1263                     extensionp++) {
1264                         extension = *extensionp;
1265
1266                         /*
1267                          * Add the extension, and all compressed variants
1268                          * of it.
1269                          */
1270                         extensions = add_extensions(extensions, extension,
1271                             compressed_file_extensions);
1272                 }
1273
1274                 g_strfreev(extensions_set);
1275         }
1276         return extensions;
1277 }
1278
1279 /* Return a list of file extensions that are used by the specified file type.
1280
1281    If include_compressed is TRUE, the list will include compressed
1282    extensions, e.g. not just "pcap" but also "pcap.gz" if we can read
1283    gzipped files.
1284
1285    All strings in the list are allocated with g_malloc() and must be freed
1286    with g_free(). */
1287 GSList *wtap_get_file_extensions_list(int filetype, gboolean include_compressed)
1288 {
1289         GSList *compressed_file_extensions;
1290         GSList *extensions;
1291
1292         if (filetype < 0 || filetype >= wtap_num_file_types)
1293                 return NULL;    /* not a valid file type */
1294
1295         if (dump_open_table[filetype].default_file_extension == NULL)
1296                 return NULL;    /* valid, but no extensions known */
1297
1298         extensions = NULL;      /* empty list, to start with */
1299
1300         /*
1301          * If include_compressions is true, get the list of compressed-file
1302          * extensions.
1303          */
1304         if (include_compressed)
1305                 compressed_file_extensions = wtap_get_compressed_file_extensions();
1306         else
1307                 compressed_file_extensions = NULL;
1308
1309         /*
1310          * Add all this file type's extensions, with compressed
1311          * variants.
1312          */
1313         extensions = add_extensions_for_filetype(filetype, extensions,
1314             compressed_file_extensions);
1315
1316         g_slist_free(compressed_file_extensions);
1317         return extensions;
1318 }
1319
1320 /*
1321  * Free a list returned by wtap_get_file_extensions_list().
1322  */
1323 void wtap_free_file_extensions_list(GSList *extensions)
1324 {
1325         GSList *extension;
1326
1327         for (extension = extensions; extension != NULL;
1328             extension = g_slist_next(extension)) {
1329                 g_free(extension->data);
1330         }
1331         g_slist_free(extensions);
1332 }
1333
1334 /* Return the default file extension to use with the specified file type;
1335    that's just the extension, without any ".". */
1336 const char *wtap_default_file_extension(int filetype)
1337 {
1338         if (filetype < 0 || filetype >= wtap_num_file_types)
1339                 return NULL;
1340         else
1341                 return dump_open_table[filetype].default_file_extension;
1342 }
1343
1344 gboolean wtap_dump_can_open(int filetype)
1345 {
1346         if (filetype < 0 || filetype >= wtap_num_file_types
1347             || dump_open_table[filetype].dump_open == NULL)
1348                 return FALSE;
1349
1350         return TRUE;
1351 }
1352
1353 #ifdef HAVE_LIBZ
1354 gboolean wtap_dump_can_compress(int filetype)
1355 {
1356         /*
1357          * If this is an unknown file type, or if we have to
1358          * seek when writing out a file with this file type,
1359          * return FALSE.
1360          */
1361         if (filetype < 0 || filetype >= wtap_num_file_types
1362             || dump_open_table[filetype].writing_must_seek)
1363                 return FALSE;
1364
1365         return TRUE;
1366 }
1367 #else
1368 gboolean wtap_dump_can_compress(int filetype _U_)
1369 {
1370         return FALSE;
1371 }
1372 #endif
1373
1374 gboolean wtap_dump_has_name_resolution(int filetype)
1375 {
1376         if (filetype < 0 || filetype >= wtap_num_file_types
1377             || dump_open_table[filetype].has_name_resolution == FALSE)
1378                 return FALSE;
1379
1380         return TRUE;
1381 }
1382
1383 gboolean wtap_dump_supports_comment_types(int filetype, guint32 comment_types)
1384 {
1385         guint32 supported_comment_types;
1386
1387         if (filetype < 0 || filetype >= wtap_num_file_types)
1388                 return FALSE;
1389
1390         supported_comment_types = dump_open_table[filetype].supported_comment_types;
1391
1392         if ((comment_types & supported_comment_types) == comment_types)
1393                 return TRUE;
1394         return FALSE;
1395 }
1396
1397 static gboolean wtap_dump_open_check(int filetype, int encap, gboolean comressed, int *err);
1398 static wtap_dumper* wtap_dump_alloc_wdh(int filetype, int encap, int snaplen,
1399                                         gboolean compressed, int *err);
1400 static gboolean wtap_dump_open_finish(wtap_dumper *wdh, int filetype, gboolean compressed, int *err);
1401
1402 static WFILE_T wtap_dump_file_open(wtap_dumper *wdh, const char *filename);
1403 static WFILE_T wtap_dump_file_fdopen(wtap_dumper *wdh, int fd);
1404 static int wtap_dump_file_close(wtap_dumper *wdh);
1405
1406 wtap_dumper* wtap_dump_open(const char *filename, int filetype, int encap,
1407                                 int snaplen, gboolean compressed, int *err)
1408 {
1409         return wtap_dump_open_ng(filename, filetype, encap,snaplen, compressed, NULL, NULL, err);
1410 }
1411
1412 static wtap_dumper *
1413 wtap_dump_init_dumper(int filetype, int encap, int snaplen, gboolean compressed,
1414     wtapng_section_t *shb_hdr, wtapng_iface_descriptions_t *idb_inf, int *err)
1415 {
1416         wtap_dumper *wdh;
1417
1418         /* Allocate a data structure for the output stream. */
1419         wdh = wtap_dump_alloc_wdh(filetype, encap, snaplen, compressed, err);
1420         if (wdh == NULL)
1421                 return NULL;    /* couldn't allocate it */
1422
1423         /* Set Section Header Block data */
1424         wdh->shb_hdr = shb_hdr;
1425         /* Set Interface Description Block data */
1426         if ((idb_inf != NULL) && (idb_inf->number_of_interfaces > 0)) {
1427                 wdh->number_of_interfaces = idb_inf->number_of_interfaces;
1428                 wdh->interface_data = idb_inf->interface_data;
1429         } else {
1430                 wtapng_if_descr_t descr;
1431
1432                 descr.wtap_encap = encap;
1433                 descr.time_units_per_second = 1000000; /* default microsecond resolution */
1434                 descr.link_type = wtap_wtap_encap_to_pcap_encap(encap);
1435                 descr.snap_len = snaplen;
1436                 descr.opt_comment = NULL;
1437                 descr.if_name = g_strdup("Unknown/not available in original file format(libpcap)");
1438                 descr.if_description = NULL;
1439                 descr.if_speed = 0;
1440                 descr.if_tsresol = 6;
1441                 descr.if_filter_str= NULL;
1442                 descr.bpf_filter_len= 0;
1443                 descr.if_filter_bpf_bytes= NULL;
1444                 descr.if_os = NULL;
1445                 descr.if_fcslen = -1;
1446                 descr.num_stat_entries = 0;          /* Number of ISB:s */
1447                 descr.interface_statistics = NULL;
1448                 wdh->number_of_interfaces= 1;
1449                 wdh->interface_data= g_array_new(FALSE, FALSE, sizeof(wtapng_if_descr_t));
1450                 g_array_append_val(wdh->interface_data, descr);
1451         }
1452         return wdh;
1453 }
1454
1455 wtap_dumper* wtap_dump_open_ng(const char *filename, int filetype, int encap,
1456                                 int snaplen, gboolean compressed, wtapng_section_t *shb_hdr, wtapng_iface_descriptions_t *idb_inf, int *err)
1457 {
1458         wtap_dumper *wdh;
1459         WFILE_T fh;
1460
1461         /* Check whether we can open a capture file with that file type
1462            and that encapsulation. */
1463         if (!wtap_dump_open_check(filetype, encap, compressed, err))
1464                 return NULL;
1465
1466         /* Allocate and initialize a data structure for the output stream. */
1467         wdh = wtap_dump_init_dumper(filetype, encap, snaplen, compressed,
1468             shb_hdr, idb_inf, err);
1469         if (wdh == NULL)
1470                 return NULL;
1471
1472         /* "-" means stdout */
1473         if (strcmp(filename, "-") == 0) {
1474                 if (compressed) {
1475                         *err = EINVAL;  /* XXX - return a Wiretap error code for this */
1476                         g_free(wdh);
1477                         return NULL;    /* compress won't work on stdout */
1478                 }
1479 #ifdef _WIN32
1480                 if (_setmode(fileno(stdout), O_BINARY) == -1) {
1481                         /* "Should not happen" */
1482                         *err = errno;
1483                         g_free(wdh);
1484                         return NULL;    /* couldn't put standard output in binary mode */
1485                 }
1486 #endif
1487                 wdh->fh = stdout;
1488         } else {
1489                 /* In case "fopen()" fails but doesn't set "errno", set "errno"
1490                    to a generic "the open failed" error. */
1491                 errno = WTAP_ERR_CANT_OPEN;
1492                 fh = wtap_dump_file_open(wdh, filename);
1493                 if (fh == NULL) {
1494                         *err = errno;
1495                         g_free(wdh);
1496                         return NULL;    /* can't create file */
1497                 }
1498                 wdh->fh = fh;
1499         }
1500
1501         if (!wtap_dump_open_finish(wdh, filetype, compressed, err)) {
1502                 /* Get rid of the file we created; we couldn't finish
1503                    opening it. */
1504                 if (wdh->fh != stdout) {
1505                         wtap_dump_file_close(wdh);
1506                         ws_unlink(filename);
1507                 }
1508                 g_free(wdh);
1509                 return NULL;
1510         }
1511         return wdh;
1512 }
1513
1514 wtap_dumper* wtap_dump_fdopen(int fd, int filetype, int encap, int snaplen,
1515                                 gboolean compressed, int *err)
1516 {
1517         return wtap_dump_fdopen_ng(fd, filetype, encap, snaplen, compressed, NULL, NULL, err);
1518 }
1519
1520 wtap_dumper* wtap_dump_fdopen_ng(int fd, int filetype, int encap, int snaplen,
1521                                 gboolean compressed, wtapng_section_t *shb_hdr, wtapng_iface_descriptions_t *idb_inf, int *err)
1522 {
1523         wtap_dumper *wdh;
1524         WFILE_T fh;
1525
1526         /* Check whether we can open a capture file with that file type
1527            and that encapsulation. */
1528         if (!wtap_dump_open_check(filetype, encap, compressed, err))
1529                 return NULL;
1530
1531         /* Allocate and initialize a data structure for the output stream. */
1532         wdh = wtap_dump_init_dumper(filetype, encap, snaplen, compressed,
1533             shb_hdr, idb_inf, err);
1534         if (wdh == NULL)
1535                 return NULL;
1536
1537 #ifdef _WIN32
1538         if (fd == 1) {
1539                 if (_setmode(fileno(stdout), O_BINARY) == -1) {
1540                         /* "Should not happen" */
1541                         *err = errno;
1542                         g_free(wdh);
1543                         return NULL;    /* couldn't put standard output in binary mode */
1544                 }
1545         }
1546 #endif
1547
1548         /* In case "fopen()" fails but doesn't set "errno", set "errno"
1549            to a generic "the open failed" error. */
1550         errno = WTAP_ERR_CANT_OPEN;
1551         fh = wtap_dump_file_fdopen(wdh, fd);
1552         if (fh == NULL) {
1553                 *err = errno;
1554                 g_free(wdh);
1555                 return NULL;    /* can't create standard I/O stream */
1556         }
1557         wdh->fh = fh;
1558
1559         if (!wtap_dump_open_finish(wdh, filetype, compressed, err)) {
1560                 wtap_dump_file_close(wdh);
1561                 g_free(wdh);
1562                 return NULL;
1563         }
1564         return wdh;
1565 }
1566
1567 static gboolean wtap_dump_open_check(int filetype, int encap, gboolean compressed, int *err)
1568 {
1569         if (!wtap_dump_can_open(filetype)) {
1570                 /* Invalid type, or type we don't know how to write. */
1571                 *err = WTAP_ERR_UNSUPPORTED_FILE_TYPE;
1572                 return FALSE;
1573         }
1574
1575         /* OK, we know how to write that type; can we write the specified
1576            encapsulation type? */
1577         *err = (*dump_open_table[filetype].can_write_encap)(encap);
1578         if (*err != 0)
1579                 return FALSE;
1580
1581         /* if compression is wanted, do we support this for this filetype? */
1582         if(compressed && !wtap_dump_can_compress(filetype)) {
1583                 *err = WTAP_ERR_COMPRESSION_NOT_SUPPORTED;
1584                 return FALSE;
1585         }
1586
1587         *err = (*dump_open_table[filetype].can_write_encap)(encap);
1588         if (*err != 0)
1589                 return FALSE;
1590
1591         /* All systems go! */
1592         return TRUE;
1593 }
1594
1595 static wtap_dumper* wtap_dump_alloc_wdh(int filetype, int encap, int snaplen,
1596                                         gboolean compressed, int *err)
1597 {
1598         wtap_dumper *wdh;
1599
1600         wdh = (wtap_dumper *)g_malloc0(sizeof (wtap_dumper));
1601         if (wdh == NULL) {
1602                 *err = errno;
1603                 return NULL;
1604         }
1605
1606         wdh->file_type = filetype;
1607         wdh->snaplen = snaplen;
1608         wdh->encap = encap;
1609         wdh->compressed = compressed;
1610         return wdh;
1611 }
1612
1613 static gboolean wtap_dump_open_finish(wtap_dumper *wdh, int filetype, gboolean compressed, int *err)
1614 {
1615         int fd;
1616         gboolean cant_seek;
1617
1618         /* Can we do a seek on the file descriptor?
1619            If not, note that fact. */
1620         if(compressed) {
1621                 cant_seek = TRUE;
1622         } else {
1623                 fd = fileno((FILE *)wdh->fh);
1624                 if (lseek(fd, 1, SEEK_CUR) == -1)
1625                         cant_seek = TRUE;
1626                 else {
1627                         /* Undo the seek. */
1628                         lseek(fd, 0, SEEK_SET);
1629                         cant_seek = FALSE;
1630                 }
1631         }
1632
1633         /* If this file type requires seeking, and we can't seek, fail. */
1634         if (dump_open_table[filetype].writing_must_seek && cant_seek) {
1635                 *err = WTAP_ERR_CANT_WRITE_TO_PIPE;
1636                 return FALSE;
1637         }
1638
1639         /* Now try to open the file for writing. */
1640         if (!(*dump_open_table[filetype].dump_open)(wdh, err)) {
1641                 return FALSE;
1642         }
1643
1644         return TRUE;    /* success! */
1645 }
1646
1647 gboolean wtap_dump(wtap_dumper *wdh, const struct wtap_pkthdr *phdr,
1648                    const guint8 *pd, int *err)
1649 {
1650         return (wdh->subtype_write)(wdh, phdr, pd, err);
1651 }
1652
1653 void wtap_dump_flush(wtap_dumper *wdh)
1654 {
1655 #ifdef HAVE_LIBZ
1656         if(wdh->compressed) {
1657                 gzwfile_flush((GZWFILE_T)wdh->fh);
1658         } else
1659 #endif
1660         {
1661                 fflush((FILE *)wdh->fh);
1662         }
1663 }
1664
1665 gboolean wtap_dump_close(wtap_dumper *wdh, int *err)
1666 {
1667         gboolean ret = TRUE;
1668
1669         if (wdh->subtype_close != NULL) {
1670                 /* There's a close routine for this dump stream. */
1671                 if (!(wdh->subtype_close)(wdh, err))
1672                         ret = FALSE;
1673         }
1674         errno = WTAP_ERR_CANT_CLOSE;
1675         /* Don't close stdout */
1676         if (wdh->fh != stdout) {
1677                 if (wtap_dump_file_close(wdh) == EOF) {
1678                         if (ret) {
1679                                 /* The per-format close function succeeded,
1680                                    but the fclose didn't.  Save the reason
1681                                    why, if our caller asked for it. */
1682                                 if (err != NULL)
1683                                         *err = errno;
1684                         }
1685                         ret = FALSE;
1686                 }
1687         } else {
1688                 /* as we don't close stdout, at least try to flush it */
1689                 wtap_dump_flush(wdh);
1690         }
1691         if (wdh->priv != NULL)
1692                 g_free(wdh->priv);
1693         g_free(wdh);
1694         return ret;
1695 }
1696
1697 gint64 wtap_get_bytes_dumped(wtap_dumper *wdh)
1698 {
1699         return wdh->bytes_dumped;
1700 }
1701
1702 void wtap_set_bytes_dumped(wtap_dumper *wdh, gint64 bytes_dumped)
1703 {
1704         wdh->bytes_dumped = bytes_dumped;
1705 }
1706
1707 gboolean wtap_dump_set_addrinfo_list(wtap_dumper *wdh, addrinfo_lists_t *addrinfo_lists)
1708 {
1709         if (!wdh || wdh->file_type < 0 || wdh->file_type >= wtap_num_file_types
1710                 || dump_open_table[wdh->file_type].has_name_resolution == FALSE)
1711                         return FALSE;
1712         wdh->addrinfo_lists = addrinfo_lists;
1713         return TRUE;
1714 }
1715
1716 /* internally open a file for writing (compressed or not) */
1717 #ifdef HAVE_LIBZ
1718 static WFILE_T wtap_dump_file_open(wtap_dumper *wdh, const char *filename)
1719 {
1720         if(wdh->compressed) {
1721                 return gzwfile_open(filename);
1722         } else {
1723                 return ws_fopen(filename, "wb");
1724         }
1725 }
1726 #else
1727 static WFILE_T wtap_dump_file_open(wtap_dumper *wdh _U_, const char *filename)
1728 {
1729         return ws_fopen(filename, "wb");
1730 }
1731 #endif
1732
1733 /* internally open a file for writing (compressed or not) */
1734 #ifdef HAVE_LIBZ
1735 static WFILE_T wtap_dump_file_fdopen(wtap_dumper *wdh, int fd)
1736 {
1737         if(wdh->compressed) {
1738                 return gzwfile_fdopen(fd);
1739         } else {
1740                 return fdopen(fd, "wb");
1741         }
1742 }
1743 #else
1744 static WFILE_T wtap_dump_file_fdopen(wtap_dumper *wdh _U_, int fd)
1745 {
1746         return fdopen(fd, "wb");
1747 }
1748 #endif
1749
1750 /* internally writing raw bytes (compressed or not) */
1751 gboolean wtap_dump_file_write(wtap_dumper *wdh, const void *buf, size_t bufsize,
1752                      int *err)
1753 {
1754         size_t nwritten;
1755
1756 #ifdef HAVE_LIBZ
1757         if (wdh->compressed) {
1758                 nwritten = gzwfile_write((GZWFILE_T)wdh->fh, buf, (unsigned) bufsize);
1759                 /*
1760                  * gzwfile_write() returns 0 on error.
1761                  */
1762                 if (nwritten == 0) {
1763                         *err = gzwfile_geterr((GZWFILE_T)wdh->fh);
1764                         return FALSE;
1765                 }
1766         } else
1767 #endif
1768         {
1769                 nwritten = fwrite(buf, 1, bufsize, (FILE *)wdh->fh);
1770                 /*
1771                  * At least according to the Mac OS X man page,
1772                  * this can return a short count on an error.
1773                  */
1774                 if (nwritten != bufsize) {
1775                         if (ferror((FILE *)wdh->fh))
1776                                 *err = errno;
1777                         else
1778                                 *err = WTAP_ERR_SHORT_WRITE;
1779                         return FALSE;
1780                 }
1781         }
1782         return TRUE;
1783 }
1784
1785 /* internally close a file for writing (compressed or not) */
1786 static int wtap_dump_file_close(wtap_dumper *wdh)
1787 {
1788 #ifdef HAVE_LIBZ
1789         if(wdh->compressed) {
1790                 return gzwfile_close((GZWFILE_T)wdh->fh);
1791         } else
1792 #endif
1793         {
1794                 return fclose((FILE *)wdh->fh);
1795         }
1796 }
1797
1798 gint64 wtap_dump_file_seek(wtap_dumper *wdh, gint64 offset, int whence, int *err)
1799 {
1800 #ifdef HAVE_LIBZ
1801         if(wdh->compressed) {
1802                 *err = WTAP_ERR_CANT_SEEK_COMPRESSED;
1803                 return -1;
1804         } else
1805 #endif
1806         {
1807                 if (-1 == fseek((FILE *)wdh->fh, (long)offset, whence)) {
1808                         *err = errno;
1809                         return -1;
1810                 } else
1811                 {
1812                         return 0;
1813                 }       
1814         }
1815 }
1816 gint64 wtap_dump_file_tell(wtap_dumper *wdh, int *err)
1817 {
1818         gint64 rval;
1819 #ifdef HAVE_LIBZ
1820         if(wdh->compressed) {
1821                 *err = WTAP_ERR_CANT_SEEK_COMPRESSED;
1822                 return -1;
1823         } else
1824 #endif
1825         {
1826                 if (-1 == (rval = ftell((FILE *)wdh->fh))) {
1827                         *err = errno;
1828                         return -1;
1829                 } else
1830                 {
1831                         return rval;
1832                 }       
1833         }
1834 }