Make pcap-ng the default. Add a compile-time option to prefer pcap-ng or
[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., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
21  */
22
23 #ifdef HAVE_CONFIG_H
24 #include "config.h"
25 #endif
26
27 #include <stdio.h>
28 #include <string.h>
29 #include <stdlib.h>
30
31 #ifdef HAVE_FCNTL_H
32 #include <fcntl.h>
33 #endif
34
35 #ifdef HAVE_UNISTD_H
36 #include <unistd.h>
37 #endif
38
39 #include <errno.h>
40
41 #include <wsutil/file_util.h>
42
43 #include "wtap-int.h"
44 #include "file_wrappers.h"
45 #include "buffer.h"
46 #include "lanalyzer.h"
47 #include "airopeek9.h"
48 #include "ngsniffer.h"
49 #include "radcom.h"
50 #include "ascendtext.h"
51 #include "nettl.h"
52 #include "libpcap.h"
53 #include "snoop.h"
54 #include "iptrace.h"
55 #include "iseries.h"
56 #include "netmon.h"
57 #include "netxray.h"
58 #include "toshiba.h"
59 #include "eyesdn.h"
60 #include "i4btrace.h"
61 #include "csids.h"
62 #include "pppdump.h"
63 #include "etherpeek.h"
64 #include "vms.h"
65 #include "dbs-etherwatch.h"
66 #include "visual.h"
67 #include "cosine.h"
68 #include "5views.h"
69 #include "erf.h"
70 #include "hcidump.h"
71 #include "network_instruments.h"
72 #include "k12.h"
73 #include "ber.h"
74 #include "catapult_dct2000.h"
75 #include "mpeg.h"
76 #include "netscreen.h"
77 #include "commview.h"
78 #include "pcapng.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
88
89 /* The open_file_* routines should return:
90  *
91  *      -1 on an I/O error;
92  *
93  *      1 if the file they're reading is one of the types it handles;
94  *
95  *      0 if the file they're reading isn't the type they're checking for.
96  *
97  * If the routine handles this type of file, it should set the "file_type"
98  * field in the "struct wtap" to the type of the file.
99  *
100  * Put the trace files that are merely saved telnet-sessions last, since it's
101  * possible that you could have captured someone a router telnet-session
102  * using another tool. So, a libpcap trace of an toshiba "snoop" session
103  * should be discovered as a libpcap file, not a toshiba file.
104  */
105
106
107 static wtap_open_routine_t open_routines_base[] = {
108         /* Files that have magic bytes in fixed locations. These
109          * are easy to identify.
110          */
111         libpcap_open,
112         lanalyzer_open,
113         ngsniffer_open,
114         snoop_open,
115         iptrace_open,
116         netmon_open,
117         netxray_open,
118         radcom_open,
119         nettl_open,
120         visual_open,
121         _5views_open,
122         network_instruments_open,
123         airopeek9_open,
124         dbs_etherwatch_open,
125         k12_open,
126         catapult_dct2000_open,
127         ber_open,
128         pcapng_open,
129         btsnoop_open,
130         packetlogger_open, /* This type does not have a magic number, but its
131                             * files are sometimes grabbed by mpeg_open. */
132         mpeg_open,
133         tnef_open,
134         dct3trace_open,
135         daintree_sna_open,
136         mime_file_open,
137         /* Files that don't have magic bytes at a fixed location,
138          * but that instead require a heuristic of some sort to
139          * identify them.  This includes the ASCII trace files that
140          * would be, for example, saved copies of a Telnet session
141          * to some box.
142          */
143
144         /* I put NetScreen *before* erf, because there were some
145          * false positives with my test-files (Sake Blok, July 2007)
146          */
147         netscreen_open,
148         erf_open,
149         ipfix_open,
150         k12text_open,
151         etherpeek_open,
152         pppdump_open,
153         iseries_open,
154         ascend_open,
155         eyesdn_open,
156         toshiba_open,
157         i4btrace_open,
158         csids_open,
159         vms_open,
160         cosine_open,
161         hcidump_open,
162         commview_open,
163         nstrace_open
164 };
165
166 #define N_FILE_TYPES    (sizeof open_routines_base / sizeof open_routines_base[0])
167
168 static wtap_open_routine_t* open_routines = NULL;
169
170 static GArray* open_routines_arr = NULL;
171
172
173 /* initialize the open routines array if it has not been initialized yet */
174 static void init_open_routines(void) {
175
176         if (open_routines_arr) return;
177
178         open_routines_arr = g_array_new(FALSE,TRUE,sizeof(wtap_open_routine_t));
179
180         g_array_append_vals(open_routines_arr,open_routines_base,N_FILE_TYPES);
181
182         open_routines = (wtap_open_routine_t*)(void *)open_routines_arr->data;
183 }
184
185 void wtap_register_open_routine(wtap_open_routine_t open_routine, gboolean has_magic) {
186         init_open_routines();
187
188         if (has_magic)
189                 g_array_prepend_val(open_routines_arr,open_routine);
190         else
191                 g_array_append_val(open_routines_arr,open_routine);
192
193         open_routines = (wtap_open_routine_t*)(void *)open_routines_arr->data;
194 }
195
196 /*
197  * Visual C++ on Win32 systems doesn't define these.  (Old UNIX systems don't
198  * define them either.)
199  *
200  * Visual C++ on Win32 systems doesn't define S_IFIFO, it defines _S_IFIFO.
201  */
202 #ifndef S_ISREG
203 #define S_ISREG(mode)   (((mode) & S_IFMT) == S_IFREG)
204 #endif
205 #ifndef S_IFIFO
206 #define S_IFIFO _S_IFIFO
207 #endif
208 #ifndef S_ISFIFO
209 #define S_ISFIFO(mode)  (((mode) & S_IFMT) == S_IFIFO)
210 #endif
211 #ifndef S_ISDIR
212 #define S_ISDIR(mode)   (((mode) & S_IFMT) == S_IFDIR)
213 #endif
214
215 /* Opens a file and prepares a wtap struct.
216    If "do_random" is TRUE, it opens the file twice; the second open
217    allows the application to do random-access I/O without moving
218    the seek offset for sequential I/O, which is used by Wireshark
219    so that it can do sequential I/O to a capture file that's being
220    written to as new packets arrive independently of random I/O done
221    to display protocol trees for packets when they're selected. */
222 wtap* wtap_open_offline(const char *filename, int *err, char **err_info,
223                         gboolean do_random)
224 {
225         int     fd;
226         ws_statb64 statb;
227         wtap    *wth;
228         unsigned int    i;
229         gboolean use_stdin = FALSE;
230
231         /* open standard input if filename is '-' */
232         if (strcmp(filename, "-") == 0)
233                 use_stdin = TRUE;
234
235         /* First, make sure the file is valid */
236         if (use_stdin) {
237                 if (ws_fstat64(0, &statb) < 0) {
238                         *err = errno;
239                         return NULL;
240                 }
241         } else {
242                 if (ws_stat64(filename, &statb) < 0) {
243                         *err = errno;
244                         return NULL;
245                 }
246         }
247         if (S_ISFIFO(statb.st_mode)) {
248                 /*
249                  * Opens of FIFOs are allowed only when not opening
250                  * for random access.
251                  *
252                  * XXX - currently, we do seeking when trying to find
253                  * out the file type, so we don't actually support
254                  * opening FIFOs.  However, we may eventually
255                  * do buffering that allows us to do at least some
256                  * file type determination even on pipes, so we
257                  * allow FIFO opens and let things fail later when
258                  * we try to seek.
259                  */
260                 if (do_random) {
261                         *err = WTAP_ERR_RANDOM_OPEN_PIPE;
262                         return NULL;
263                 }
264         } else if (S_ISDIR(statb.st_mode)) {
265                 /*
266                  * Return different errors for "this is a directory"
267                  * and "this is some random special file type", so
268                  * the user can get a potentially more helpful error.
269                  */
270                 *err = EISDIR;
271                 return NULL;
272         } else if (! S_ISREG(statb.st_mode)) {
273                 *err = WTAP_ERR_NOT_REGULAR_FILE;
274                 return NULL;
275         }
276
277         /*
278          * We need two independent descriptors for random access, so
279          * they have different file positions.  If we're opening the
280          * standard input, we can only dup it to get additional
281          * descriptors, so we can't have two independent descriptors,
282          * and thus can't do random access.
283          */
284         if (use_stdin && do_random) {
285                 *err = WTAP_ERR_RANDOM_OPEN_STDIN;
286                 return NULL;
287         }
288
289         errno = ENOMEM;
290         wth = (wtap *)g_malloc0(sizeof(wtap));
291
292         /* Open the file */
293         errno = WTAP_ERR_CANT_OPEN;
294         if (use_stdin) {
295                 /*
296                  * We dup FD 0, so that we don't have to worry about
297                  * a file_close of wth->fh closing the standard
298                  * input of the process.
299                  */
300                 fd = ws_dup(0);
301                 if (fd < 0) {
302                         *err = errno;
303                         g_free(wth);
304                         return NULL;
305                 }
306 #ifdef _WIN32
307                 if (_setmode(fd, O_BINARY) == -1) {
308                         /* "Shouldn't happen" */
309                         *err = errno;
310                         g_free(wth);
311                         return NULL;
312                 }
313 #endif
314                 if (!(wth->fh = filed_open(fd))) {
315                         *err = errno;
316                         ws_close(fd);
317                         g_free(wth);
318                         return NULL;
319                 }
320         } else {
321                 if (!(wth->fh = file_open(filename))) {
322                         *err = errno;
323                         g_free(wth);
324                         return NULL;
325                 }
326         }
327
328         if (do_random) {
329                 if (!(wth->random_fh = file_open(filename))) {
330                         *err = errno;
331                         file_close(wth->fh);
332                         g_free(wth);
333                         return NULL;
334                 }
335         } else
336                 wth->random_fh = NULL;
337
338         /* initialization */
339         wth->file_encap = WTAP_ENCAP_UNKNOWN;
340         wth->data_offset = 0;
341         wth->subtype_sequential_close = NULL;
342         wth->subtype_close = NULL;
343         wth->tsprecision = WTAP_FILE_TSPREC_USEC;
344         wth->priv = NULL;
345
346         init_open_routines();
347         if (wth->random_fh) {
348                 wth->fast_seek = g_ptr_array_new();
349
350                 file_set_random_access(wth->fh, FALSE, wth->fast_seek);
351                 file_set_random_access(wth->random_fh, TRUE, wth->fast_seek);
352         }
353
354         /* Try all file types */
355         for (i = 0; i < open_routines_arr->len; i++) {
356                 /* Seek back to the beginning of the file; the open routine
357                    for the previous file type may have left the file
358                    position somewhere other than the beginning, and the
359                    open routine for this file type will probably want
360                    to start reading at the beginning.
361
362                    Initialize the data offset while we're at it. */
363                 if (file_seek(wth->fh, 0, SEEK_SET, err) == -1) {
364                         /* I/O error - give up */
365                         if (wth->random_fh != NULL)
366                                 file_close(wth->random_fh);
367                         file_close(wth->fh);
368                         g_free(wth);
369                         return NULL;
370                 }
371                 wth->data_offset = 0;
372
373                 switch ((*open_routines[i])(wth, err, err_info)) {
374
375                 case -1:
376                         /* I/O error - give up */
377                         if (wth->random_fh != NULL)
378                                 file_close(wth->random_fh);
379                         file_close(wth->fh);
380                         g_free(wth);
381                         return NULL;
382
383                 case 0:
384                         /* No I/O error, but not that type of file */
385                         break;
386
387                 case 1:
388                         /* We found the file type */
389                         goto success;
390                 }
391         }
392
393         /* Well, it's not one of the types of file we know about. */
394         wtap_close(wth);
395         *err = WTAP_ERR_FILE_UNKNOWN_FORMAT;
396         return NULL;
397
398 success:
399         wth->frame_buffer = (struct Buffer *)g_malloc(sizeof(struct Buffer));
400         buffer_init(wth->frame_buffer, 1500);
401         return wth;
402 }
403
404 /* Table of the file types we know about. */
405 static const struct file_type_info dump_open_table_base[] = {
406         /* WTAP_FILE_UNKNOWN (only used internally for initialization) */
407         { NULL, NULL, NULL, NULL, FALSE, FALSE,
408           NULL, NULL },
409
410         /* WTAP_FILE_WTAP (only used internally while capturing) */
411         { NULL, NULL, NULL, NULL, FALSE, FALSE,
412           NULL, NULL },
413
414         /* WTAP_FILE_PCAP */
415         /* Gianluca Varenni suggests that we add "deprecated" to the description. */
416         { "Wireshark/tcpdump/... - libpcap", "libpcap", "*.pcap;*.cap", ".pcap", FALSE, FALSE,
417           libpcap_dump_can_write_encap, libpcap_dump_open },
418
419         /* WTAP_FILE_PCAP_NSEC */
420         { "Wireshark - nanosecond libpcap", "nseclibpcap", "*.pcap;*.cap", ".pcap", FALSE, FALSE,
421           libpcap_dump_can_write_encap, libpcap_dump_open },
422
423         /* WTAP_FILE_PCAP_AIX */
424         { "AIX tcpdump - libpcap", "aixlibpcap", "*.pcap;*.cap", ".pcap", FALSE, FALSE,
425           NULL, NULL },
426
427         /* WTAP_FILE_PCAP_SS991029 */
428         { "Modified tcpdump - libpcap", "modlibpcap", "*.pcap;*.cap", ".pcap", FALSE, FALSE,
429           libpcap_dump_can_write_encap, libpcap_dump_open },
430
431         /* WTAP_FILE_PCAP_NOKIA */
432         { "Nokia tcpdump - libpcap ", "nokialibpcap", "*.pcap;*.cap", ".pcap", FALSE, FALSE,
433           libpcap_dump_can_write_encap, libpcap_dump_open },
434
435         /* WTAP_FILE_PCAP_SS990417 */
436         { "RedHat 6.1 tcpdump - libpcap", "rh6_1libpcap", "*.pcap;*.cap", ".pcap", FALSE, FALSE,
437           libpcap_dump_can_write_encap, libpcap_dump_open },
438
439         /* WTAP_FILE_PCAP_SS990915 */
440         { "SuSE 6.3 tcpdump - libpcap", "suse6_3libpcap", "*.pcap;*.cap", ".pcap", FALSE, FALSE,
441           libpcap_dump_can_write_encap, libpcap_dump_open },
442
443         /* WTAP_FILE_5VIEWS */
444         { "Accellent 5Views capture", "5views", "*.5vw", ".5vw", TRUE, FALSE,
445           _5views_dump_can_write_encap, _5views_dump_open },
446
447         /* WTAP_FILE_IPTRACE_1_0 */
448         { "AIX iptrace 1.0", "iptrace_1", "*.*", NULL, FALSE, FALSE,
449           NULL, NULL },
450
451         /* WTAP_FILE_IPTRACE_2_0 */
452         { "AIX iptrace 2.0", "iptrace_2", "*.*", NULL, FALSE, FALSE,
453           NULL, NULL },
454
455         /* WTAP_FILE_BER */
456         { "ASN.1 Basic Encoding Rules", "ber", "*.*", NULL, FALSE, FALSE,
457                 NULL, NULL },
458
459         /* WTAP_FILE_HCIDUMP */
460         { "Bluetooth HCI dump", "hcidump", "*.*", NULL, FALSE, FALSE,
461           NULL, NULL },
462
463         /* WTAP_FILE_CATAPULT_DCT2000 */
464         { "Catapult DCT2000 trace (.out format)", "dct2000", "*.out", ".out", FALSE, FALSE,
465           catapult_dct2000_dump_can_write_encap, catapult_dct2000_dump_open },
466
467         /* WTAP_FILE_NETXRAY_OLD */
468         { "Cinco Networks NetXRay 1.x", "netxray1", "*.cap", ".cap", TRUE, FALSE,
469           NULL, NULL },
470
471         /* WTAP_FILE_NETXRAY_1_0 */
472         { "Cinco Networks NetXRay 2.0 or later", "netxray2", "*.cap", ".cap", TRUE, FALSE,
473           NULL, NULL },
474
475         /* WTAP_FILE_COSINE */
476         { "CoSine IPSX L2 capture", "cosine", "*.*", NULL, FALSE, FALSE,
477           NULL, NULL },
478
479         /* WTAP_FILE_CSIDS */
480         { "CSIDS IPLog", "csids", "*.*", NULL, FALSE, FALSE,
481           NULL, NULL },
482
483         /* WTAP_FILE_DBS_ETHERWATCH */
484         { "DBS Etherwatch (VMS)", "etherwatch", "*.*", NULL, FALSE, FALSE,
485           NULL, NULL},
486
487         /* WTAP_FILE_ERF */
488         { "Endace ERF capture", "erf", "*.erf", ".erf", FALSE, FALSE,
489           NULL, NULL },
490
491         /* WTAP_FILE_EYESDN */
492         { "EyeSDN USB S0/E1 ISDN trace format", "eyesdn", "*.trc", ".trc", FALSE, FALSE,
493            eyesdn_dump_can_write_encap, eyesdn_dump_open },
494
495         /* WTAP_FILE_NETTL */
496         { "HP-UX nettl trace", "nettl", "*.TRC0;*.TRC1", ".TRC0", FALSE, FALSE,
497           nettl_dump_can_write_encap, nettl_dump_open },
498
499         /* WTAP_FILE_ISERIES */
500         { "IBM iSeries comm. trace (ASCII)", "iseries_ascii", "*.*", NULL, FALSE, FALSE,
501           NULL, NULL },
502
503         /* WTAP_FILE_ISERIES_UNICODE */
504         { "IBM iSeries comm. trace (UNICODE)", "iseries_unicode", "*.*", NULL, FALSE, FALSE,
505           NULL, NULL },
506
507         /* WTAP_FILE_I4BTRACE */
508         { "I4B ISDN trace", "i4btrace", "*.*", NULL, FALSE, FALSE,
509           NULL, NULL },
510
511         /* WTAP_FILE_ASCEND */
512         { "Lucent/Ascend access server trace", "ascend", "*.*", NULL, FALSE, FALSE,
513           NULL, NULL },
514
515         /* WTAP_FILE_NETMON_1_x */
516         { "Microsoft NetMon 1.x", "netmon1", "*.cap", ".cap", TRUE, FALSE,
517           netmon_dump_can_write_encap, netmon_dump_open },
518
519         /* WTAP_FILE_NETMON_2_x */
520         { "Microsoft NetMon 2.x", "netmon2", "*.cap", ".cap", TRUE, FALSE,
521           netmon_dump_can_write_encap, netmon_dump_open },
522
523         /* WTAP_FILE_NGSNIFFER_UNCOMPRESSED */
524         { "NA Sniffer (DOS)", "ngsniffer", "*.cap;*.enc;*.trc;*.fdc;*.syc", ".cap", FALSE, FALSE,
525           ngsniffer_dump_can_write_encap, ngsniffer_dump_open },
526
527         /* WTAP_FILE_NGSNIFFER_COMPRESSED */
528         { "NA Sniffer (DOS), compressed", "ngsniffer_comp", "*.caz", ".caz", FALSE, FALSE,
529           NULL, NULL },
530
531         /* WTAP_FILE_NETXRAY_1_1 */
532         { "NA Sniffer (Windows) 1.1", "ngwsniffer_1_1", "*.cap", ".cap", TRUE, FALSE,
533           netxray_dump_can_write_encap_1_1, netxray_dump_open_1_1 },
534
535         /* WTAP_FILE_NETXRAY_2_00x */
536         { "NA Sniffer (Windows) 2.00x", "ngwsniffer_2_0", "*.cap", ".cap", TRUE, FALSE,
537           netxray_dump_can_write_encap_2_0, netxray_dump_open_2_0 },
538
539         /* WTAP_FILE_NETWORK_INSTRUMENTS */
540         { "Network Instruments Observer", "niobserverv", "*.bfr", ".bfr", FALSE, FALSE,
541           network_instruments_dump_can_write_encap, network_instruments_dump_open },
542
543         /* WTAP_FILE_LANALYZER */
544         { "Novell LANalyzer","lanalyzer", "*.tr1", ".tr1", TRUE, FALSE,
545           lanalyzer_dump_can_write_encap, lanalyzer_dump_open },
546
547         /* WTAP_FILE_PPPDUMP */
548         { "pppd log (pppdump format)", "pppd", "*.*", NULL, FALSE, FALSE,
549           NULL, NULL },
550
551         /* WTAP_FILE_RADCOM */
552         { "RADCOM WAN/LAN analyzer", "radcom", "*.*", NULL, FALSE, FALSE,
553           NULL, NULL },
554
555         /* WTAP_FILE_SNOOP */
556         { "Sun snoop", "snoop", "*.snoop;*.cap", ".snoop", FALSE, FALSE,
557           snoop_dump_can_write_encap, snoop_dump_open },
558
559         /* WTAP_FILE_SHOMITI */
560         { "Shomiti/Finisar Surveyor", "shomiti", "*.cap", ".cap", FALSE, FALSE,
561           NULL, NULL },
562
563         /* WTAP_FILE_VMS */
564         { "TCPIPtrace (VMS)", "tcpiptrace", "*.*", NULL, FALSE, FALSE,
565           NULL, NULL},
566
567         /* WTAP_FILE_K12 */
568         { "Tektronix K12xx 32-bit .rf5 format", "rf5", "*.rf5", ".rf5", TRUE, FALSE,
569                 k12_dump_can_write_encap, k12_dump_open },
570
571         /* WTAP_FILE_TOSHIBA */
572         { "Toshiba Compact ISDN Router snoop", "toshiba", "*.*", NULL, FALSE, FALSE,
573           NULL, NULL },
574
575         /* WTAP_FILE_VISUAL_NETWORKS */
576         { "Visual Networks traffic capture", "visual", "*.*", NULL, TRUE, FALSE,
577           visual_dump_can_write_encap, visual_dump_open },
578
579         /* WTAP_FILE_ETHERPEEK_V56 */
580         { "WildPackets Ether/TokenPeek (V5 & V6)", "peek56", "*.tpc;*.apc;*.pkt;*.wpz", ".pkt", FALSE, FALSE,
581           NULL, NULL },
582
583         /* WTAP_FILE_ETHERPEEK_V7 */
584         { "WildPackets Ether/Token/AiroPeek (V7)", "peek7", "*.tpc;*.apc;*.pkt;*.wpz", ".pkt", FALSE, FALSE,
585           NULL, NULL },
586
587         /* WTAP_FILE_ETHERPEEK_V9 */
588         { "WildPackets Ether/AiroPeek (V9)", "peek9", "*.tpc;*.apc;*.pkt;*.wpz", ".pkt", FALSE, FALSE,
589           NULL, NULL },
590
591         /* WTAP_FILE_MPEG */
592         { "MPEG", "mpeg", "*.mpeg;*.mpg;*.mp3", ".mpeg", FALSE, FALSE,
593           NULL, NULL },
594
595         /* WTAP_FILE_K12TEXT  */
596         { "K12 text file", "k12text", "*.txt", ".txt", FALSE, FALSE,
597           k12text_dump_can_write_encap, k12text_dump_open },
598
599         /* WTAP_FILE_NETSCREEN */
600         { "NetScreen snoop text file", "netscreen", "*.*", NULL, FALSE, FALSE,
601           NULL, NULL },
602
603         /* WTAP_FILE_COMMVIEW */
604         { "TamoSoft CommView", "commview", "*.ncf", ".ncf", FALSE, FALSE,
605           commview_dump_can_write_encap, commview_dump_open },
606
607         /* WTAP_FILE_PCAPNG */
608         { "Wireshark - pcapng", "pcapng", "*.pcapng", NULL, FALSE, TRUE,
609           pcapng_dump_can_write_encap, pcapng_dump_open },
610
611         /* WTAP_FILE_BTSNOOP */
612         { "Symbian OS btsnoop", "btsnoop", "*.log", ".log", FALSE, FALSE,
613           btsnoop_dump_can_write_encap, btsnoop_dump_open_h4 },
614
615         /* WTAP_FILE_X2E_XORAYA */
616         { NULL, NULL, NULL, NULL, FALSE, FALSE,
617           NULL, NULL },
618
619         /* WTAP_FILE_TNEF */
620         { "Transport-Neutral Encapsulation Format", "tnef", "*.*", NULL, FALSE, FALSE,
621           NULL, NULL },
622
623         /* WTAP_FILE_DCT3TRACE */
624         { "Gammu DCT3 trace", "dct3trace", "*.xml", NULL, FALSE, FALSE,
625           NULL, NULL },
626
627         /* WTAP_FILE_PACKETLOGGER */
628         { "PacketLogger", "pklg", "*.pklg", NULL, FALSE, FALSE,
629           NULL, NULL },
630
631         /* WTAP_FILE_DAINTREE_SNA */
632         { "Daintree SNA", "dsna", "*.dcf", NULL, FALSE, FALSE,
633           NULL, NULL },
634
635         /* WTAP_FILE_NETSCALER_1_0 */
636         { "NetScaler Trace (Version 1.0)", "nstrace10", "*.*", "*.*", TRUE, FALSE,
637           nstrace_10_dump_can_write_encap, nstrace_dump_open },
638
639         /* WTAP_FILE_NETSCALER_2_0 */
640         { "NetScaler Trace (Version 2.0)", "nstrace20", "*.cap", "*.cap", TRUE, FALSE,
641           nstrace_20_dump_can_write_encap, nstrace_dump_open },
642
643         /* WTAP_FILE_JPEG_JFIF */
644         { "JPEG/JFIF", "jpeg", "*.jpg;*.jpeg;*.jfif", ".jpg", FALSE, FALSE,
645           NULL, NULL },
646
647         /* WTAP_FILE_IPFIX */
648         { "IPFIX File Format", "ipfix", "*.pfx;*.ipfix", NULL, FALSE, FALSE,
649           NULL, NULL },
650
651         /* WTAP_ENCAP_MIME */
652         { "MIME File Format", "mime", NULL, NULL, FALSE, FALSE,
653            NULL, NULL }
654 };
655
656 gint wtap_num_file_types = sizeof(dump_open_table_base) / sizeof(struct file_type_info);
657
658 static GArray*  dump_open_table_arr = NULL;
659 static const struct file_type_info* dump_open_table = dump_open_table_base;
660
661 /* initialize the open routines array if it has not being initialized yet */
662 static void init_file_types(void) {
663
664         if (dump_open_table_arr) return;
665
666         dump_open_table_arr = g_array_new(FALSE,TRUE,sizeof(struct file_type_info));
667
668         g_array_append_vals(dump_open_table_arr,dump_open_table_base,wtap_num_file_types);
669
670         dump_open_table = (const struct file_type_info*)(void *)dump_open_table_arr->data;
671 }
672
673 int wtap_register_file_type(const struct file_type_info* fi) {
674         init_file_types();
675
676         g_array_append_val(dump_open_table_arr,*fi);
677
678         dump_open_table = (const struct file_type_info*)(void *)dump_open_table_arr->data;
679
680         return wtap_num_file_types++;
681 }
682
683 int wtap_get_num_file_types(void)
684 {
685         return wtap_num_file_types;
686 }
687
688 /* Name that should be somewhat descriptive. */
689 const char *wtap_file_type_string(int filetype)
690 {
691         if (filetype < 0 || filetype >= wtap_num_file_types) {
692                 g_error("Unknown capture file type %d", filetype);
693                 /** g_error() does an abort() and thus never returns **/
694                 return "";
695         } else
696                 return dump_open_table[filetype].name;
697 }
698
699 /* Name to use in, say, a command-line flag specifying the type. */
700 const char *wtap_file_type_short_string(int filetype)
701 {
702         if (filetype < 0 || filetype >= wtap_num_file_types)
703                 return NULL;
704         else
705                 return dump_open_table[filetype].short_name;
706 }
707
708 /* Translate a short name to a capture file type. */
709 int wtap_short_string_to_file_type(const char *short_name)
710 {
711         int filetype;
712
713         for (filetype = 0; filetype < wtap_num_file_types; filetype++) {
714                 if (dump_open_table[filetype].short_name != NULL &&
715                     strcmp(short_name, dump_open_table[filetype].short_name) == 0)
716                         return filetype;
717         }
718         return -1;      /* no such file type, or we can't write it */
719 }
720
721 /* file extensions to use. */
722 const char *wtap_file_extensions_string(int filetype)
723 {
724         if (filetype < 0 || filetype >= wtap_num_file_types)
725                 return NULL;
726         else
727                 return dump_open_table[filetype].file_extensions;
728 }
729
730 /* default file extension to use. */
731 const char *wtap_file_extension_default_string(int filetype)
732 {
733         if (filetype < 0 || filetype >= wtap_num_file_types)
734                 return NULL;
735         else
736                 return dump_open_table[filetype].file_extension_default;
737 }
738
739 gboolean wtap_dump_can_open(int filetype)
740 {
741         if (filetype < 0 || filetype >= wtap_num_file_types
742             || dump_open_table[filetype].dump_open == NULL)
743                 return FALSE;
744
745         return TRUE;
746 }
747
748 gboolean wtap_dump_can_write_encap(int filetype, int encap)
749 {
750         if (filetype < 0 || filetype >= wtap_num_file_types
751             || dump_open_table[filetype].can_write_encap == NULL)
752                 return FALSE;
753
754         if ((*dump_open_table[filetype].can_write_encap)(encap) != 0)
755                 return FALSE;
756
757         return TRUE;
758 }
759
760 #ifdef HAVE_LIBZ
761 gboolean wtap_dump_can_compress(int filetype)
762 {
763         /*
764          * If this is an unknown file type, or if we have to
765          * seek when writing out a file with this file type,
766          * return FALSE.
767          */
768         if (filetype < 0 || filetype >= wtap_num_file_types
769             || dump_open_table[filetype].writing_must_seek)
770                 return FALSE;
771
772         return TRUE;
773 }
774 #else
775 gboolean wtap_dump_can_compress(int filetype _U_)
776 {
777         return FALSE;
778 }
779 #endif
780
781 gboolean wtap_dump_has_name_resolution(int filetype)
782 {
783         if (filetype < 0 || filetype >= wtap_num_file_types
784             || dump_open_table[filetype].has_name_resolution == FALSE)
785                 return FALSE;
786
787         return TRUE;
788 }
789
790 static gboolean wtap_dump_open_check(int filetype, int encap, gboolean comressed, int *err);
791 static wtap_dumper* wtap_dump_alloc_wdh(int filetype, int encap, int snaplen,
792                                         gboolean compressed, int *err);
793 static gboolean wtap_dump_open_finish(wtap_dumper *wdh, int filetype, gboolean compressed, int *err);
794
795 static WFILE_T wtap_dump_file_open(wtap_dumper *wdh, const char *filename);
796 static WFILE_T wtap_dump_file_fdopen(wtap_dumper *wdh, int fd);
797 static int wtap_dump_file_close(wtap_dumper *wdh);
798
799 wtap_dumper* wtap_dump_open(const char *filename, int filetype, int encap,
800                                 int snaplen, gboolean compressed, int *err)
801 {
802         wtap_dumper *wdh;
803         WFILE_T fh;
804
805         /* Check whether we can open a capture file with that file type
806            and that encapsulation. */
807         if (!wtap_dump_open_check(filetype, encap, compressed, err))
808                 return NULL;
809
810         /* Allocate a data structure for the output stream. */
811         wdh = wtap_dump_alloc_wdh(filetype, encap, snaplen, compressed, err);
812         if (wdh == NULL)
813                 return NULL;    /* couldn't allocate it */
814
815         /* "-" means stdout */
816         if (strcmp(filename, "-") == 0) {
817                 if (compressed) {
818                         *err = EINVAL;  /* XXX - return a Wiretap error code for this */
819                         g_free(wdh);
820                         return NULL;    /* compress won't work on stdout */
821                 }
822 #ifdef _WIN32
823                 if (_setmode(fileno(stdout), O_BINARY) == -1) {
824                         /* "Should not happen" */
825                         *err = errno;
826                         g_free(wdh);
827                         return NULL;    /* couldn't put standard output in binary mode */
828                 }
829 #endif
830                 wdh->fh = stdout;
831         } else {
832                 /* In case "fopen()" fails but doesn't set "errno", set "errno"
833                    to a generic "the open failed" error. */
834                 errno = WTAP_ERR_CANT_OPEN;
835                 fh = wtap_dump_file_open(wdh, filename);
836                 if (fh == NULL) {
837                         *err = errno;
838                         g_free(wdh);
839                         return NULL;    /* can't create file */
840                 }
841                 wdh->fh = fh;
842         }
843
844         if (!wtap_dump_open_finish(wdh, filetype, compressed, err)) {
845                 /* Get rid of the file we created; we couldn't finish
846                    opening it. */
847                 if (wdh->fh != stdout) {
848                         wtap_dump_file_close(wdh);
849                         ws_unlink(filename);
850                 }
851                 g_free(wdh);
852                 return NULL;
853         }
854         return wdh;
855 }
856
857 wtap_dumper* wtap_dump_fdopen(int fd, int filetype, int encap, int snaplen,
858                                 gboolean compressed, int *err)
859 {
860         wtap_dumper *wdh;
861         WFILE_T fh;
862
863         /* Check whether we can open a capture file with that file type
864            and that encapsulation. */
865         if (!wtap_dump_open_check(filetype, encap, compressed, err))
866                 return NULL;
867
868         /* Allocate a data structure for the output stream. */
869         wdh = wtap_dump_alloc_wdh(filetype, encap, snaplen, compressed, err);
870         if (wdh == NULL)
871                 return NULL;    /* couldn't allocate it */
872
873 #ifdef _WIN32
874         if (fd == 1) {
875                 if (_setmode(fileno(stdout), O_BINARY) == -1) {
876                         /* "Should not happen" */
877                         *err = errno;
878                         g_free(wdh);
879                         return NULL;    /* couldn't put standard output in binary mode */
880                 }
881         }
882 #endif
883
884         /* In case "fopen()" fails but doesn't set "errno", set "errno"
885            to a generic "the open failed" error. */
886         errno = WTAP_ERR_CANT_OPEN;
887         fh = wtap_dump_file_fdopen(wdh, fd);
888         if (fh == NULL) {
889                 *err = errno;
890                 g_free(wdh);
891                 return NULL;    /* can't create standard I/O stream */
892         }
893         wdh->fh = fh;
894
895         if (!wtap_dump_open_finish(wdh, filetype, compressed, err)) {
896                 wtap_dump_file_close(wdh);
897                 g_free(wdh);
898                 return NULL;
899         }
900         return wdh;
901 }
902
903 static gboolean wtap_dump_open_check(int filetype, int encap, gboolean compressed, int *err)
904 {
905         if (!wtap_dump_can_open(filetype)) {
906                 /* Invalid type, or type we don't know how to write. */
907                 *err = WTAP_ERR_UNSUPPORTED_FILE_TYPE;
908                 return FALSE;
909         }
910
911         /* OK, we know how to write that type; can we write the specified
912            encapsulation type? */
913         *err = (*dump_open_table[filetype].can_write_encap)(encap);
914         if (*err != 0)
915                 return FALSE;
916
917         /* if compression is wanted, do we support this for this filetype? */
918         if(compressed && !wtap_dump_can_compress(filetype)) {
919                 *err = WTAP_ERR_COMPRESSION_NOT_SUPPORTED;
920                 return FALSE;
921         }
922
923         *err = (*dump_open_table[filetype].can_write_encap)(encap);
924         if (*err != 0)
925                 return FALSE;
926
927         /* All systems go! */
928         return TRUE;
929 }
930
931 static wtap_dumper* wtap_dump_alloc_wdh(int filetype, int encap, int snaplen,
932                                         gboolean compressed, int *err)
933 {
934         wtap_dumper *wdh;
935
936         wdh = (wtap_dumper *)g_malloc0(sizeof (wtap_dumper));
937         if (wdh == NULL) {
938                 *err = errno;
939                 return NULL;
940         }
941
942         wdh->file_type = filetype;
943         wdh->snaplen = snaplen;
944         wdh->encap = encap;
945         wdh->compressed = compressed;
946         return wdh;
947 }
948
949 static gboolean wtap_dump_open_finish(wtap_dumper *wdh, int filetype, gboolean compressed, int *err)
950 {
951         int fd;
952         gboolean cant_seek;
953
954         /* Can we do a seek on the file descriptor?
955            If not, note that fact. */
956         if(compressed) {
957                 cant_seek = TRUE;
958         } else {
959                 fd = fileno((FILE *)wdh->fh);
960                 if (lseek(fd, 1, SEEK_CUR) == -1)
961                         cant_seek = TRUE;
962                 else {
963                         /* Undo the seek. */
964                         lseek(fd, 0, SEEK_SET);
965                         cant_seek = FALSE;
966                 }
967         }
968
969         /* If this file type requires seeking, and we can't seek, fail. */
970         if (dump_open_table[filetype].writing_must_seek && cant_seek) {
971                 *err = WTAP_ERR_CANT_WRITE_TO_PIPE;
972                 return FALSE;
973         }
974
975         /* Now try to open the file for writing. */
976         if (!(*dump_open_table[filetype].dump_open)(wdh, err)) {
977                 return FALSE;
978         }
979
980         return TRUE;    /* success! */
981 }
982
983 gboolean wtap_dump(wtap_dumper *wdh, const struct wtap_pkthdr *phdr,
984                    const union wtap_pseudo_header *pseudo_header, const guchar *pd, int *err)
985 {
986         return (wdh->subtype_write)(wdh, phdr, pseudo_header, pd, err);
987 }
988
989 void wtap_dump_flush(wtap_dumper *wdh)
990 {
991 #ifdef HAVE_LIBZ
992         if(wdh->compressed) {
993                 gzwfile_flush((GZWFILE_T)wdh->fh);
994         } else
995 #endif
996         {
997                 fflush((FILE *)wdh->fh);
998         }
999 }
1000
1001 gboolean wtap_dump_close(wtap_dumper *wdh, int *err)
1002 {
1003         gboolean ret = TRUE;
1004
1005         if (wdh->subtype_close != NULL) {
1006                 /* There's a close routine for this dump stream. */
1007                 if (!(wdh->subtype_close)(wdh, err))
1008                         ret = FALSE;
1009         }
1010         errno = WTAP_ERR_CANT_CLOSE;
1011         /* Don't close stdout */
1012         if (wdh->fh != stdout) {
1013                 if (wtap_dump_file_close(wdh) == EOF) {
1014                         if (ret) {
1015                                 /* The per-format close function succeeded,
1016                                    but the fclose didn't.  Save the reason
1017                                    why, if our caller asked for it. */
1018                                 if (err != NULL)
1019                                         *err = errno;
1020                         }
1021                         ret = FALSE;
1022                 }
1023         } else {
1024                 /* as we don't close stdout, at least try to flush it */
1025                 wtap_dump_flush(wdh);
1026         }
1027         if (wdh->priv != NULL)
1028                 g_free(wdh->priv);
1029         g_free(wdh);
1030         return ret;
1031 }
1032
1033 gint64 wtap_get_bytes_dumped(wtap_dumper *wdh)
1034 {
1035         return wdh->bytes_dumped;
1036 }
1037
1038 void wtap_set_bytes_dumped(wtap_dumper *wdh, gint64 bytes_dumped)
1039 {
1040         wdh->bytes_dumped = bytes_dumped;
1041 }
1042
1043 gboolean wtap_dump_set_addrinfo_list(wtap_dumper *wdh, struct addrinfo *addrinfo_list)
1044 {
1045         if (!wdh || wdh->file_type < 0 || wdh->file_type >= wtap_num_file_types
1046                 || dump_open_table[wdh->file_type].has_name_resolution == FALSE)
1047                         return FALSE;
1048         wdh->addrinfo_list = addrinfo_list;
1049         return TRUE;
1050 }
1051
1052 /* internally open a file for writing (compressed or not) */
1053 #ifdef HAVE_LIBZ
1054 static WFILE_T wtap_dump_file_open(wtap_dumper *wdh, const char *filename)
1055 {
1056         if(wdh->compressed) {
1057                 return gzwfile_open(filename);
1058         } else {
1059                 return ws_fopen(filename, "wb");
1060         }
1061 }
1062 #else
1063 static WFILE_T wtap_dump_file_open(wtap_dumper *wdh _U_, const char *filename)
1064 {
1065         return ws_fopen(filename, "wb");
1066 }
1067 #endif
1068
1069 /* internally open a file for writing (compressed or not) */
1070 #ifdef HAVE_LIBZ
1071 static WFILE_T wtap_dump_file_fdopen(wtap_dumper *wdh, int fd)
1072 {
1073         if(wdh->compressed) {
1074                 return gzwfile_fdopen(fd);
1075         } else {
1076                 return fdopen(fd, "wb");
1077         }
1078 }
1079 #else
1080 static WFILE_T wtap_dump_file_fdopen(wtap_dumper *wdh _U_, int fd)
1081 {
1082         return fdopen(fd, "wb");
1083 }
1084 #endif
1085
1086 /* internally writing raw bytes (compressed or not) */
1087 gboolean wtap_dump_file_write(wtap_dumper *wdh, const void *buf, size_t bufsize,
1088                      int *err)
1089 {
1090         size_t nwritten;
1091
1092 #ifdef HAVE_LIBZ
1093         if (wdh->compressed) {
1094                 nwritten = gzwfile_write((GZWFILE_T)wdh->fh, buf, (unsigned) bufsize);
1095                 /*
1096                  * gzwfile_write() returns 0 on error.
1097                  */
1098                 if (nwritten == 0) {
1099                         *err = gzwfile_geterr((GZWFILE_T)wdh->fh);
1100                         return FALSE;
1101                 }
1102         } else
1103 #endif
1104         {
1105                 nwritten = fwrite(buf, 1, bufsize, (FILE *)wdh->fh);
1106                 /*
1107                  * At least according to the Mac OS X man page,
1108                  * this can return a short count on an error.
1109                  */
1110                 if (nwritten != bufsize) {
1111                         if (ferror((FILE *)wdh->fh))
1112                                 *err = errno;
1113                         else
1114                                 *err = WTAP_ERR_SHORT_WRITE;
1115                         return FALSE;
1116                 }
1117         }
1118         return TRUE;
1119 }
1120
1121 /* internally close a file for writing (compressed or not) */
1122 static int wtap_dump_file_close(wtap_dumper *wdh)
1123 {
1124 #ifdef HAVE_LIBZ
1125         if(wdh->compressed) {
1126                 return gzwfile_close((GZWFILE_T)wdh->fh);
1127         } else
1128 #endif
1129         {
1130                 return fclose((FILE *)wdh->fh);
1131         }
1132 }