Don't hand "fdata" to "clear_fdata()" if you haven't filled it in.
[obnox/wireshark/wip.git] / tethereal.c
1 /* tethereal.c
2  *
3  * $Id: tethereal.c,v 1.77 2001/04/07 06:58:17 guy Exp $
4  *
5  * Ethereal - Network traffic analyzer
6  * By Gerald Combs <gerald@zing.org>
7  * Copyright 1998 Gerald Combs
8  *
9  * Text-mode variant, by Gilbert Ramirez <gram@xiexie.org>.
10  *
11  * This program is free software; you can redistribute it and/or
12  * modify it under the terms of the GNU General Public License
13  * as published by the Free Software Foundation; either version 2
14  * of the License, or (at your option) any later version.
15  * 
16  * This program is distributed in the hope that it will be useful,
17  * but WITHOUT ANY WARRANTY; without even the implied warranty of
18  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
19  * GNU General Public License for more details.
20  * 
21  * You should have received a copy of the GNU General Public License
22  * along with this program; if not, write to the Free Software
23  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
24  *
25  */
26
27 #ifdef HAVE_CONFIG_H
28 # include "config.h"
29 #endif
30
31 #include <stdlib.h>
32 #include <stdio.h>
33 #include <string.h>
34 #include <locale.h>
35
36 #ifdef HAVE_UNISTD_H
37 #include <unistd.h>
38 #endif
39
40 #include <errno.h>
41
42 #ifdef HAVE_SYS_TYPES_H
43 #include <sys/types.h>
44 #endif
45
46 #ifdef HAVE_SYS_STAT_H
47 #include <sys/stat.h>
48 #endif
49
50 #ifdef HAVE_FCNTL_H
51 #include <fcntl.h>
52 #endif
53
54 #include <signal.h>
55
56 #ifdef HAVE_LIBPCAP
57 #include <pcap.h>
58 #endif
59
60 #ifdef NEED_SNPRINTF_H
61 # include "snprintf.h"
62 #endif
63
64 #if defined(HAVE_UCD_SNMP_SNMP_H)
65 #ifdef HAVE_UCD_SNMP_VERSION_H
66 #include <ucd-snmp/version.h>
67 #endif /* HAVE_UCD_SNMP_VERSION_H */
68 #elif defined(HAVE_SNMP_SNMP_H)
69 #ifdef HAVE_SNMP_VERSION_H
70 #include <snmp/version.h>
71 #endif /* HAVE_SNMP_VERSION_H */
72 #endif /* SNMP */
73
74 #ifdef NEED_STRERROR_H
75 #include "strerror.h"
76 #endif
77
78 #ifdef NEED_GETOPT_H
79 #include "getopt.h"
80 #endif
81
82 #include <glib.h>
83 #include <epan.h>
84
85 #include "globals.h"
86 #include "timestamp.h"
87 #include "packet.h"
88 #include "file.h"
89 #include "prefs.h"
90 #include "column.h"
91 #include "print.h"
92 #include "resolv.h"
93 #include "util.h"
94 #include "conversation.h"
95 #include "plugins.h"
96 #include "register.h"
97
98 #ifdef WIN32
99 #include "capture-wpcap.h"
100 #endif
101
102 static guint32 firstsec, firstusec;
103 static guint32 prevsec, prevusec;
104 static GString *comp_info_str;
105 static gboolean verbose;
106 static gboolean print_hex;
107 static gboolean line_buffered;
108
109 #ifdef HAVE_LIBPCAP
110 typedef struct _loop_data {
111   gint           linktype;
112   pcap_t        *pch;
113   wtap_dumper   *pdh;
114 } loop_data;
115
116 static loop_data ld;
117
118 static int capture(int, int);
119 static void capture_pcap_cb(u_char *, const struct pcap_pkthdr *,
120   const u_char *);
121 static void capture_cleanup(int);
122 #endif
123
124 typedef struct {
125   capture_file *cf;
126   wtap_dumper *pdh;
127 } cb_args_t;
128
129 static int load_cap_file(capture_file *, int);
130 static void wtap_dispatch_cb_write(u_char *, const struct wtap_pkthdr *, int,
131     union wtap_pseudo_header *, const u_char *);
132 static void show_capture_file_io_error(const char *, int, gboolean);
133 static void wtap_dispatch_cb_print(u_char *, const struct wtap_pkthdr *, int,
134     union wtap_pseudo_header *, const u_char *);
135
136 packet_info  pi;
137 capture_file cfile;
138 FILE        *data_out_file = NULL;
139 guint        main_ctx, file_ctx;
140 ts_type timestamp_type = RELATIVE;
141 #ifdef HAVE_LIBPCAP
142 static int promisc_mode = TRUE;
143 #endif
144
145 static void 
146 print_usage(void)
147 {
148   int i;
149
150   fprintf(stderr, "This is GNU t%s %s, compiled %s\n", PACKAGE, VERSION,
151         comp_info_str->str);
152 #ifdef HAVE_LIBPCAP
153   fprintf(stderr, "t%s [ -DvVhlp ] [ -c count ] [ -f <capture filter> ]\n", PACKAGE);
154   fprintf(stderr, "\t[ -F <capture file type> ] [ -i interface ] [ -n ]\n");
155   fprintf(stderr, "\t[ -o <preference setting> ] ... [ -r infile ] [ -R <read filter> ]\n");
156   fprintf(stderr, "\t[ -s snaplen ] [ -t <time stamp format> ] [ -w savefile ] [ -x ]\n");
157 #else
158   fprintf(stderr, "t%s [ -vVhl ] [ -F <capture file type> ] [ -n ]\n", PACKAGE);
159   fprintf(stderr, "\t[ -o <preference setting> ] ... [ -r infile ] [ -R <read filter> ]\n");
160   fprintf(stderr, "\t[ -t <time stamp format> ] [ -w savefile ] [ -x ]\n");
161 #endif
162   fprintf(stderr, "Valid file type arguments to the \"-F\" flag:\n");
163   for (i = 0; i < WTAP_NUM_FILE_TYPES; i++) {
164     if (wtap_dump_can_open(i))
165       fprintf(stderr, "\t%s - %s\n",
166         wtap_file_type_short_string(i), wtap_file_type_string(i));
167   }
168   fprintf(stderr, "\tdefault is libpcap\n");
169 }
170
171 int
172 main(int argc, char *argv[])
173 {
174   int                  opt, i;
175   extern char         *optarg;
176   gboolean             arg_error = FALSE;
177 #ifdef HAVE_LIBPCAP
178 #ifdef WIN32
179   char pcap_version[] = WPCAP_STRING;
180 #else
181   extern char          pcap_version[];
182 #endif
183 #endif
184
185 #ifdef WIN32
186   WSADATA               wsaData;
187 #endif
188
189   char                *gpf_path, *pf_path;
190   int                  gpf_open_errno, pf_open_errno;
191   int                  err;
192 #ifdef HAVE_LIBPCAP
193   gboolean             capture_filter_specified = FALSE;
194   int                  packet_count = 0;
195   GList               *if_list, *if_entry;
196   gchar                err_str[PCAP_ERRBUF_SIZE];
197 #else
198   gboolean             capture_option_specified = FALSE;
199 #endif
200   int                 out_file_type = WTAP_FILE_PCAP;
201   gchar               *cf_name = NULL, *rfilter = NULL;
202   dfilter_t           *rfcode = NULL;
203   e_prefs             *prefs;
204
205   /* Register all dissectors; we must do this before checking for the
206      "-G" flag, as the "-G" flag dumps a list of fields registered
207      by the dissectors, and we must do it before we read the preferences,
208      in case any dissectors register preferences. */
209   epan_init(PLUGIN_DIR,register_all_protocols,register_all_protocol_handoffs);
210
211   /* Now register the preferences for any non-dissector modules.
212      We must do that before we read the preferences as well. */
213   prefs_register_modules();
214
215   /* If invoked with the "-G" flag, we dump out a glossary of
216      display filter symbols.
217
218      We do this here to mirror what happens in the GTK+ version, although
219      it's not necessary here. */
220   if (argc >= 2 && strcmp(argv[1], "-G") == 0) {
221     proto_registrar_dump();
222     exit(0);
223   }
224
225   /* Set the C-language locale to the native environment. */
226   setlocale(LC_ALL, "");
227
228   prefs = read_prefs(&gpf_open_errno, &gpf_path, &pf_open_errno, &pf_path);
229   if (gpf_path != NULL) {
230     fprintf(stderr, "Can't open global preferences file \"%s\": %s.\n", pf_path,
231         strerror(gpf_open_errno));
232   }
233   if (pf_path != NULL) {
234     fprintf(stderr, "Can't open your preferences file \"%s\": %s.\n", pf_path,
235         strerror(pf_open_errno));
236   }
237
238 #ifdef WIN32
239   /* Load Wpcap, if possible */
240   load_wpcap();
241 #endif
242     
243   /* Initialize the capture file struct */
244   cfile.plist           = NULL;
245   cfile.plist_end       = NULL;
246   cfile.wth             = NULL;
247   cfile.filename        = NULL;
248   cfile.user_saved      = FALSE;
249   cfile.is_tempfile     = FALSE;
250   cfile.rfcode          = NULL;
251   cfile.dfilter         = NULL;
252   cfile.dfcode          = NULL;
253 #ifdef HAVE_LIBPCAP
254   cfile.cfilter         = g_strdup("");
255 #endif
256   cfile.iface           = NULL;
257   cfile.save_file       = NULL;
258   cfile.save_file_fd    = -1;
259   cfile.snap            = WTAP_MAX_PACKET_SIZE;
260   cfile.count           = 0;
261   col_init(&cfile.cinfo, prefs->num_cols);
262
263   /* Assemble the compile-time options */
264   comp_info_str = g_string_new("");
265
266   g_string_append(comp_info_str, "with ");
267   g_string_sprintfa(comp_info_str,
268 #ifdef GLIB_MAJOR_VERSION
269     "GLib %d.%d.%d", GLIB_MAJOR_VERSION, GLIB_MINOR_VERSION,
270     GLIB_MICRO_VERSION);
271 #else
272     "GLib (version unknown)");
273 #endif
274
275 #ifdef HAVE_LIBPCAP
276   g_string_append(comp_info_str, ", with libpcap ");
277   g_string_append(comp_info_str, pcap_version);
278 #else
279   g_string_append(comp_info_str, ", without libpcap");
280 #endif
281
282 #ifdef HAVE_LIBZ
283   g_string_append(comp_info_str, ", with libz ");
284 #ifdef ZLIB_VERSION
285   g_string_append(comp_info_str, ZLIB_VERSION);
286 #else /* ZLIB_VERSION */
287   g_string_append(comp_info_str, "(version unknown)");
288 #endif /* ZLIB_VERSION */
289 #else /* HAVE_LIBZ */
290   g_string_append(comp_info_str, ", without libz");
291 #endif /* HAVE_LIBZ */
292
293 /* Oh, this is pretty */
294 #if defined(HAVE_UCD_SNMP_SNMP_H)
295   g_string_append(comp_info_str, ", with UCD SNMP ");
296 #ifdef HAVE_UCD_SNMP_VERSION_H
297   g_string_append(comp_info_str, VersionInfo);
298 #else /* HAVE_UCD_SNMP_VERSION_H */
299   g_string_append(comp_info_str, "(version unknown)");
300 #endif /* HAVE_UCD_SNMP_VERSION_H */
301 #elif defined(HAVE_SNMP_SNMP_H)
302   g_string_append(comp_info_str, ", with CMU SNMP ");
303 #ifdef HAVE_SNMP_VERSION_H
304   g_string_append(comp_info_str, snmp_Version());
305 #else /* HAVE_SNMP_VERSION_H */
306   g_string_append(comp_info_str, "(version unknown)");
307 #endif /* HAVE_SNMP_VERSION_H */
308 #else /* no SNMP */
309   g_string_append(comp_info_str, ", without SNMP");
310 #endif
311     
312   /* Now get our args */
313   while ((opt = getopt(argc, argv, "c:Df:F:hi:lno:pr:R:s:t:vw:Vx")) != EOF) {
314     switch (opt) {
315       case 'c':        /* Capture xxx packets */
316 #ifdef HAVE_LIBPCAP
317         packet_count = atoi(optarg);
318 #else
319         capture_option_specified = TRUE;
320         arg_error = TRUE;
321 #endif
322         break;
323       case 'D':        /* Print a list of capture devices */
324 #ifdef HAVE_LIBPCAP
325         if_list = get_interface_list(&err, err_str);
326         if (if_list == NULL) {
327             switch (err) {
328
329             case CANT_GET_INTERFACE_LIST:
330                 fprintf(stderr, "tethereal: Can't get list of interfaces: %s\n",
331                         err_str);
332                 break;
333
334             case NO_INTERFACES_FOUND:
335                 fprintf(stderr, "tethereal: There are no interfaces on which a capture can be done\n");
336                 break;
337             }
338             exit(2);
339         }
340         for (if_entry = g_list_first(if_list); if_entry != NULL;
341                 if_entry = g_list_next(if_entry))
342           printf("%s\n", (char *)if_entry->data);
343         free_interface_list(if_list);
344         exit(0);
345 #else
346         capture_option_specified = TRUE;
347         arg_error = TRUE;
348 #endif
349         break;
350       case 'f':
351 #ifdef HAVE_LIBPCAP
352         capture_filter_specified = TRUE;
353         cfile.cfilter = g_strdup(optarg);
354 #else
355         capture_option_specified = TRUE;
356         arg_error = TRUE;
357 #endif
358         break;
359       case 'F':
360         out_file_type = wtap_short_string_to_file_type(optarg);
361         if (out_file_type < 0) {
362           fprintf(stderr, "tethereal: \"%s\" is not a valid capture file type\n",
363                         optarg);
364           exit(1);
365         }
366         break;
367       case 'h':        /* Print help and exit */
368         print_usage();
369         exit(0);
370         break;
371       case 'i':        /* Use interface xxx */
372 #ifdef HAVE_LIBPCAP
373         cfile.iface = g_strdup(optarg);
374 #else
375         capture_option_specified = TRUE;
376         arg_error = TRUE;
377 #endif
378         break;
379       case 'l':        /* "Line-buffer" standard output */
380         /* This isn't line-buffering, strictly speaking, it's just
381            flushing the standard output after the information for
382            each packet is printed; however, that should be good
383            enough for all the purposes to which "-l" is put.
384
385            See the comment in "wtap_dispatch_cb_print()" for an
386            explanation of why we do that, and why we don't just
387            use "setvbuf()" to make the standard output line-buffered
388            (short version: in Windows, "line-buffered" is the same
389            as "fully-buffered", and the output buffer is only flushed
390            when it fills up). */
391         line_buffered = TRUE;
392         break;
393       case 'n':        /* No name resolution */
394         g_resolving_actif = 0;
395         break;
396       case 'o':        /* Override preference from command line */
397         switch (prefs_set_pref(optarg)) {
398
399         case PREFS_SET_SYNTAX_ERR:
400           fprintf(stderr, "tethereal: Invalid -o flag \"%s\"\n", optarg);
401           exit(1);
402           break;
403
404         case PREFS_SET_NO_SUCH_PREF:
405           fprintf(stderr, "tethereal: -o flag \"%s\" specifies unknown preference\n",
406                         optarg);
407           exit(1);
408           break;
409         }
410         break;
411       case 'p':        /* Don't capture in promiscuous mode */
412 #ifdef HAVE_LIBPCAP
413         promisc_mode = 0;
414 #else
415         capture_option_specified = TRUE;
416         arg_error = TRUE;
417 #endif
418         break;
419       case 'r':        /* Read capture file xxx */
420         cf_name = g_strdup(optarg);
421         break;
422       case 'R':        /* Read file filter */
423         rfilter = optarg;
424         break;
425       case 's':        /* Set the snapshot (capture) length */
426 #ifdef HAVE_LIBPCAP
427         cfile.snap = atoi(optarg);
428 #else
429         capture_option_specified = TRUE;
430         arg_error = TRUE;
431 #endif
432         break;
433       case 't':        /* Time stamp type */
434         if (strcmp(optarg, "r") == 0)
435           timestamp_type = RELATIVE;
436         else if (strcmp(optarg, "a") == 0)
437           timestamp_type = ABSOLUTE;
438         else if (strcmp(optarg, "ad") == 0)
439           timestamp_type = ABSOLUTE_WITH_DATE;
440         else if (strcmp(optarg, "d") == 0)
441           timestamp_type = DELTA;
442         else {
443           fprintf(stderr, "tethereal: Invalid time stamp type \"%s\"\n",
444             optarg);
445           fprintf(stderr, "It must be \"r\" for relative, \"a\" for absolute,\n");
446           fprintf(stderr, "\"ad\" for absolute with date, or \"d\" for delta.\n");
447           exit(1);
448         }
449         break;
450       case 'v':        /* Show version and exit */
451         printf("t%s %s, %s\n", PACKAGE, VERSION, comp_info_str->str);
452         exit(0);
453         break;
454       case 'w':        /* Write to capture file xxx */
455         cfile.save_file = g_strdup(optarg);
456         break;
457       case 'V':        /* Verbose */
458         verbose = TRUE;
459         break;
460       case 'x':        /* Print packet data in hex (and ASCII) */
461         print_hex = TRUE;
462         break;
463     }
464   }
465   
466   /* If no capture filter or read filter has been specified, and there are
467      still command-line arguments, treat them as the tokens of a capture
468      filter (if no "-r" flag was specified) or a read filter (if a "-r"
469      flag was specified. */
470   if (optind < argc) {
471     if (cf_name != NULL) {
472       if (rfilter != NULL) {
473         fprintf(stderr,
474 "tethereal: Read filters were specified both with \"-R\" and with additional command-line arguments\n");
475         exit(2);
476       }
477       rfilter = get_args_as_string(argc, argv, optind);
478     } else {
479 #ifdef HAVE_LIBPCAP
480       if (capture_filter_specified) {
481         fprintf(stderr,
482 "tethereal: Capture filters were specified both with \"-f\" and with additional command-line arguments\n");
483         exit(2);
484       }
485       cfile.cfilter = get_args_as_string(argc, argv, optind);
486 #else
487       capture_option_specified = TRUE;
488 #endif
489     }
490   }
491
492 #ifdef WIN32
493   /* Start windows sockets */
494   WSAStartup( MAKEWORD( 1, 1 ), &wsaData );
495 #endif
496
497   /* Notify all registered modules that have had any of their preferences
498      changed either from one of the preferences file or from the command
499      line that its preferences have changed. */
500   prefs_apply_all();
501
502 #ifndef HAVE_LIBPCAP
503   if (capture_option_specified)
504     fprintf(stderr, "This version of Tethereal was not built with support for capturing packets.\n");
505 #endif
506   if (arg_error)
507     print_usage();
508
509   /* Build the column format array */  
510   for (i = 0; i < cfile.cinfo.num_cols; i++) {
511     cfile.cinfo.col_fmt[i] = get_column_format(i);
512     cfile.cinfo.col_title[i] = g_strdup(get_column_title(i));
513     cfile.cinfo.fmt_matx[i] = (gboolean *) g_malloc0(sizeof(gboolean) *
514       NUM_COL_FMTS);
515     get_column_format_matches(cfile.cinfo.fmt_matx[i], cfile.cinfo.col_fmt[i]);
516     cfile.cinfo.col_data[i] = NULL;
517     if (cfile.cinfo.col_fmt[i] == COL_INFO)
518       cfile.cinfo.col_buf[i] = (gchar *) g_malloc(sizeof(gchar) * COL_MAX_INFO_LEN);
519     else
520       cfile.cinfo.col_buf[i] = (gchar *) g_malloc(sizeof(gchar) * COL_MAX_LEN);
521   }
522
523   if (cfile.snap < 1)
524     cfile.snap = WTAP_MAX_PACKET_SIZE;
525   else if (cfile.snap < MIN_PACKET_SIZE)
526     cfile.snap = MIN_PACKET_SIZE;
527   
528   if (rfilter != NULL) {
529     if (!dfilter_compile(rfilter, &rfcode)) {
530       fprintf(stderr, "tethereal: %s\n", dfilter_error_msg);
531       epan_cleanup();
532       exit(2);
533     }
534   }
535   cfile.rfcode = rfcode;
536   if (cf_name) {
537     err = open_cap_file(cf_name, FALSE, &cfile);
538     if (err != 0) {
539       epan_cleanup();
540       exit(2);
541     }
542     err = load_cap_file(&cfile, out_file_type);
543     if (err != 0) {
544       epan_cleanup();
545       exit(2);
546     }
547     cf_name[0] = '\0';
548   } else {
549     /* No capture file specified, so we're supposed to do a live capture;
550        do we have support for live captures? */
551 #ifdef HAVE_LIBPCAP
552
553 #ifdef _WIN32
554     if (!has_wpcap) {
555         fprintf(stderr, "tethereal: Could not load wpcap.dll.\n");
556         exit(2);
557     }
558 #endif
559
560     /* Yes; did the user specify an interface to use? */
561     if (cfile.iface == NULL) {
562         /* No - pick the first one from the list of interfaces. */
563         if_list = get_interface_list(&err, err_str);
564         if (if_list == NULL) {
565             switch (err) {
566
567             case CANT_GET_INTERFACE_LIST:
568                 fprintf(stderr, "tethereal: Can't get list of interfaces: %s\n",
569                         err_str);
570                 break;
571
572             case NO_INTERFACES_FOUND:
573                 fprintf(stderr, "tethereal: There are no interfaces on which a capture can be done\n");
574                 break;
575             }
576             exit(2);
577         }
578         cfile.iface = g_strdup(if_list->data);  /* first interface */
579         free_interface_list(if_list);
580     }
581     capture(packet_count, out_file_type);
582 #else
583     /* No - complain. */
584     fprintf(stderr, "This version of Tethereal was not built with support for capturing packets.\n");
585     exit(2);
586 #endif
587   }
588
589   epan_cleanup();
590
591   exit(0);
592 }
593
594 #ifdef HAVE_LIBPCAP
595 /* Do the low-level work of a capture.
596    Returns TRUE if it succeeds, FALSE otherwise. */
597 static int
598 capture(int packet_count, int out_file_type)
599 {
600   gchar       err_str[PCAP_ERRBUF_SIZE];
601   bpf_u_int32 netnum, netmask;
602   struct bpf_program fcode;
603   void        (*oldhandler)(int);
604   int         err, inpkts;
605   char        errmsg[1024+1];
606 #ifndef _WIN32
607   static const char ppamsg[] = "can't find PPA for ";
608   char       *libpcap_warn;
609 #endif
610   struct pcap_stat stats;
611
612   /* Initialize the table of conversations. */
613   epan_conversation_init();
614
615   /* Initialize protocol-specific variables */
616   init_all_protocols();
617
618   ld.linktype       = WTAP_ENCAP_UNKNOWN;
619   ld.pdh            = NULL;
620
621   /* Open the network interface to capture from it. */
622   ld.pch = pcap_open_live(cfile.iface, cfile.snap, promisc_mode, 1000, err_str);
623
624   if (ld.pch == NULL) {
625     /* Well, we couldn't start the capture. */
626 #ifdef _WIN32
627     /* On Win32 OSes, the capture devices are probably available to all
628        users; don't warn about permissions problems.
629
630        Do, however, warn that Token Ring and PPP devices aren't supported. */
631     snprintf(errmsg, sizeof errmsg,
632         "The capture session could not be initiated (%s).\n"
633         "Please check that you have the proper interface specified.\n"
634         "\n"
635         "Note that the driver Tethereal uses for packet capture on Windows\n"
636         "doesn't support capturing on Token Ring interfaces, and doesn't\n"
637         "support capturing on PPP/WAN interfaces in Windows NT/2000.\n",
638         err_str);
639 #else
640       /* If we got a "can't find PPA for XXX" message, warn the user (who
641          is running Ethereal on HP-UX) that they don't have a version
642          of libpcap patched to properly handle HP-UX (the patched version
643          says "can't find /dev/dlpi PPA for XXX" rather than "can't find
644          PPA for XXX"). */
645       if (strncmp(err_str, ppamsg, sizeof ppamsg - 1) == 0)
646         libpcap_warn =
647           "\n\n"
648           "You are running Tethereal with a version of the libpcap library\n"
649           "that doesn't handle HP-UX network devices well; this means that\n"
650           "Tethereal may not be able to capture packets.\n"
651           "\n"
652           "To fix this, you will need to download the source to Tethereal\n"
653           "from www.ethereal.com if you have not already done so, read\n"
654           "the instructions in the \"README.hpux\" file in the source\n"
655           "distribution, download the source to libpcap if you have not\n"
656           "already done so, patch libpcap as per the instructions, rebuild\n"
657           "and install libpcap, and then build Tethereal (if you have already\n"
658           "built Tethereal from source, do a \"make distclean\" and re-run\n"
659           "configure before building).";
660       else
661         libpcap_warn = "";
662     snprintf(errmsg, sizeof errmsg,
663       "The capture session could not be initiated (%s).\n"
664       "Please check to make sure you have sufficient permissions, and that\n"
665       "you have the proper interface specified.%s", err_str, libpcap_warn);
666 #endif
667     goto error;
668   }
669
670   if (cfile.cfilter) {
671     /* A capture filter was specified; set it up. */
672     if (pcap_lookupnet (cfile.iface, &netnum, &netmask, err_str) < 0) {
673       /*
674        * Well, we can't get the netmask for this interface; it's used
675        * only for filters that check for broadcast IP addresses, so
676        * we just warn the user, and punt and use 0.
677        */
678       fprintf(stderr, 
679         "Warning:  Couldn't obtain netmask info (%s)\n.", err_str);
680       netmask = 0;
681     }
682     if (pcap_compile(ld.pch, &fcode, cfile.cfilter, 1, netmask) < 0) {
683       snprintf(errmsg, sizeof errmsg, "Unable to parse filter string (%s).",
684         pcap_geterr(ld.pch));
685       goto error;
686     }
687     if (pcap_setfilter(ld.pch, &fcode) < 0) {
688       snprintf(errmsg, sizeof errmsg, "Can't install filter (%s).",
689         pcap_geterr(ld.pch));
690       goto error;
691     }
692   }
693
694   ld.linktype = wtap_pcap_encap_to_wtap_encap(pcap_datalink(ld.pch));
695   if (cfile.save_file != NULL) {
696     /* Set up to write to the capture file. */
697     if (ld.linktype == WTAP_ENCAP_UNKNOWN) {
698       strcpy(errmsg, "The network you're capturing from is of a type"
699                " that Tethereal doesn't support.");
700       goto error;
701     }
702     ld.pdh = wtap_dump_open(cfile.save_file, out_file_type,
703                 ld.linktype, pcap_snapshot(ld.pch), &err);
704
705     if (ld.pdh == NULL) {
706       snprintf(errmsg, sizeof errmsg, file_open_error_message(errno, TRUE),
707                 cfile.save_file);
708       goto error;
709     }
710   }
711
712   /* Catch SIGINT and SIGTERM and, if we get either of them, clean up
713      and exit.
714      XXX - deal with signal semantics on various platforms.  Or just
715      use "sigaction()" and be done with it? */
716   signal(SIGTERM, capture_cleanup);
717   signal(SIGINT, capture_cleanup);
718 #if !defined(WIN32)
719   if ((oldhandler = signal(SIGHUP, capture_cleanup)) != SIG_DFL)
720     signal(SIGHUP, oldhandler);
721 #endif
722
723   /* Let the user know what interface was chosen. */
724   fprintf(stderr, "Capturing on %s\n", cfile.iface);
725   fflush(stderr);
726
727   inpkts = pcap_loop(ld.pch, packet_count, capture_pcap_cb, (u_char *) &ld);
728
729   if (cfile.save_file != NULL) {
730     /* We're saving to a file, which means we're printing packet counts
731        to the standard output.  Send a newline so that we move to the
732        line after the packet count. */
733     fprintf(stderr, "\n");
734   }
735
736   /* If we got an error while capturing, report it. */
737   if (inpkts < 0) {
738     fprintf(stderr, "tethereal: Error while capturing packets: %s\n",
739         pcap_geterr(ld.pch));
740   }
741
742   /* Get the capture statistics, and, if any packets were dropped, report
743      that. */
744   if (pcap_stats(ld.pch, &stats) >= 0) {
745     if (stats.ps_drop != 0) {
746       fprintf(stderr, "%u packets dropped\n", stats.ps_drop);
747     }
748   } else {
749     fprintf(stderr, "tethereal: Can't get packet-drop statistics: %s\n",
750         pcap_geterr(ld.pch));
751   }
752   pcap_close(ld.pch);
753
754   return TRUE;
755
756 error:
757   g_free(cfile.save_file);
758   cfile.save_file = NULL;
759   fprintf(stderr, "tethereal: %s\n", errmsg);
760   if (ld.pch != NULL)
761     pcap_close(ld.pch);
762
763   return FALSE;
764 }
765
766 static void
767 capture_pcap_cb(u_char *user, const struct pcap_pkthdr *phdr,
768   const u_char *pd)
769 {
770   struct wtap_pkthdr whdr;
771   loop_data *ld = (loop_data *) user;
772   cb_args_t args;
773
774   whdr.ts.tv_sec = phdr->ts.tv_sec;
775   whdr.ts.tv_usec = phdr->ts.tv_usec;
776   whdr.caplen = phdr->caplen;
777   whdr.len = phdr->len;
778   whdr.pkt_encap = ld->linktype;
779
780   args.cf = &cfile;
781   args.pdh = ld->pdh;
782   if (ld->pdh) {
783     wtap_dispatch_cb_write((u_char *)&args, &whdr, 0, NULL, pd);
784     fprintf(stderr, "\r%u ", cfile.count);
785     fflush(stdout);
786   } else {
787     wtap_dispatch_cb_print((u_char *)&args, &whdr, 0, NULL, pd);
788   }
789 }
790
791 static void
792 capture_cleanup(int signum)
793 {
794   int err;
795
796   fprintf(stderr, "\n");
797   pcap_close(ld.pch);
798   if (ld.pdh != NULL) {
799     if (!wtap_dump_close(ld.pdh, &err)) {
800       show_capture_file_io_error(cfile.save_file, err, TRUE);
801       exit(2);
802     }
803   }
804   exit(0);
805 }
806 #endif /* HAVE_LIBPCAP */
807
808 static int
809 load_cap_file(capture_file *cf, int out_file_type)
810 {
811   gint         linktype;
812   wtap_dumper *pdh;
813   int          err;
814   int          success;
815   cb_args_t    args;
816
817   linktype = wtap_file_encap(cf->wth);
818   if (cf->save_file != NULL) {
819     /* Set up to write to the capture file. */
820     pdh = wtap_dump_open(cf->save_file, out_file_type,
821                 linktype, wtap_snapshot_length(cf->wth), &err);
822
823     if (pdh == NULL) {
824       /* We couldn't set up to write to the capture file. */
825       switch (err) {
826
827       case WTAP_ERR_UNSUPPORTED_FILE_TYPE:
828         fprintf(stderr,
829                 "tethereal: Capture files can't be written in that format.\n");
830         break;
831
832       case WTAP_ERR_UNSUPPORTED_ENCAP:
833       case WTAP_ERR_ENCAP_PER_PACKET_UNSUPPORTED:
834         fprintf(stderr,
835 "tethereal: The capture file being read cannot be written in that format.\n");
836         break;
837
838       case WTAP_ERR_CANT_OPEN:
839         fprintf(stderr,
840 "tethereal: The file \"%s\" couldn't be created for some unknown reason.\n",
841                  cf->save_file);
842         break;
843
844       case WTAP_ERR_SHORT_WRITE:
845         fprintf(stderr,
846 "tethereal: A full header couldn't be written to the file \"%s\".\n",
847                 cf->save_file);
848         break;
849
850       default:
851         if (err < 0) {
852           fprintf(stderr,
853                 "tethereal: The file \"%s\" could not be opened: Error %d.\n",
854                 cf->save_file, err);
855         } else {
856           fprintf(stderr,
857                 "tethereal: The file \"%s\" could not be opened: %s\n.",
858                 cf->save_file, strerror(err));
859         }
860         break;
861       }
862       goto out;
863     }
864     args.cf = cf;
865     args.pdh = pdh;
866     success = wtap_loop(cf->wth, 0, wtap_dispatch_cb_write, (u_char *) &args,
867                         &err);
868   } else {
869     args.cf = cf;
870     args.pdh = NULL;
871     success = wtap_loop(cf->wth, 0, wtap_dispatch_cb_print, (u_char *) &args,
872                         &err);
873   }
874   if (!success) {
875     /* Print up a message box noting that the read failed somewhere along
876        the line. */
877     switch (err) {
878
879     case WTAP_ERR_UNSUPPORTED_ENCAP:
880       fprintf(stderr,
881 "tethereal: \"%s\" is a capture file is for a network type that Tethereal doesn't support.\n",
882         cf->filename);
883       break;
884
885     case WTAP_ERR_CANT_READ:
886       fprintf(stderr,
887 "tethereal: An attempt to read from \"%s\" failed for some unknown reason.\n",
888         cf->filename);
889       break;
890
891     case WTAP_ERR_SHORT_READ:
892       fprintf(stderr,
893 "tethereal: \"%s\" appears to have been cut short in the middle of a packet.\n",
894         cf->filename);
895       break;
896
897     case WTAP_ERR_BAD_RECORD:
898       fprintf(stderr,
899 "tethereal: \"%s\" appears to be damaged or corrupt.\n",
900         cf->filename);
901       break;
902
903     default:
904       fprintf(stderr,
905 "tethereal: An error occurred while reading \"%s\": %s.\n",
906         cf->filename, wtap_strerror(err));
907       break;
908     }
909   }
910
911 out:
912   wtap_close(cf->wth);
913   cf->wth = NULL;
914
915   return err;
916 }
917
918 static void
919 fill_in_fdata(frame_data *fdata, capture_file *cf,
920         const struct wtap_pkthdr *phdr,
921         const union wtap_pseudo_header *pseudo_header, int offset)
922 {
923   int i;
924
925   fdata->next = NULL;
926   fdata->prev = NULL;
927   fdata->pfd = NULL;
928   fdata->data_src = NULL;
929   fdata->num = cf->count;
930   fdata->pkt_len = phdr->len;
931   fdata->cap_len = phdr->caplen;
932   fdata->file_off = offset;
933   fdata->cinfo = NULL;
934   fdata->lnk_t = phdr->pkt_encap;
935   fdata->abs_secs  = phdr->ts.tv_sec;
936   fdata->abs_usecs = phdr->ts.tv_usec;
937   fdata->flags.passed_dfilter = 0;
938   fdata->flags.encoding = CHAR_ASCII;
939   fdata->flags.visited = 0;
940   fdata->flags.marked = 0;
941
942   /* If we don't have the time stamp of the first packet in the
943      capture, it's because this is the first packet.  Save the time
944      stamp of this packet as the time stamp of the first packet. */
945   if (!firstsec && !firstusec) {
946     firstsec  = fdata->abs_secs;
947     firstusec = fdata->abs_usecs;
948   }
949
950   /* If we don't have the time stamp of the previous displayed packet,
951      it's because this is the first displayed packet.  Save the time
952      stamp of this packet as the time stamp of the previous displayed
953      packet. */
954   if (!prevsec && !prevusec) {
955     prevsec  = fdata->abs_secs;
956     prevusec = fdata->abs_usecs;
957   }
958
959   /* Get the time elapsed between the first packet and this packet. */
960   compute_timestamp_diff(&fdata->rel_secs, &fdata->rel_usecs,
961                 fdata->abs_secs, fdata->abs_usecs, firstsec, firstusec);
962
963   /* If it's greater than the current elapsed time, set the elapsed time
964      to it (we check for "greater than" so as not to be confused by
965      time moving backwards). */
966   if (cf->esec < fdata->rel_secs
967         || (cf->esec == fdata->rel_secs && cf->eusec < fdata->rel_usecs)) {
968     cf->esec = fdata->rel_secs;
969     cf->eusec = fdata->rel_usecs;
970   }
971   
972   /* Get the time elapsed between the previous displayed packet and
973      this packet. */
974   compute_timestamp_diff(&fdata->del_secs, &fdata->del_usecs,
975                 fdata->abs_secs, fdata->abs_usecs, prevsec, prevusec);
976   prevsec = fdata->abs_secs;
977   prevusec = fdata->abs_usecs;
978
979   fdata->cinfo = &cf->cinfo;
980   for (i = 0; i < fdata->cinfo->num_cols; i++) {
981     fdata->cinfo->col_buf[i][0] = '\0';
982     fdata->cinfo->col_data[i] = fdata->cinfo->col_buf[i];
983   }
984 }
985
986 /* Free up all data attached to a "frame_data" structure. */
987 static void
988 clear_fdata(frame_data *fdata)
989 {
990   if (fdata->pfd)
991     g_slist_free(fdata->pfd);
992   if (fdata->data_src)
993     g_slist_free(fdata->data_src);
994 }
995
996 static void
997 wtap_dispatch_cb_write(u_char *user, const struct wtap_pkthdr *phdr, int offset,
998   union wtap_pseudo_header *pseudo_header, const u_char *buf)
999 {
1000   cb_args_t    *args = (cb_args_t *) user;
1001   capture_file *cf = args->cf;
1002   wtap_dumper  *pdh = args->pdh;
1003   frame_data    fdata;
1004   proto_tree   *protocol_tree;
1005   int           err;
1006   gboolean      passed;
1007   epan_dissect_t *edt;
1008
1009   cf->count++;
1010   if (cf->rfcode) {
1011     fill_in_fdata(&fdata, cf, phdr, pseudo_header, offset);
1012     protocol_tree = proto_tree_create_root();
1013     edt = epan_dissect_new(pseudo_header, buf, &fdata, protocol_tree);
1014     passed = dfilter_apply_edt(cf->rfcode, edt);
1015   } else {
1016     protocol_tree = NULL;
1017     passed = TRUE;
1018     edt = NULL;
1019   }
1020   if (passed) {
1021     if (!wtap_dump(pdh, phdr, pseudo_header, buf, &err)) {
1022 #ifdef HAVE_LIBPCAP
1023       if (ld.pch != NULL) {
1024         /* We're capturing packets, so we're printing a count of packets
1025            captured; move to the line after the count. */
1026         fprintf(stderr, "\n");
1027       }
1028 #endif
1029       show_capture_file_io_error(cf->save_file, err, FALSE);
1030 #ifdef HAVE_LIBPCAP
1031       if (ld.pch != NULL)
1032         pcap_close(ld.pch);
1033 #endif
1034       wtap_dump_close(pdh, &err);
1035       exit(2);
1036     }
1037   }
1038   if (protocol_tree != NULL)
1039     proto_tree_free(protocol_tree);
1040   if (edt != NULL)
1041     epan_dissect_free(edt);
1042   if (cf->rfcode)
1043     clear_fdata(&fdata);
1044 }
1045
1046 static void
1047 show_capture_file_io_error(const char *fname, int err, gboolean is_close)
1048 {
1049   switch (err) {
1050
1051   case ENOSPC:
1052     fprintf(stderr,
1053 "tethereal: Not all the packets could be written to \"%s\" because there is "
1054 "no space left on the file system.\n",
1055         fname);
1056     break;
1057
1058 #ifdef EDQUOT
1059   case EDQUOT:
1060     fprintf(stderr,
1061 "tethereal: Not all the packets could be written to \"%s\" because you are "
1062 "too close to, or over your disk quota.\n",
1063         fname);
1064   break;
1065 #endif
1066
1067   case WTAP_ERR_CANT_CLOSE:
1068     fprintf(stderr,
1069 "tethereal: \"%s\" couldn't be closed for some unknown reason.\n",
1070         fname);
1071     break;
1072
1073   case WTAP_ERR_SHORT_WRITE:
1074     fprintf(stderr,
1075 "tethereal: Not all the packets could be written to \"%s\".\n",
1076         fname);
1077     break;
1078
1079   default:
1080     if (is_close) {
1081       fprintf(stderr,
1082 "tethereal: \"%s\" could not be closed: %s.\n",
1083         fname, wtap_strerror(err));
1084     } else {
1085       fprintf(stderr,
1086 "tethereal: An error occurred while writing to \"%s\": %s.\n",
1087         fname, wtap_strerror(err));
1088     }
1089     break;
1090   }
1091 }
1092
1093 static void
1094 wtap_dispatch_cb_print(u_char *user, const struct wtap_pkthdr *phdr, int offset,
1095   union wtap_pseudo_header *pseudo_header, const u_char *buf)
1096 {
1097   cb_args_t    *args = (cb_args_t *) user;
1098   capture_file *cf = args->cf;
1099   frame_data    fdata;
1100   proto_tree   *protocol_tree;
1101   gboolean      passed;
1102   print_args_t  print_args;
1103   epan_dissect_t *edt;
1104   int           i;
1105
1106   cf->count++;
1107
1108   /* The protocol tree will be "visible", i.e., printed, only if we're
1109      not printing a summary. */
1110   proto_tree_is_visible = verbose;
1111
1112   fill_in_fdata(&fdata, cf, phdr, pseudo_header, offset);
1113
1114   passed = TRUE;
1115   if (cf->rfcode || verbose)
1116     protocol_tree = proto_tree_create_root();
1117   else
1118     protocol_tree = NULL;
1119   edt = epan_dissect_new(pseudo_header, buf, &fdata, protocol_tree);
1120   if (cf->rfcode)
1121     passed = dfilter_apply_edt(cf->rfcode, edt);
1122   if (passed) {
1123     /* The packet passed the read filter. */
1124     if (verbose) {
1125       /* Print the information in the protocol tree. */
1126       print_args.to_file = TRUE;
1127       print_args.format = PR_FMT_TEXT;
1128       print_args.print_summary = FALSE;
1129       print_args.print_hex = print_hex;
1130       print_args.expand_all = TRUE;
1131       proto_tree_print(FALSE, &print_args, (GNode *)protocol_tree,
1132                         buf, &fdata, stdout);
1133       if (!print_hex) {
1134         /* "print_hex_data()" will put out a leading blank line, as well
1135            as a trailing one; print one here, to separate the packets,
1136            only if "print_hex_data()" won't be called. */
1137         printf("\n");
1138       }
1139     } else {
1140       /* Just fill in the columns. */
1141       fill_in_columns(&fdata);
1142
1143       /* Now print them. */
1144       for (i = 0; i < cf->cinfo.num_cols; i++) {
1145         switch (cf->cinfo.col_fmt[i]) {
1146         case COL_NUMBER:
1147           /*
1148            * Don't print this if we're doing a live capture from a network
1149            * interface - if we're doing a live capture, you won't be
1150            * able to look at the capture in the future (it's not being
1151            * saved anywhere), so the frame numbers are unlikely to be
1152            * useful.
1153            *
1154            * (XXX - it might be nice to be able to save and print at
1155            * the same time, sort of like an "Update list of packets
1156            * in real time" capture in Ethereal.)
1157            */
1158           if (cf->iface != NULL)
1159             continue;
1160           printf("%3s", cf->cinfo.col_data[i]);
1161           break;
1162
1163         case COL_CLS_TIME:
1164         case COL_REL_TIME:
1165         case COL_ABS_TIME:
1166         case COL_ABS_DATE_TIME: /* XXX - wider */
1167           printf("%10s", cf->cinfo.col_data[i]);
1168           break;
1169
1170         case COL_DEF_SRC:
1171         case COL_RES_SRC:
1172         case COL_UNRES_SRC:
1173         case COL_DEF_DL_SRC:
1174         case COL_RES_DL_SRC:
1175         case COL_UNRES_DL_SRC:
1176         case COL_DEF_NET_SRC:
1177         case COL_RES_NET_SRC:
1178         case COL_UNRES_NET_SRC:
1179           printf("%12s", cf->cinfo.col_data[i]);
1180           break;
1181
1182         case COL_DEF_DST:
1183         case COL_RES_DST:
1184         case COL_UNRES_DST:
1185         case COL_DEF_DL_DST:
1186         case COL_RES_DL_DST:
1187         case COL_UNRES_DL_DST:
1188         case COL_DEF_NET_DST:
1189         case COL_RES_NET_DST:
1190         case COL_UNRES_NET_DST:
1191           printf("%-12s", cf->cinfo.col_data[i]);
1192           break;
1193
1194         default:
1195           printf("%s", cf->cinfo.col_data[i]);
1196           break;
1197         }
1198         if (i != cf->cinfo.num_cols - 1) {
1199           /*
1200            * This isn't the last column, so we need to print a
1201            * separator between this column and the next.
1202            *
1203            * If we printed a network source and are printing a
1204            * network destination of the same type next, separate
1205            * them with "->"; if we printed a network destination
1206            * and are printing a network source of the same type
1207            * next, separate them with "<-"; otherwise separate them
1208            * with a space.
1209            */
1210           switch (cf->cinfo.col_fmt[i]) {
1211
1212           case COL_DEF_SRC:
1213           case COL_RES_SRC:
1214           case COL_UNRES_SRC:
1215             switch (cf->cinfo.col_fmt[i + 1]) {
1216
1217             case COL_DEF_DST:
1218             case COL_RES_DST:
1219             case COL_UNRES_DST:
1220               printf(" -> ");
1221               break;
1222
1223             default:
1224               putchar(' ');
1225               break;
1226             }
1227             break;
1228
1229           case COL_DEF_DL_SRC:
1230           case COL_RES_DL_SRC:
1231           case COL_UNRES_DL_SRC:
1232             switch (cf->cinfo.col_fmt[i + 1]) {
1233
1234             case COL_DEF_DL_DST:
1235             case COL_RES_DL_DST:
1236             case COL_UNRES_DL_DST:
1237               printf(" -> ");
1238               break;
1239
1240             default:
1241               putchar(' ');
1242               break;
1243             }
1244             break;
1245
1246           case COL_DEF_NET_SRC:
1247           case COL_RES_NET_SRC:
1248           case COL_UNRES_NET_SRC:
1249             switch (cf->cinfo.col_fmt[i + 1]) {
1250
1251             case COL_DEF_NET_DST:
1252             case COL_RES_NET_DST:
1253             case COL_UNRES_NET_DST:
1254               printf(" -> ");
1255               break;
1256
1257             default:
1258               putchar(' ');
1259               break;
1260             }
1261             break;
1262
1263           case COL_DEF_DST:
1264           case COL_RES_DST:
1265           case COL_UNRES_DST:
1266             switch (cf->cinfo.col_fmt[i + 1]) {
1267
1268             case COL_DEF_SRC:
1269             case COL_RES_SRC:
1270             case COL_UNRES_SRC:
1271               printf(" <- ");
1272               break;
1273
1274             default:
1275               putchar(' ');
1276               break;
1277             }
1278             break;
1279
1280           case COL_DEF_DL_DST:
1281           case COL_RES_DL_DST:
1282           case COL_UNRES_DL_DST:
1283             switch (cf->cinfo.col_fmt[i + 1]) {
1284
1285             case COL_DEF_DL_SRC:
1286             case COL_RES_DL_SRC:
1287             case COL_UNRES_DL_SRC:
1288               printf(" <- ");
1289               break;
1290
1291             default:
1292               putchar(' ');
1293               break;
1294             }
1295             break;
1296
1297           case COL_DEF_NET_DST:
1298           case COL_RES_NET_DST:
1299           case COL_UNRES_NET_DST:
1300             switch (cf->cinfo.col_fmt[i + 1]) {
1301
1302             case COL_DEF_NET_SRC:
1303             case COL_RES_NET_SRC:
1304             case COL_UNRES_NET_SRC:
1305               printf(" <- ");
1306               break;
1307
1308             default:
1309               putchar(' ');
1310               break;
1311             }
1312             break;
1313
1314           default:
1315             putchar(' ');
1316             break;
1317           }
1318         }
1319       }
1320       putchar('\n');
1321     }
1322     if (print_hex) {
1323       print_hex_data(stdout, print_args.format, &fdata);
1324       putchar('\n');
1325     }
1326     fdata.cinfo = NULL;
1327   }
1328
1329   /* The ANSI C standard does not appear to *require* that a line-buffered
1330      stream be flushed to the host environment whenever a newline is
1331      written, it just says that, on such a stream, characters "are
1332      intended to be transmitted to or from the host environment as a
1333      block when a new-line character is encountered".
1334
1335      The Visual C++ 6.0 C implementation doesn't do what is intended;
1336      even if you set a stream to be line-buffered, it still doesn't
1337      flush the buffer at the end of every line.
1338
1339      So, if the "-l" flag was specified, we flush the standard output
1340      at the end of a packet.  This will do the right thing if we're
1341      printing packet summary lines, and, as we print the entire protocol
1342      tree for a single packet without waiting for anything to happen,
1343      it should be as good as line-buffered mode if we're printing
1344      protocol trees.  (The whole reason for the "-l" flag in either
1345      tcpdump or Tethereal is to allow the output of a live capture to
1346      be piped to a program or script and to have that script see the
1347      information for the packet as soon as it's printed, rather than
1348      having to wait until a standard I/O buffer fills up. */
1349   if (line_buffered)
1350     fflush(stdout);
1351   if (protocol_tree != NULL)
1352     proto_tree_free(protocol_tree);
1353
1354   epan_dissect_free(edt);
1355
1356   clear_fdata(&fdata);
1357
1358   proto_tree_is_visible = FALSE;
1359 }
1360
1361 char *
1362 file_open_error_message(int err, gboolean for_writing)
1363 {
1364   char *errmsg;
1365   static char errmsg_errno[1024+1];
1366
1367   switch (err) {
1368
1369   case WTAP_ERR_NOT_REGULAR_FILE:
1370     errmsg = "The file \"%s\" is a \"special file\" or socket or other non-regular file.";
1371     break;
1372
1373   case WTAP_ERR_FILE_UNKNOWN_FORMAT:
1374   case WTAP_ERR_UNSUPPORTED:
1375     /* Seen only when opening a capture file for reading. */
1376     errmsg = "The file \"%s\" is not a capture file in a format Tethereal understands.";
1377     break;
1378
1379   case WTAP_ERR_UNSUPPORTED_FILE_TYPE:
1380     /* Seen only when opening a capture file for writing. */
1381     errmsg = "Tethereal does not support writing capture files in that format.";
1382     break;
1383
1384   case WTAP_ERR_UNSUPPORTED_ENCAP:
1385   case WTAP_ERR_ENCAP_PER_PACKET_UNSUPPORTED:
1386     if (for_writing)
1387       errmsg = "Tethereal cannot save this capture in that format.";
1388     else
1389       errmsg = "The file \"%s\" is a capture for a network type that Tethereal doesn't support.";
1390     break;
1391
1392   case WTAP_ERR_BAD_RECORD:
1393     errmsg = "The file \"%s\" appears to be damaged or corrupt.";
1394     break;
1395
1396   case WTAP_ERR_CANT_OPEN:
1397     if (for_writing)
1398       errmsg = "The file \"%s\" could not be created for some unknown reason.";
1399     else
1400       errmsg = "The file \"%s\" could not be opened for some unknown reason.";
1401     break;
1402
1403   case WTAP_ERR_SHORT_READ:
1404     errmsg = "The file \"%s\" appears to have been cut short"
1405              " in the middle of a packet.";
1406     break;
1407
1408   case WTAP_ERR_SHORT_WRITE:
1409     errmsg = "A full header couldn't be written to the file \"%s\".";
1410     break;
1411
1412   case ENOENT:
1413     if (for_writing)
1414       errmsg = "The path to the file \"%s\" does not exist.";
1415     else
1416       errmsg = "The file \"%s\" does not exist.";
1417     break;
1418
1419   case EACCES:
1420     if (for_writing)
1421       errmsg = "You do not have permission to create or write to the file \"%s\".";
1422     else
1423       errmsg = "You do not have permission to read the file \"%s\".";
1424     break;
1425
1426   case EISDIR:
1427     errmsg = "\"%s\" is a directory (folder), not a file.";
1428     break;
1429
1430   default:
1431     snprintf(errmsg_errno, sizeof(errmsg_errno),
1432              "The file \"%%s\" could not be opened: %s.",
1433              wtap_strerror(err));
1434     errmsg = errmsg_errno;
1435     break;
1436   }
1437   return errmsg;
1438 }
1439
1440 int
1441 open_cap_file(char *fname, gboolean is_tempfile, capture_file *cf)
1442 {
1443   wtap       *wth;
1444   int         err;
1445   FILE_T      fh;
1446   int         fd;
1447   struct stat cf_stat;
1448   char        err_msg[2048+1];
1449
1450   wth = wtap_open_offline(fname, &err, FALSE);
1451   if (wth == NULL)
1452     goto fail;
1453
1454   /* Find the size of the file. */
1455   fh = wtap_file(wth);
1456   fd = wtap_fd(wth);
1457   if (fstat(fd, &cf_stat) < 0) {
1458     err = errno;
1459     wtap_close(wth);
1460     goto fail;
1461   }
1462
1463   /* The open succeeded.  Fill in the information for this file. */
1464
1465   /* Initialize the table of conversations. */
1466   epan_conversation_init();
1467
1468   /* Initialize protocol-specific variables */
1469   init_all_protocols();
1470
1471   cf->wth = wth;
1472   cf->filed = fd;
1473   cf->f_len = cf_stat.st_size;
1474
1475   /* Set the file name because we need it to set the follow stream filter.
1476      XXX - is that still true?  We need it for other reasons, though,
1477      in any case. */
1478   cf->filename = g_strdup(fname);
1479
1480   /* Indicate whether it's a permanent or temporary file. */
1481   cf->is_tempfile = is_tempfile;
1482
1483   /* If it's a temporary capture buffer file, mark it as not saved. */
1484   cf->user_saved = !is_tempfile;
1485
1486   cf->cd_t      = wtap_file_type(cf->wth);
1487   cf->count     = 0;
1488   cf->drops_known = FALSE;
1489   cf->drops     = 0;
1490   cf->esec      = 0;
1491   cf->eusec     = 0;
1492   cf->snap      = wtap_snapshot_length(cf->wth);
1493   cf->progbar_quantum = 0;
1494   cf->progbar_nextstep = 0;
1495   firstsec = 0, firstusec = 0;
1496   prevsec = 0, prevusec = 0;
1497  
1498   return (0);
1499
1500 fail:
1501   snprintf(err_msg, sizeof err_msg, file_open_error_message(err, FALSE), fname);
1502   fprintf(stderr, "tethereal: %s\n", err_msg);
1503   return (err);
1504 }