In a dump_open routine, you don't need to seek to the beginning of the
[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 "jpeg_jfif.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         jpeg_jfif_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         ws_statb64 statb;
226         wtap    *wth;
227         unsigned int    i;
228         gboolean use_stdin = FALSE;
229
230         /* open standard input if filename is '-' */
231         if (strcmp(filename, "-") == 0)
232                 use_stdin = TRUE;
233
234         /* First, make sure the file is valid */
235         if (use_stdin) {
236                 if (ws_fstat64(0, &statb) < 0) {
237                         *err = errno;
238                         return NULL;
239                 }
240         } else {
241                 if (ws_stat64(filename, &statb) < 0) {
242                         *err = errno;
243                         return NULL;
244                 }
245         }
246         if (S_ISFIFO(statb.st_mode)) {
247                 /*
248                  * Opens of FIFOs are allowed only when not opening
249                  * for random access.
250                  *
251                  * XXX - currently, we do seeking when trying to find
252                  * out the file type, so we don't actually support
253                  * opening FIFOs.  However, we may eventually
254                  * do buffering that allows us to do at least some
255                  * file type determination even on pipes, so we
256                  * allow FIFO opens and let things fail later when
257                  * we try to seek.
258                  */
259                 if (do_random) {
260                         *err = WTAP_ERR_RANDOM_OPEN_PIPE;
261                         return NULL;
262                 }
263         } else if (S_ISDIR(statb.st_mode)) {
264                 /*
265                  * Return different errors for "this is a directory"
266                  * and "this is some random special file type", so
267                  * the user can get a potentially more helpful error.
268                  */
269                 *err = EISDIR;
270                 return NULL;
271         } else if (! S_ISREG(statb.st_mode)) {
272                 *err = WTAP_ERR_NOT_REGULAR_FILE;
273                 return NULL;
274         }
275
276         /*
277          * We need two independent descriptors for random access, so
278          * they have different file positions.  If we're opening the
279          * standard input, we can only dup it to get additional
280          * descriptors, so we can't have two independent descriptors,
281          * and thus can't do random access.
282          */
283         if (use_stdin && do_random) {
284                 *err = WTAP_ERR_RANDOM_OPEN_STDIN;
285                 return NULL;
286         }
287
288         errno = ENOMEM;
289         wth = (wtap *)g_malloc0(sizeof(wtap));
290
291         /* Open the file */
292         errno = WTAP_ERR_CANT_OPEN;
293         if (use_stdin) {
294                 /*
295                  * We dup FD 0, so that we don't have to worry about
296                  * an fclose or gzclose of wth->fh closing the standard
297                  * input of the process.
298                  */
299                 wth->fd = ws_dup(0);
300                 if (wth->fd < 0) {
301                         *err = errno;
302                         g_free(wth);
303                         return NULL;
304                 }
305 #ifdef _WIN32
306                 if (_setmode(wth->fd, O_BINARY) == -1) {
307                         /* "Shouldn't happen" */
308                         *err = errno;
309                         g_free(wth);
310                         return NULL;
311                 }
312 #endif
313         } else {
314                 wth->fd = ws_open(filename, O_RDONLY|O_BINARY, 0000 /* no creation so don't matter */);
315                 if (wth->fd < 0) {
316                         *err = errno;
317                         g_free(wth);
318                         return NULL;
319                 }
320         }
321         if (!(wth->fh = filed_open(wth->fd))) {
322                 *err = errno;
323                 ws_close(wth->fd);
324                 g_free(wth);
325                 return NULL;
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         { "Wireshark/tcpdump/... - libpcap", "libpcap", "*.pcap;*.cap", ".pcap", FALSE, FALSE,
416           libpcap_dump_can_write_encap, libpcap_dump_open },
417
418         /* WTAP_FILE_PCAP_NSEC */
419         { "Wireshark - nanosecond libpcap", "nseclibpcap", "*.pcap;*.cap", ".pcap", FALSE, FALSE,
420           libpcap_dump_can_write_encap, libpcap_dump_open },
421
422         /* WTAP_FILE_PCAP_AIX */
423         { "AIX tcpdump - libpcap", "aixlibpcap", "*.pcap;*.cap", ".pcap", FALSE, FALSE,
424           NULL, NULL },
425
426         /* WTAP_FILE_PCAP_SS991029 */
427         { "Modified tcpdump - libpcap", "modlibpcap", "*.pcap;*.cap", ".pcap", FALSE, FALSE,
428           libpcap_dump_can_write_encap, libpcap_dump_open },
429
430         /* WTAP_FILE_PCAP_NOKIA */
431         { "Nokia tcpdump - libpcap ", "nokialibpcap", "*.pcap;*.cap", ".pcap", FALSE, FALSE,
432           libpcap_dump_can_write_encap, libpcap_dump_open },
433
434         /* WTAP_FILE_PCAP_SS990417 */
435         { "RedHat 6.1 tcpdump - libpcap", "rh6_1libpcap", "*.pcap;*.cap", ".pcap", FALSE, FALSE,
436           libpcap_dump_can_write_encap, libpcap_dump_open },
437
438         /* WTAP_FILE_PCAP_SS990915 */
439         { "SuSE 6.3 tcpdump - libpcap", "suse6_3libpcap", "*.pcap;*.cap", ".pcap", FALSE, FALSE,
440           libpcap_dump_can_write_encap, libpcap_dump_open },
441
442         /* WTAP_FILE_5VIEWS */
443         { "Accellent 5Views capture", "5views", "*.5vw", ".5vw", TRUE, FALSE,
444           _5views_dump_can_write_encap, _5views_dump_open },
445
446         /* WTAP_FILE_IPTRACE_1_0 */
447         { "AIX iptrace 1.0", "iptrace_1", "*.*", NULL, FALSE, FALSE,
448           NULL, NULL },
449
450         /* WTAP_FILE_IPTRACE_2_0 */
451         { "AIX iptrace 2.0", "iptrace_2", "*.*", NULL, FALSE, FALSE,
452           NULL, NULL },
453
454         /* WTAP_FILE_BER */
455         { "ASN.1 Basic Encoding Rules", "ber", "*.*", NULL, FALSE, FALSE,
456                 NULL, NULL },
457
458         /* WTAP_FILE_HCIDUMP */
459         { "Bluetooth HCI dump", "hcidump", "*.*", NULL, FALSE, FALSE,
460           NULL, NULL },
461
462         /* WTAP_FILE_CATAPULT_DCT2000 */
463         { "Catapult DCT2000 trace (.out format)", "dct2000", "*.out", ".out", FALSE, FALSE,
464           catapult_dct2000_dump_can_write_encap, catapult_dct2000_dump_open },
465
466         /* WTAP_FILE_NETXRAY_OLD */
467         { "Cinco Networks NetXRay 1.x", "netxray1", "*.cap", ".cap", TRUE, FALSE,
468           NULL, NULL },
469
470         /* WTAP_FILE_NETXRAY_1_0 */
471         { "Cinco Networks NetXRay 2.0 or later", "netxray2", "*.cap", ".cap", TRUE, FALSE,
472           NULL, NULL },
473
474         /* WTAP_FILE_COSINE */
475         { "CoSine IPSX L2 capture", "cosine", "*.*", NULL, FALSE, FALSE,
476           NULL, NULL },
477
478         /* WTAP_FILE_CSIDS */
479         { "CSIDS IPLog", "csids", "*.*", NULL, FALSE, FALSE,
480           NULL, NULL },
481
482         /* WTAP_FILE_DBS_ETHERWATCH */
483         { "DBS Etherwatch (VMS)", "etherwatch", "*.*", NULL, FALSE, FALSE,
484           NULL, NULL},
485
486         /* WTAP_FILE_ERF */
487         { "Endace ERF capture", "erf", "*.erf", ".erf", FALSE, FALSE,
488           NULL, NULL },
489
490         /* WTAP_FILE_EYESDN */
491         { "EyeSDN USB S0/E1 ISDN trace format", "eyesdn", "*.trc", ".trc", FALSE, FALSE,
492            eyesdn_dump_can_write_encap, eyesdn_dump_open },
493
494         /* WTAP_FILE_NETTL */
495         { "HP-UX nettl trace", "nettl", "*.TRC0;*.TRC1", ".TRC0", FALSE, FALSE,
496           nettl_dump_can_write_encap, nettl_dump_open },
497
498         /* WTAP_FILE_ISERIES */
499         { "IBM iSeries comm. trace (ASCII)", "iseries_ascii", "*.*", NULL, FALSE, FALSE,
500           NULL, NULL },
501
502         /* WTAP_FILE_ISERIES_UNICODE */
503         { "IBM iSeries comm. trace (UNICODE)", "iseries_unicode", "*.*", NULL, FALSE, FALSE,
504           NULL, NULL },
505
506         /* WTAP_FILE_I4BTRACE */
507         { "I4B ISDN trace", "i4btrace", "*.*", NULL, FALSE, FALSE,
508           NULL, NULL },
509
510         /* WTAP_FILE_ASCEND */
511         { "Lucent/Ascend access server trace", "ascend", "*.*", NULL, FALSE, FALSE,
512           NULL, NULL },
513
514         /* WTAP_FILE_NETMON_1_x */
515         { "Microsoft NetMon 1.x", "netmon1", "*.cap", ".cap", TRUE, FALSE,
516           netmon_dump_can_write_encap, netmon_dump_open },
517
518         /* WTAP_FILE_NETMON_2_x */
519         { "Microsoft NetMon 2.x", "netmon2", "*.cap", ".cap", TRUE, FALSE,
520           netmon_dump_can_write_encap, netmon_dump_open },
521
522         /* WTAP_FILE_NGSNIFFER_UNCOMPRESSED */
523         { "NA Sniffer (DOS)", "ngsniffer", "*.cap;*.enc;*.trc;*.fdc;*.syc", ".cap", FALSE, FALSE,
524           ngsniffer_dump_can_write_encap, ngsniffer_dump_open },
525
526         /* WTAP_FILE_NGSNIFFER_COMPRESSED */
527         { "NA Sniffer (DOS), compressed", "ngsniffer_comp", "*.caz", ".caz", FALSE, FALSE,
528           NULL, NULL },
529
530         /* WTAP_FILE_NETXRAY_1_1 */
531         { "NA Sniffer (Windows) 1.1", "ngwsniffer_1_1", "*.cap", ".cap", TRUE, FALSE,
532           netxray_dump_can_write_encap_1_1, netxray_dump_open_1_1 },
533
534         /* WTAP_FILE_NETXRAY_2_00x */
535         { "NA Sniffer (Windows) 2.00x", "ngwsniffer_2_0", "*.cap", ".cap", TRUE, FALSE,
536           netxray_dump_can_write_encap_2_0, netxray_dump_open_2_0 },
537
538         /* WTAP_FILE_NETWORK_INSTRUMENTS_V9 */
539         { "Network Instruments Observer (V9)", "niobserverv9", "*.bfr", ".bfr", FALSE, FALSE,
540           network_instruments_dump_can_write_encap, network_instruments_dump_open },
541
542         /* WTAP_FILE_LANALYZER */
543         { "Novell LANalyzer","lanalyzer", "*.tr1", ".tr1", TRUE, FALSE,
544           lanalyzer_dump_can_write_encap, lanalyzer_dump_open },
545
546         /* WTAP_FILE_PPPDUMP */
547         { "pppd log (pppdump format)", "pppd", "*.*", NULL, FALSE, FALSE,
548           NULL, NULL },
549
550         /* WTAP_FILE_RADCOM */
551         { "RADCOM WAN/LAN analyzer", "radcom", "*.*", NULL, FALSE, FALSE,
552           NULL, NULL },
553
554         /* WTAP_FILE_SNOOP */
555         { "Sun snoop", "snoop", "*.snoop;*.cap", ".snoop", FALSE, FALSE,
556           snoop_dump_can_write_encap, snoop_dump_open },
557
558         /* WTAP_FILE_SHOMITI */
559         { "Shomiti/Finisar Surveyor", "shomiti", "*.cap", ".cap", FALSE, FALSE,
560           NULL, NULL },
561
562         /* WTAP_FILE_VMS */
563         { "TCPIPtrace (VMS)", "tcpiptrace", "*.*", NULL, FALSE, FALSE,
564           NULL, NULL},
565
566         /* WTAP_FILE_K12 */
567         { "Tektronix K12xx 32-bit .rf5 format", "rf5", "*.rf5", ".rf5", TRUE, FALSE,
568                 k12_dump_can_write_encap, k12_dump_open },
569
570         /* WTAP_FILE_TOSHIBA */
571         { "Toshiba Compact ISDN Router snoop", "toshiba", "*.*", NULL, FALSE, FALSE,
572           NULL, NULL },
573
574         /* WTAP_FILE_VISUAL_NETWORKS */
575         { "Visual Networks traffic capture", "visual", "*.*", NULL, TRUE, FALSE,
576           visual_dump_can_write_encap, visual_dump_open },
577
578         /* WTAP_FILE_ETHERPEEK_V56 */
579         { "WildPackets Ether/TokenPeek (V5 & V6)", "peek56", "*.tpc;*.apc;*.pkt;*.wpz", ".pkt", FALSE, FALSE,
580           NULL, NULL },
581
582         /* WTAP_FILE_ETHERPEEK_V7 */
583         { "WildPackets Ether/Token/AiroPeek (V7)", "peek7", "*.tpc;*.apc;*.pkt;*.wpz", ".pkt", FALSE, FALSE,
584           NULL, NULL },
585
586         /* WTAP_FILE_ETHERPEEK_V9 */
587         { "WildPackets Ether/AiroPeek (V9)", "peek9", "*.tpc;*.apc;*.pkt;*.wpz", ".pkt", FALSE, FALSE,
588           NULL, NULL },
589
590         /* WTAP_FILE_MPEG */
591         { "MPEG", "mpeg", "*.mpeg;*.mpg;*.mp3", ".mpeg", FALSE, FALSE,
592           NULL, NULL },
593
594         /* WTAP_FILE_K12TEXT  */
595         { "K12 text file", "k12text", "*.txt", ".txt", FALSE, FALSE,
596           k12text_dump_can_write_encap, k12text_dump_open },
597
598         /* WTAP_FILE_NETSCREEN */
599         { "NetScreen snoop text file", "netscreen", "*.*", NULL, FALSE, FALSE,
600           NULL, NULL },
601
602         /* WTAP_FILE_COMMVIEW */
603         { "TamoSoft CommView", "commview", "*.ncf", ".ncf", FALSE, FALSE,
604           commview_dump_can_write_encap, commview_dump_open },
605
606         /* WTAP_FILE_PCAPNG */
607         { "Wireshark - pcapng", "pcapng", "*.pcapng", NULL, FALSE, TRUE,
608           pcapng_dump_can_write_encap, pcapng_dump_open },
609
610         /* WTAP_FILE_BTSNOOP */
611         { "Symbian OS btsnoop", "btsnoop", "*.log", ".log", FALSE, FALSE,
612           btsnoop_dump_can_write_encap, btsnoop_dump_open_h4 },
613
614         /* WTAP_FILE_X2E_XORAYA */
615         { NULL, NULL, NULL, NULL, FALSE, FALSE,
616           NULL, NULL },
617
618         /* WTAP_FILE_TNEF */
619         { "Transport-Neutral Encapsulation Format", "tnef", "*.*", NULL, FALSE, FALSE,
620           NULL, NULL },
621
622         /* WTAP_FILE_DCT3TRACE */
623         { "Gammu DCT3 trace", "dct3trace", "*.xml", NULL, FALSE, FALSE,
624           NULL, NULL },
625
626         /* WTAP_FILE_PACKETLOGGER */
627         { "PacketLogger", "pklg", "*.pklg", NULL, FALSE, FALSE,
628           NULL, NULL },
629
630         /* WTAP_FILE_DAINTREE_SNA */
631         { "Daintree SNA", "dsna", "*.dcf", NULL, FALSE, FALSE,
632           NULL, NULL },
633
634         /* WTAP_FILE_NETSCALER_1_0 */
635         { "NetScaler Trace (Version 1.0)", "nstrace10", "*.*", "*.*", TRUE, FALSE,
636           nstrace_10_dump_can_write_encap, nstrace_dump_open },
637
638         /* WTAP_FILE_NETSCALER_2_0 */
639         { "NetScaler Trace (Version 2.0)", "nstrace20", "*.cap", "*.cap", TRUE, FALSE,
640           nstrace_20_dump_can_write_encap, nstrace_dump_open },
641
642         /* WTAP_FILE_JPEG_JFIF */
643         { "JPEG/JFIF", "jpeg", "*.jpg;*.jpeg;*.jfif", ".jpg", FALSE, FALSE,
644           NULL, NULL },
645
646         /* WTAP_FILE_IPFIX */
647         { "IPFIX File Format", "ipfix", "*.pfx;*.ipfix", NULL, FALSE, FALSE,
648           NULL, NULL }
649 };
650
651 gint wtap_num_file_types = sizeof(dump_open_table_base) / sizeof(struct file_type_info);
652
653 static GArray*  dump_open_table_arr = NULL;
654 static const struct file_type_info* dump_open_table = dump_open_table_base;
655
656 /* initialize the open routines array if it has not being initialized yet */
657 static void init_file_types(void) {
658
659         if (dump_open_table_arr) return;
660
661         dump_open_table_arr = g_array_new(FALSE,TRUE,sizeof(struct file_type_info));
662
663         g_array_append_vals(dump_open_table_arr,dump_open_table_base,wtap_num_file_types);
664
665         dump_open_table = (const struct file_type_info*)(void *)dump_open_table_arr->data;
666 }
667
668 int wtap_register_file_type(const struct file_type_info* fi) {
669         init_file_types();
670
671         g_array_append_val(dump_open_table_arr,*fi);
672
673         dump_open_table = (const struct file_type_info*)(void *)dump_open_table_arr->data;
674
675         return wtap_num_file_types++;
676 }
677
678 int wtap_get_num_file_types(void)
679 {
680         return wtap_num_file_types;
681 }
682
683 /* Name that should be somewhat descriptive. */
684 const char *wtap_file_type_string(int filetype)
685 {
686         if (filetype < 0 || filetype >= wtap_num_file_types) {
687                 g_error("Unknown capture file type %d", filetype);
688                 /** g_error() does an abort() and thus never returns **/
689                 return "";
690         } else
691                 return dump_open_table[filetype].name;
692 }
693
694 /* Name to use in, say, a command-line flag specifying the type. */
695 const char *wtap_file_type_short_string(int filetype)
696 {
697         if (filetype < 0 || filetype >= wtap_num_file_types)
698                 return NULL;
699         else
700                 return dump_open_table[filetype].short_name;
701 }
702
703 /* Translate a short name to a capture file type. */
704 int wtap_short_string_to_file_type(const char *short_name)
705 {
706         int filetype;
707
708         for (filetype = 0; filetype < wtap_num_file_types; filetype++) {
709                 if (dump_open_table[filetype].short_name != NULL &&
710                     strcmp(short_name, dump_open_table[filetype].short_name) == 0)
711                         return filetype;
712         }
713         return -1;      /* no such file type, or we can't write it */
714 }
715
716 /* file extensions to use. */
717 const char *wtap_file_extensions_string(int filetype)
718 {
719         if (filetype < 0 || filetype >= wtap_num_file_types)
720                 return NULL;
721         else
722                 return dump_open_table[filetype].file_extensions;
723 }
724
725 /* default file extension to use. */
726 const char *wtap_file_extension_default_string(int filetype)
727 {
728         if (filetype < 0 || filetype >= wtap_num_file_types)
729                 return NULL;
730         else
731                 return dump_open_table[filetype].file_extension_default;
732 }
733
734 gboolean wtap_dump_can_open(int filetype)
735 {
736         if (filetype < 0 || filetype >= wtap_num_file_types
737             || dump_open_table[filetype].dump_open == NULL)
738                 return FALSE;
739
740         return TRUE;
741 }
742
743 gboolean wtap_dump_can_write_encap(int filetype, int encap)
744 {
745         if (filetype < 0 || filetype >= wtap_num_file_types
746             || dump_open_table[filetype].can_write_encap == NULL)
747                 return FALSE;
748
749         if ((*dump_open_table[filetype].can_write_encap)(encap) != 0)
750                 return FALSE;
751
752         return TRUE;
753 }
754
755 #ifdef HAVE_LIBZ
756 gboolean wtap_dump_can_compress(int filetype)
757 {
758         /*
759          * If this is an unknown file type, or if we have to
760          * seek when writing out a file with this file type,
761          * return FALSE.
762          */
763         if (filetype < 0 || filetype >= wtap_num_file_types
764             || dump_open_table[filetype].writing_must_seek)
765                 return FALSE;
766
767         return TRUE;
768 }
769 #else
770 gboolean wtap_dump_can_compress(int filetype _U_)
771 {
772         return FALSE;
773 }
774 #endif
775
776 gboolean wtap_dump_has_name_resolution(int filetype)
777 {
778         if (filetype < 0 || filetype >= wtap_num_file_types
779             || dump_open_table[filetype].has_name_resolution == FALSE)
780                 return FALSE;
781
782         return TRUE;
783 }
784
785 static gboolean wtap_dump_open_check(int filetype, int encap, gboolean comressed, int *err);
786 static wtap_dumper* wtap_dump_alloc_wdh(int filetype, int encap, int snaplen,
787                                         gboolean compressed, int *err);
788 static gboolean wtap_dump_open_finish(wtap_dumper *wdh, int filetype, gboolean compressed, int *err);
789
790 static WFILE_T wtap_dump_file_open(wtap_dumper *wdh, const char *filename);
791 static WFILE_T wtap_dump_file_fdopen(wtap_dumper *wdh, int fd);
792 static int wtap_dump_file_close(wtap_dumper *wdh);
793
794 wtap_dumper* wtap_dump_open(const char *filename, int filetype, int encap,
795                                 int snaplen, gboolean compressed, int *err)
796 {
797         wtap_dumper *wdh;
798         WFILE_T fh;
799
800         /* Check whether we can open a capture file with that file type
801            and that encapsulation. */
802         if (!wtap_dump_open_check(filetype, encap, compressed, err))
803                 return NULL;
804
805         /* Allocate a data structure for the output stream. */
806         wdh = wtap_dump_alloc_wdh(filetype, encap, snaplen, compressed, err);
807         if (wdh == NULL)
808                 return NULL;    /* couldn't allocate it */
809
810         /* "-" means stdout */
811         if (strcmp(filename, "-") == 0) {
812                 if (compressed) {
813                         *err = EINVAL;  /* XXX - return a Wiretap error code for this */
814                         g_free(wdh);
815                         return NULL;    /* compress won't work on stdout */
816                 }
817 #ifdef _WIN32
818                 if (_setmode(fileno(stdout), O_BINARY) == -1) {
819                         /* "Should not happen" */
820                         *err = errno;
821                         g_free(wdh);
822                         return NULL;    /* couldn't put standard output in binary mode */
823                 }
824 #endif
825                 wdh->fh = stdout;
826         } else {
827                 /* In case "fopen()" fails but doesn't set "errno", set "errno"
828                    to a generic "the open failed" error. */
829                 errno = WTAP_ERR_CANT_OPEN;
830                 fh = wtap_dump_file_open(wdh, filename);
831                 if (fh == NULL) {
832                         *err = errno;
833                         g_free(wdh);
834                         return NULL;    /* can't create file */
835                 }
836                 wdh->fh = fh;
837         }
838
839         if (!wtap_dump_open_finish(wdh, filetype, compressed, err)) {
840                 /* Get rid of the file we created; we couldn't finish
841                    opening it. */
842                 if (wdh->fh != stdout) {
843                         wtap_dump_file_close(wdh);
844                         ws_unlink(filename);
845                 }
846                 g_free(wdh);
847                 return NULL;
848         }
849         return wdh;
850 }
851
852 wtap_dumper* wtap_dump_fdopen(int fd, int filetype, int encap, int snaplen,
853                                 gboolean compressed, int *err)
854 {
855         wtap_dumper *wdh;
856         WFILE_T fh;
857
858         /* Check whether we can open a capture file with that file type
859            and that encapsulation. */
860         if (!wtap_dump_open_check(filetype, encap, compressed, err))
861                 return NULL;
862
863         /* Allocate a data structure for the output stream. */
864         wdh = wtap_dump_alloc_wdh(filetype, encap, snaplen, compressed, err);
865         if (wdh == NULL)
866                 return NULL;    /* couldn't allocate it */
867
868 #ifdef _WIN32
869         if (fd == 1) {
870                 if (_setmode(fileno(stdout), O_BINARY) == -1) {
871                         /* "Should not happen" */
872                         *err = errno;
873                         g_free(wdh);
874                         return NULL;    /* couldn't put standard output in binary mode */
875                 }
876         }
877 #endif
878
879         /* In case "fopen()" fails but doesn't set "errno", set "errno"
880            to a generic "the open failed" error. */
881         errno = WTAP_ERR_CANT_OPEN;
882         fh = wtap_dump_file_fdopen(wdh, fd);
883         if (fh == NULL) {
884                 *err = errno;
885                 g_free(wdh);
886                 return NULL;    /* can't create standard I/O stream */
887         }
888         wdh->fh = fh;
889
890         if (!wtap_dump_open_finish(wdh, filetype, compressed, err)) {
891                 wtap_dump_file_close(wdh);
892                 g_free(wdh);
893                 return NULL;
894         }
895         return wdh;
896 }
897
898 static gboolean wtap_dump_open_check(int filetype, int encap, gboolean compressed, int *err)
899 {
900         if (!wtap_dump_can_open(filetype)) {
901                 /* Invalid type, or type we don't know how to write. */
902                 *err = WTAP_ERR_UNSUPPORTED_FILE_TYPE;
903                 return FALSE;
904         }
905
906         /* OK, we know how to write that type; can we write the specified
907            encapsulation type? */
908         *err = (*dump_open_table[filetype].can_write_encap)(encap);
909         if (*err != 0)
910                 return FALSE;
911
912         /* if compression is wanted, do we support this for this filetype? */
913         if(compressed && !wtap_dump_can_compress(filetype)) {
914                 *err = WTAP_ERR_COMPRESSION_NOT_SUPPORTED;
915                 return FALSE;
916         }
917
918         *err = (*dump_open_table[filetype].can_write_encap)(encap);
919         if (*err != 0)
920                 return FALSE;
921
922         /* All systems go! */
923         return TRUE;
924 }
925
926 static wtap_dumper* wtap_dump_alloc_wdh(int filetype, int encap, int snaplen,
927                                         gboolean compressed, int *err)
928 {
929         wtap_dumper *wdh;
930
931         wdh = (wtap_dumper *)g_malloc0(sizeof (wtap_dumper));
932         if (wdh == NULL) {
933                 *err = errno;
934                 return NULL;
935         }
936
937         wdh->file_type = filetype;
938         wdh->snaplen = snaplen;
939         wdh->encap = encap;
940         wdh->compressed = compressed;
941         return wdh;
942 }
943
944 static gboolean wtap_dump_open_finish(wtap_dumper *wdh, int filetype, gboolean compressed, int *err)
945 {
946         int fd;
947         gboolean cant_seek;
948
949         /* Can we do a seek on the file descriptor?
950            If not, note that fact. */
951         if(compressed) {
952                 cant_seek = TRUE;
953         } else {
954                 fd = fileno((FILE *)wdh->fh);
955                 if (lseek(fd, 1, SEEK_CUR) == -1)
956                         cant_seek = TRUE;
957                 else {
958                         /* Undo the seek. */
959                         lseek(fd, 0, SEEK_SET);
960                         cant_seek = FALSE;
961                 }
962         }
963
964         /* If this file type requires seeking, and we can't seek, fail. */
965         if (dump_open_table[filetype].writing_must_seek && cant_seek) {
966                 *err = WTAP_ERR_CANT_WRITE_TO_PIPE;
967                 return FALSE;
968         }
969
970         /* Now try to open the file for writing. */
971         if (!(*dump_open_table[filetype].dump_open)(wdh, err)) {
972                 return FALSE;
973         }
974
975         return TRUE;    /* success! */
976 }
977
978 gboolean wtap_dump(wtap_dumper *wdh, const struct wtap_pkthdr *phdr,
979                    const union wtap_pseudo_header *pseudo_header, const guchar *pd, int *err)
980 {
981         return (wdh->subtype_write)(wdh, phdr, pseudo_header, pd, err);
982 }
983
984 void wtap_dump_flush(wtap_dumper *wdh)
985 {
986 #ifdef HAVE_LIBZ
987         if(wdh->compressed) {
988                 gzwfile_flush((GZWFILE_T)wdh->fh);
989         } else
990 #endif
991         {
992                 fflush((FILE *)wdh->fh);
993         }
994 }
995
996 gboolean wtap_dump_close(wtap_dumper *wdh, int *err)
997 {
998         gboolean ret = TRUE;
999
1000         if (wdh->subtype_close != NULL) {
1001                 /* There's a close routine for this dump stream. */
1002                 if (!(wdh->subtype_close)(wdh, err))
1003                         ret = FALSE;
1004         }
1005         errno = WTAP_ERR_CANT_CLOSE;
1006         /* Don't close stdout */
1007         if (wdh->fh != stdout) {
1008                 if (wtap_dump_file_close(wdh) == EOF) {
1009                         if (ret) {
1010                                 /* The per-format close function succeeded,
1011                                    but the fclose didn't.  Save the reason
1012                                    why, if our caller asked for it. */
1013                                 if (err != NULL)
1014                                         *err = errno;
1015                         }
1016                         ret = FALSE;
1017                 }
1018         } else {
1019                 /* as we don't close stdout, at least try to flush it */
1020                 wtap_dump_flush(wdh);
1021         }
1022         if (wdh->priv != NULL)
1023                 g_free(wdh->priv);
1024         g_free(wdh);
1025         return ret;
1026 }
1027
1028 gint64 wtap_get_bytes_dumped(wtap_dumper *wdh)
1029 {
1030         return wdh->bytes_dumped;
1031 }
1032
1033 void wtap_set_bytes_dumped(wtap_dumper *wdh, gint64 bytes_dumped)
1034 {
1035         wdh->bytes_dumped = bytes_dumped;
1036 }
1037
1038 gboolean wtap_dump_set_addrinfo_list(wtap_dumper *wdh, struct addrinfo *addrinfo_list)
1039 {
1040         if (!wdh || wdh->file_type < 0 || wdh->file_type >= wtap_num_file_types
1041                 || dump_open_table[wdh->file_type].has_name_resolution == FALSE)
1042                         return FALSE;
1043         wdh->addrinfo_list = addrinfo_list;
1044         return TRUE;
1045 }
1046
1047 /* internally open a file for writing (compressed or not) */
1048 #ifdef HAVE_LIBZ
1049 static WFILE_T wtap_dump_file_open(wtap_dumper *wdh, const char *filename)
1050 {
1051         if(wdh->compressed) {
1052                 return gzwfile_open(filename);
1053         } else {
1054                 return ws_fopen(filename, "wb");
1055         }
1056 }
1057 #else
1058 static WFILE_T wtap_dump_file_open(wtap_dumper *wdh _U_, const char *filename)
1059 {
1060         return ws_fopen(filename, "wb");
1061 }
1062 #endif
1063
1064 /* internally open a file for writing (compressed or not) */
1065 #ifdef HAVE_LIBZ
1066 static WFILE_T wtap_dump_file_fdopen(wtap_dumper *wdh, int fd)
1067 {
1068         if(wdh->compressed) {
1069                 return gzwfile_fdopen(fd);
1070         } else {
1071                 return fdopen(fd, "wb");
1072         }
1073 }
1074 #else
1075 static WFILE_T wtap_dump_file_fdopen(wtap_dumper *wdh _U_, int fd)
1076 {
1077         return fdopen(fd, "wb");
1078 }
1079 #endif
1080
1081 /* internally writing raw bytes (compressed or not) */
1082 gboolean wtap_dump_file_write(wtap_dumper *wdh, const void *buf, size_t bufsize,
1083                      int *err)
1084 {
1085         size_t nwritten;
1086
1087 #ifdef HAVE_LIBZ
1088         if (wdh->compressed) {
1089                 nwritten = gzwfile_write((GZWFILE_T)wdh->fh, buf, (unsigned) bufsize);
1090                 /*
1091                  * gzwfile_write() returns 0 on error.
1092                  */
1093                 if (nwritten == 0) {
1094                         *err = gzwfile_geterr((GZWFILE_T)wdh->fh);
1095                         return FALSE;
1096                 }
1097         } else
1098 #endif
1099         {
1100                 nwritten = fwrite(buf, 1, bufsize, (FILE *)wdh->fh);
1101                 /*
1102                  * At least according to the Mac OS X man page,
1103                  * this can return a short count on an error.
1104                  */
1105                 if (nwritten != bufsize) {
1106                         if (ferror((FILE *)wdh->fh))
1107                                 *err = errno;
1108                         else
1109                                 *err = WTAP_ERR_SHORT_WRITE;
1110                         return FALSE;
1111                 }
1112         }
1113         return TRUE;
1114 }
1115
1116 /* internally close a file for writing (compressed or not) */
1117 static int wtap_dump_file_close(wtap_dumper *wdh)
1118 {
1119 #ifdef HAVE_LIBZ
1120         if(wdh->compressed) {
1121                 return gzwfile_close((GZWFILE_T)wdh->fh);
1122         } else
1123 #endif
1124         {
1125                 return fclose((FILE *)wdh->fh);
1126         }
1127 }