54edce854f44e24b644f168d0168fad2d9452c12
[obnox/wireshark/wip.git] / tethereal.c
1 /* tethereal.c
2  *
3  * $Id: tethereal.c,v 1.14 2000/01/24 04:53:54 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
35 #ifdef HAVE_UNISTD_H
36 #include <unistd.h>
37 #endif
38
39 #include <errno.h>
40 #include <sys/types.h>
41 #include <sys/stat.h>
42 #include <fcntl.h>
43 #include <signal.h>
44
45 #ifdef NEED_SNPRINTF_H
46 # ifdef HAVE_STDARG_H
47 #  include <stdarg.h>
48 # else
49 #  include <varargs.h>
50 # endif
51 # include "snprintf.h"
52 #endif
53
54 #if defined(HAVE_UCD_SNMP_SNMP_H)
55 #ifdef HAVE_UCD_SNMP_VERSION_H
56 #include <ucd-snmp/version.h>
57 #endif /* HAVE_UCD_SNMP_VERSION_H */
58 #elif defined(HAVE_SNMP_SNMP_H)
59 #ifdef HAVE_SNMP_VERSION_H
60 #include <snmp/version.h>
61 #endif /* HAVE_SNMP_VERSION_H */
62 #endif /* SNMP */
63
64 #ifdef NEED_STRERROR_H
65 #include "strerror.h"
66 #endif
67
68 #include "globals.h"
69 #include "timestamp.h"
70 #include "packet.h"
71 #include "file.h"
72 #include "prefs.h"
73 #include "column.h"
74 #include "print.h"
75 #include "resolv.h"
76 #include "follow.h"
77 #include "util.h"
78 #include "ui_util.h"
79 #include "conversation.h"
80 #include "plugins.h"
81
82 static guint32 firstsec, firstusec;
83 static guint32 prevsec, prevusec;
84 static gchar   comp_info_str[256];
85 static gboolean verbose;
86 static gboolean print_hex;
87
88 #ifdef HAVE_LIBPCAP
89 typedef struct _loop_data {
90   gint           linktype;
91   pcap_t        *pch;
92   wtap_dumper   *pdh;
93 } loop_data;
94
95 static loop_data ld;
96
97 static int capture(int, int);
98 static void capture_pcap_cb(u_char *, const struct pcap_pkthdr *,
99   const u_char *);
100 static void capture_cleanup(int);
101 #endif
102
103 typedef struct {
104   capture_file *cf;
105   wtap_dumper *pdh;
106 } cb_args_t;
107
108 static int load_cap_file(capture_file *, int);
109 static void wtap_dispatch_cb_write(u_char *, const struct wtap_pkthdr *, int,
110     const u_char *);
111 static void wtap_dispatch_cb_print(u_char *, const struct wtap_pkthdr *, int,
112     const u_char *);
113 static gchar *col_info(frame_data *, gint);
114
115 packet_info  pi;
116 capture_file cf;
117 FILE        *data_out_file = NULL;
118 guint        main_ctx, file_ctx;
119 ts_type timestamp_type = RELATIVE;
120
121 /* call initialization routines at program startup time */
122 static void
123 ethereal_proto_init(void) {
124   init_dissect_rpc();
125   proto_init();
126   init_dissect_udp();
127   dfilter_init();
128 #ifdef HAVE_PLUGINS
129   init_plugins();
130 #endif
131 }
132
133 static void
134 ethereal_proto_cleanup(void) {
135         proto_cleanup();
136         dfilter_cleanup();
137 }
138
139 static void 
140 print_usage(void)
141 {
142   int i;
143
144   fprintf(stderr, "This is GNU t%s %s, compiled with %s\n", PACKAGE,
145           VERSION, comp_info_str);
146
147   fprintf(stderr, "t%s [ -vVh ] [ -c count ] [ -D ] [ -f <filter expression> ]\n", PACKAGE);
148   fprintf(stderr, "\t[ -F <capture type> ] [ -i iface ] [ -n ] [ -r infile ]\n");
149   fprintf(stderr, "\t[ -R <filter expression> ] [ -s snaplen ] [ -t <time stamp format> ]\n");
150   fprintf(stderr, "\t[ -w savefile ] [ -x ]\n");
151   fprintf(stderr, "Valid file type arguments to the \"-F\" flag:\n");
152   for (i = 0; i < WTAP_NUM_FILE_TYPES; i++) {
153     if (wtap_dump_can_open(i))
154       fprintf(stderr, "\t%s - %s\n",
155         wtap_file_type_short_string(i), wtap_file_type_string(i));
156   }
157   fprintf(stderr, "\tdefault is libpcap\n");
158 }
159
160 int
161 main(int argc, char *argv[])
162 {
163   int                  opt, i;
164   extern char         *optarg;
165   gboolean             arg_error = FALSE;
166 #ifdef HAVE_LIBPCAP
167   extern char          pcap_version[];
168 #endif
169   char                *pf_path;
170   int                  err;
171 #ifdef HAVE_LIBPCAP
172   int                  packet_count = 0;
173   GList               *if_list;
174   gchar                err_str[PCAP_ERRBUF_SIZE];
175 #else
176   gboolean             capture_option_specified = FALSE;
177 #endif
178   int                 out_file_type = WTAP_FILE_PCAP;
179   gchar               *cf_name = NULL, *rfilter = NULL;
180   dfilter             *rfcode = NULL;
181   e_prefs             *prefs;
182
183   /* If invoked with the "-G" flag, we dump out a glossary of
184      display filter symbols.
185
186      We do this here to mirror what happens in the GTK+ version, although
187      it's not necessary here. */
188   if (argc >= 2 && strcmp(argv[1], "-G") == 0) {
189     ethereal_proto_init();
190     proto_registrar_dump();
191     exit(0);
192   }
193
194   prefs = read_prefs(&pf_path);
195   if (pf_path != NULL) {
196     fprintf(stderr, "Can't open preferences file \"%s\": %s.\n", pf_path,
197         strerror(errno));
198   }
199     
200   /* Initialize the capture file struct */
201   cf.plist              = NULL;
202   cf.plist_end          = NULL;
203   cf.wth                = NULL;
204   cf.fh                 = NULL;
205   cf.filename           = NULL;
206   cf.user_saved         = FALSE;
207   cf.is_tempfile        = FALSE;
208   cf.rfcode             = NULL;
209   cf.dfilter            = NULL;
210   cf.dfcode             = NULL;
211 #ifdef HAVE_LIBPCAP
212   cf.cfilter            = g_strdup("");
213 #endif
214   cf.iface              = NULL;
215   cf.save_file          = NULL;
216   cf.save_file_fd       = -1;
217   cf.snap               = WTAP_MAX_PACKET_SIZE;
218   cf.count              = 0;
219   cf.cinfo.num_cols     = prefs->num_cols;
220   cf.cinfo.col_fmt      = (gint *) g_malloc(sizeof(gint) * cf.cinfo.num_cols);
221   cf.cinfo.fmt_matx     = (gboolean **) g_malloc(sizeof(gboolean *) * cf.cinfo.num_cols);
222   cf.cinfo.col_width    = (gint *) g_malloc(sizeof(gint) * cf.cinfo.num_cols);
223   cf.cinfo.col_title    = (gchar **) g_malloc(sizeof(gchar *) * cf.cinfo.num_cols);
224   cf.cinfo.col_data     = (gchar **) g_malloc(sizeof(gchar *) * cf.cinfo.num_cols);
225
226   /* Assemble the compile-time options */
227   snprintf(comp_info_str, 256,
228 #ifdef GTK_MAJOR_VERSION
229     "GTK+ %d.%d.%d, %s%s, %s%s, %s%s", GTK_MAJOR_VERSION, GTK_MINOR_VERSION,
230     GTK_MICRO_VERSION,
231 #else
232     "GTK+ (version unknown), %s%s, %s%s, %s%s",
233 #endif
234
235 #ifdef HAVE_LIBPCAP
236    "with libpcap ", pcap_version,
237 #else
238    "without libpcap", "",
239 #endif
240
241 #ifdef HAVE_LIBZ
242 #ifdef ZLIB_VERSION
243    "with libz ", ZLIB_VERSION,
244 #else /* ZLIB_VERSION */
245    "with libz ", "(version unknown)",
246 #endif /* ZLIB_VERSION */
247 #else /* HAVE_LIBZ */
248    "without libz", "",
249 #endif /* HAVE_LIBZ */
250
251 /* Oh, this is pretty */
252 #if defined(HAVE_UCD_SNMP_SNMP_H)
253 #ifdef HAVE_UCD_SNMP_VERSION_H
254    "with UCD SNMP ", VersionInfo
255 #else /* HAVE_UCD_SNMP_VERSION_H */
256    "with UCD SNMP ", "(version unknown)"
257 #endif /* HAVE_UCD_SNMP_VERSION_H */
258 #elif defined(HAVE_SNMP_SNMP_H)
259 #ifdef HAVE_SNMP_VERSION_H
260    "with CMU SNMP ", snmp_Version()
261 #else /* HAVE_SNMP_VERSION_H */
262    "with CMU SNMP ", "(version unknown)"
263 #endif /* HAVE_SNMP_VERSION_H */
264 #else /* no SNMP */
265    "without SNMP", ""
266 #endif
267    );
268     
269   /* Now get our args */
270   while ((opt = getopt(argc, argv, "c:Df:F:hi:nr:R:s:t:vw:Vx")) != EOF) {
271     switch (opt) {
272       case 'c':        /* Capture xxx packets */
273 #ifdef HAVE_LIBPCAP
274         packet_count = atoi(optarg);
275 #else
276         capture_option_specified = TRUE;
277         arg_error = TRUE;
278 #endif
279         break;
280       case 'D':        /* Turn off DSCP printing */
281         g_ip_dscp_actif = FALSE;
282         break;
283       case 'f':
284 #ifdef HAVE_LIBPCAP
285         cf.cfilter = g_strdup(optarg);
286 #else
287         capture_option_specified = TRUE;
288         arg_error = TRUE;
289 #endif
290         break;
291       case 'F':
292         out_file_type = wtap_short_string_to_file_type(optarg);
293         if (out_file_type < 0) {
294           fprintf(stderr, "tethereal: \"%s\" is not a valid capture file type\n",
295                         optarg);
296           exit(1);
297         }
298         break;
299       case 'h':        /* Print help and exit */
300         print_usage();
301         exit(0);
302         break;
303       case 'i':        /* Use interface xxx */
304 #ifdef HAVE_LIBPCAP
305         cf.iface = g_strdup(optarg);
306 #else
307         capture_option_specified = TRUE;
308         arg_error = TRUE;
309 #endif
310         break;
311       case 'n':        /* No name resolution */
312         g_resolving_actif = 0;
313         break;
314       case 'r':        /* Read capture file xxx */
315         cf_name = g_strdup(optarg);
316         break;
317       case 'R':        /* Read file filter */
318         rfilter = optarg;
319         break;
320       case 's':        /* Set the snapshot (capture) length */
321 #ifdef HAVE_LIBPCAP
322         cf.snap = atoi(optarg);
323 #else
324         capture_option_specified = TRUE;
325         arg_error = TRUE;
326 #endif
327         break;
328       case 't':        /* Time stamp type */
329         if (strcmp(optarg, "r") == 0)
330           timestamp_type = RELATIVE;
331         else if (strcmp(optarg, "a") == 0)
332           timestamp_type = ABSOLUTE;
333         else if (strcmp(optarg, "d") == 0)
334           timestamp_type = DELTA;
335         else {
336           fprintf(stderr, "tethereal: Invalid time stamp type \"%s\"\n",
337             optarg);
338           fprintf(stderr, "It must be \"r\" for relative, \"a\" for absolute,\n");
339           fprintf(stderr, "or \"d\" for delta.\n");
340           exit(1);
341         }
342         break;
343       case 'v':        /* Show version and exit */
344         printf("t%s %s, with %s\n", PACKAGE, VERSION, comp_info_str);
345         exit(0);
346         break;
347       case 'w':        /* Write to capture file xxx */
348         cf.save_file = g_strdup(optarg);
349         break;
350       case 'V':        /* Verbose */
351         verbose = TRUE;
352         break;
353       case 'x':        /* Print packet data in hex (and ASCII) */
354         print_hex = TRUE;
355         break;
356     }
357   }
358   
359 #ifndef HAVE_LIBPCAP
360   if (capture_option_specified)
361     fprintf(stderr, "This version of Ethereal was not built with support for capturing packets.\n");
362 #endif
363   if (arg_error)
364     print_usage();
365
366   /* Build the column format array */  
367   for (i = 0; i < cf.cinfo.num_cols; i++) {
368     cf.cinfo.col_fmt[i] = get_column_format(i);
369     cf.cinfo.col_title[i] = g_strdup(get_column_title(i));
370     cf.cinfo.fmt_matx[i] = (gboolean *) g_malloc0(sizeof(gboolean) *
371       NUM_COL_FMTS);
372     get_column_format_matches(cf.cinfo.fmt_matx[i], cf.cinfo.col_fmt[i]);
373     if (cf.cinfo.col_fmt[i] == COL_INFO)
374       cf.cinfo.col_data[i] = (gchar *) g_malloc(sizeof(gchar) * COL_MAX_INFO_LEN);
375     else
376       cf.cinfo.col_data[i] = (gchar *) g_malloc(sizeof(gchar) * COL_MAX_LEN);
377   }
378
379   if (cf.snap < 1)
380     cf.snap = WTAP_MAX_PACKET_SIZE;
381   else if (cf.snap < MIN_PACKET_SIZE)
382     cf.snap = MIN_PACKET_SIZE;
383   
384   ethereal_proto_init();   /* Init anything that needs initializing */
385
386   if (rfilter != NULL) {
387     if (dfilter_compile(rfilter, &rfcode) != 0) {
388       fprintf(stderr, "tethereal: %s\n", dfilter_error_msg);
389       ethereal_proto_cleanup();
390       exit(2);
391     }
392   }
393   cf.rfcode = rfcode;
394   if (cf_name) {
395     err = open_cap_file(cf_name, FALSE, &cf);
396     if (err != 0) {
397       ethereal_proto_cleanup();
398       exit(2);
399     }
400     err = load_cap_file(&cf, out_file_type);
401     if (err != 0) {
402       ethereal_proto_cleanup();
403       exit(2);
404     }
405     cf_name[0] = '\0';
406   } else {
407     /* No capture file specified, so we're supposed to do a live capture;
408        do we have support for live captures? */
409 #ifdef HAVE_LIBPCAP
410     /* Yes; did the user specify an interface to use? */
411     if (cf.iface == NULL) {
412         /* No - pick the first one from the list of interfaces. */
413         if_list = get_interface_list(&err, err_str);
414         if (if_list == NULL) {
415             switch (err) {
416
417             case CANT_GET_INTERFACE_LIST:
418                 fprintf(stderr, "tethereal: Can't get list of interfaces: %s\n",
419                         err_str);
420                 break;
421
422             case NO_INTERFACES_FOUND:
423                 fprintf(stderr, "tethereal: There are no interfaces on which a capture can be done\n");
424                 break;
425             }
426             exit(2);
427         }
428         cf.iface = g_strdup(if_list->data);     /* first interface */
429         free_interface_list(if_list);
430     }
431     capture(packet_count, out_file_type);
432 #else
433     /* No - complain. */
434     fprintf(stderr, "This version of Tethereal was not built with support for capturing packets.\n");
435     exit(2);
436 #endif
437   }
438
439   ethereal_proto_cleanup();
440
441   exit(0);
442 }
443
444 #ifdef HAVE_LIBPCAP
445 /* Do the low-level work of a capture.
446    Returns TRUE if it succeeds, FALSE otherwise. */
447 static int
448 capture(int packet_count, int out_file_type)
449 {
450   gchar       err_str[PCAP_ERRBUF_SIZE];
451   bpf_u_int32 netnum, netmask;
452   void        (*oldhandler)(int);
453   int         err, inpkts;
454   char        errmsg[1024+1];
455
456   ld.linktype       = WTAP_ENCAP_UNKNOWN;
457   ld.pdh            = NULL;
458
459   /* Open the network interface to capture from it. */
460   ld.pch = pcap_open_live(cf.iface, cf.snap, 1, 1000, err_str);
461
462   if (ld.pch == NULL) {
463     /* Well, we couldn't start the capture.
464        If this is a child process that does the capturing in sync
465        mode or fork mode, it shouldn't do any UI stuff until we pop up the
466        capture-progress window, and, since we couldn't start the
467        capture, we haven't popped it up. */
468     snprintf(errmsg, sizeof errmsg,
469       "The capture session could not be initiated (%s).\n"
470       "Please check to make sure you have sufficient permissions, and that\n"
471       "you have the proper interface specified.", err_str);
472     goto error;
473   }
474
475   if (cf.cfilter) {
476     /* A capture filter was specified; set it up. */
477     if (pcap_lookupnet (cf.iface, &netnum, &netmask, err_str) < 0) {
478       snprintf(errmsg, sizeof errmsg,
479         "Can't use filter:  Couldn't obtain netmask info (%s).", err_str);
480       goto error;
481     }
482     if (pcap_compile(ld.pch, &cf.fcode, cf.cfilter, 1, netmask) < 0) {
483       snprintf(errmsg, sizeof errmsg, "Unable to parse filter string (%s).",
484         pcap_geterr(ld.pch));
485       goto error;
486     }
487     if (pcap_setfilter(ld.pch, &cf.fcode) < 0) {
488       snprintf(errmsg, sizeof errmsg, "Can't install filter (%s).",
489         pcap_geterr(ld.pch));
490       goto error;
491     }
492   }
493
494   ld.linktype = wtap_pcap_encap_to_wtap_encap(pcap_datalink(ld.pch));
495   if (cf.save_file != NULL) {
496     /* Set up to write to the capture file. */
497     if (ld.linktype == WTAP_ENCAP_UNKNOWN) {
498       strcpy(errmsg, "The network you're capturing from is of a type"
499                " that Ethereal doesn't support.");
500       goto error;
501     }
502     ld.pdh = wtap_dump_open(cf.save_file, out_file_type,
503                 ld.linktype, pcap_snapshot(ld.pch), &err);
504
505     if (ld.pdh == NULL) {
506       /* We couldn't set up to write to the capture file. */
507       switch (err) {
508
509       case WTAP_ERR_UNSUPPORTED_FILE_TYPE:
510         strcpy(errmsg, "Tethereal does not support writing capture files in that format.");
511         break;
512
513       case WTAP_ERR_UNSUPPORTED_ENCAP:
514       case WTAP_ERR_ENCAP_PER_PACKET_UNSUPPORTED:
515         strcpy(errmsg, "Tethereal cannot save this capture in that format.");
516         break;
517
518       case WTAP_ERR_CANT_OPEN:
519         strcpy(errmsg, "The file to which the capture would be written"
520                  " couldn't be created for some unknown reason.");
521         break;
522
523       case WTAP_ERR_SHORT_WRITE:
524         strcpy(errmsg, "A full header couldn't be written to the file"
525                  " to which the capture would be written.");
526         break;
527
528       default:
529         if (err < 0) {
530           sprintf(errmsg, "The file to which the capture would be"
531                        " written (\"%s\") could not be opened: Error %d.",
532                         cf.save_file, err);
533         } else {
534           sprintf(errmsg, "The file to which the capture would be"
535                        " written (\"%s\") could not be opened: %s.",
536                         cf.save_file, strerror(err));
537         }
538         break;
539       }
540       goto error;
541     }
542   }
543
544   /* Catch SIGINT and SIGTERM and, if we get either of them, clean up
545      and exit.
546      XXX - deal with signal semantics on various platforms.  Or just
547      use "sigaction()" and be done with it? */
548   signal(SIGTERM, capture_cleanup);
549   signal(SIGINT, capture_cleanup);
550   if ((oldhandler = signal(SIGHUP, capture_cleanup)) != SIG_DFL)
551     signal(SIGHUP, oldhandler);
552
553   /* Let the user know what interface was chosen. */
554   printf("Capturing on %s\n", cf.iface);
555
556   inpkts = pcap_loop(ld.pch, packet_count, capture_pcap_cb, (u_char *) &ld);
557   pcap_close(ld.pch);
558
559   return TRUE;
560
561 error:
562   g_free(cf.save_file);
563   cf.save_file = NULL;
564   fprintf(stderr, "tethereal: %s\n", errmsg);
565   if (ld.pch != NULL)
566     pcap_close(ld.pch);
567
568   return FALSE;
569 }
570
571 static void
572 capture_pcap_cb(u_char *user, const struct pcap_pkthdr *phdr,
573   const u_char *pd)
574 {
575   struct wtap_pkthdr whdr;
576   loop_data *ld = (loop_data *) user;
577   cb_args_t args;
578
579   whdr.ts = phdr->ts;
580   whdr.caplen = phdr->caplen;
581   whdr.len = phdr->len;
582   whdr.pkt_encap = ld->linktype;
583
584   args.cf = &cf;
585   args.pdh = ld->pdh;
586   if (ld->pdh) {
587     wtap_dispatch_cb_write((u_char *)&args, &whdr, 0, pd);
588     cf.count++;
589     printf("\r%u ", cf.count);
590     fflush(stdout);
591   } else {
592     wtap_dispatch_cb_print((u_char *)&args, &whdr, 0, pd);
593   }
594 }
595
596 static void
597 capture_cleanup(int signum)
598 {
599   int err;
600
601   printf("\n");
602   pcap_close(ld.pch);
603   if (ld.pdh != NULL)
604     wtap_dump_close(ld.pdh, &err);
605   /* XXX - complain if this fails */
606   exit(0);
607 }
608 #endif /* HAVE_LIBPCAP */
609
610 static int
611 load_cap_file(capture_file *cf, int out_file_type)
612 {
613   gint         linktype;
614   wtap_dumper *pdh;
615   int          err;
616   int          success;
617   cb_args_t    args;
618
619   linktype = wtap_file_encap(cf->wth);
620   if (cf->save_file != NULL) {
621     /* Set up to write to the capture file. */
622     pdh = wtap_dump_open(cf->save_file, out_file_type,
623                 linktype, wtap_snapshot_length(cf->wth), &err);
624
625     if (pdh == NULL) {
626       /* We couldn't set up to write to the capture file. */
627       switch (err) {
628
629       case WTAP_ERR_UNSUPPORTED_FILE_TYPE:
630         fprintf(stderr,
631                 "tethereal: Capture files can't be written in that format.\n");
632         break;
633
634       case WTAP_ERR_UNSUPPORTED_ENCAP:
635       case WTAP_ERR_ENCAP_PER_PACKET_UNSUPPORTED:
636         fprintf(stderr,
637 "tethereal: The capture file being read cannot be written in that format.\n");
638         break;
639
640       case WTAP_ERR_CANT_OPEN:
641         fprintf(stderr,
642 "tethereal: The file \"%s\" couldn't be created for some unknown reason.\n",
643                  cf->save_file);
644         break;
645
646       case WTAP_ERR_SHORT_WRITE:
647         fprintf(stderr,
648 "tethereal: A full header couldn't be written to the file \"%s\".\n",
649                 cf->save_file);
650         break;
651
652       default:
653         if (err < 0) {
654           fprintf(stderr,
655                 "tethereal: The file \"%s\" could not be opened: Error %d.\n",
656                 cf->save_file, err);
657         } else {
658           fprintf(stderr,
659                 "tethereal: The file \"%s\" could not be opened: %s\n.",
660                 cf->save_file, strerror(err));
661         }
662         break;
663       }
664       goto out;
665     }
666     args.cf = cf;
667     args.pdh = pdh;
668     success = wtap_loop(cf->wth, 0, wtap_dispatch_cb_write, (u_char *) &args,
669                         &err);
670   } else {
671     args.cf = cf;
672     args.pdh = NULL;
673     success = wtap_loop(cf->wth, 0, wtap_dispatch_cb_print, (u_char *) &args,
674                         &err);
675   }
676   if (!success) {
677     /* Print up a message box noting that the read failed somewhere along
678        the line. */
679     switch (err) {
680
681     case WTAP_ERR_CANT_READ:
682       fprintf(stderr,
683 "tethereal: An attempt to read from the file failed for some unknown reason.\n");
684       break;
685
686     case WTAP_ERR_SHORT_READ:
687       fprintf(stderr,
688 "tethereal: The capture file appears to have been cut short in the middle of a packet.\n");
689       break;
690
691     case WTAP_ERR_BAD_RECORD:
692       fprintf(stderr,
693 "tethereal: The capture file appears to be damaged or corrupt.\n");
694       break;
695
696     default:
697       fprintf(stderr,
698 "tethereal: An error occurred while reading the capture file: %s.\n",
699         wtap_strerror(err));
700       break;
701     }
702   }
703
704 out:
705   wtap_close(cf->wth);
706   cf->wth = NULL;
707
708   return err;
709 }
710
711 static void
712 fill_in_fdata(frame_data *fdata, capture_file *cf,
713         const struct wtap_pkthdr *phdr, int offset)
714 {
715   int i;
716
717   fdata->next = NULL;
718   fdata->prev = NULL;
719   fdata->pkt_len  = phdr->len;
720   fdata->cap_len  = phdr->caplen;
721   fdata->file_off = offset;
722   fdata->lnk_t = phdr->pkt_encap;
723   fdata->abs_secs  = phdr->ts.tv_sec;
724   fdata->abs_usecs = phdr->ts.tv_usec;
725   fdata->encoding = CHAR_ASCII;
726   fdata->pseudo_header = phdr->pseudo_header;
727   fdata->cinfo = NULL;
728
729   fdata->num = cf->count;
730
731   /* If we don't have the time stamp of the first packet in the
732      capture, it's because this is the first packet.  Save the time
733      stamp of this packet as the time stamp of the first packet. */
734   if (!firstsec && !firstusec) {
735     firstsec  = fdata->abs_secs;
736     firstusec = fdata->abs_usecs;
737   }
738
739   /* Get the time elapsed between the first packet and this packet. */
740   cf->esec = fdata->abs_secs - firstsec;
741   if (firstusec <= fdata->abs_usecs) {
742     cf->eusec = fdata->abs_usecs - firstusec;
743   } else {
744     cf->eusec = (fdata->abs_usecs + 1000000) - firstusec;
745     cf->esec--;
746   }
747   
748   /* If we don't have the time stamp of the previous displayed packet,
749      it's because this is the first displayed packet.  Save the time
750      stamp of this packet as the time stamp of the previous displayed
751      packet. */
752   if (!prevsec && !prevusec) {
753     prevsec  = fdata->abs_secs;
754     prevusec = fdata->abs_usecs;
755   }
756
757   /* Get the time elapsed between the first packet and this packet. */
758   fdata->rel_secs = cf->esec;
759   fdata->rel_usecs = cf->eusec;
760   
761   /* Get the time elapsed between the previous displayed packet and
762      this packet. */
763   fdata->del_secs = fdata->abs_secs - prevsec;
764   if (prevusec <= fdata->abs_usecs) {
765     fdata->del_usecs = fdata->abs_usecs - prevusec;
766   } else {
767     fdata->del_usecs = (fdata->abs_usecs + 1000000) - prevusec;
768     fdata->del_secs--;
769   }
770   prevsec = fdata->abs_secs;
771   prevusec = fdata->abs_usecs;
772
773   fdata->cinfo = &cf->cinfo;
774   for (i = 0; i < fdata->cinfo->num_cols; i++) {
775     fdata->cinfo->col_data[i][0] = '\0';
776   }
777 }
778
779 static void
780 wtap_dispatch_cb_write(u_char *user, const struct wtap_pkthdr *phdr, int offset,
781   const u_char *buf)
782 {
783   cb_args_t    *args = (cb_args_t *) user;
784   capture_file *cf = args->cf;
785   wtap_dumper  *pdh = args->pdh;
786   frame_data    fdata;
787   proto_tree   *protocol_tree;
788   int           err;
789   gboolean      passed;
790
791   cf->count++;
792   if (cf->rfcode) {
793     fill_in_fdata(&fdata, cf, phdr, offset);
794     protocol_tree = proto_tree_create_root();
795     dissect_packet(buf, &fdata, protocol_tree);
796     passed = dfilter_apply(cf->rfcode, protocol_tree, buf);
797   } else {
798     protocol_tree = NULL;
799     passed = TRUE;
800   }
801   if (passed) {
802     /* XXX - do something if this fails */
803     wtap_dump(pdh, phdr, buf, &err);
804   }
805   if (protocol_tree != NULL)
806     proto_tree_free(protocol_tree);
807 }
808
809 static void
810 wtap_dispatch_cb_print(u_char *user, const struct wtap_pkthdr *phdr, int offset,
811   const u_char *buf)
812 {
813   cb_args_t    *args = (cb_args_t *) user;
814   capture_file *cf = args->cf;
815   frame_data    fdata;
816   proto_tree   *protocol_tree;
817   gboolean      passed;
818   print_args_t print_args;
819
820   cf->count++;
821
822   fill_in_fdata(&fdata, cf, phdr, offset);
823
824   passed = TRUE;
825   if (cf->rfcode || verbose)
826     protocol_tree = proto_tree_create_root();
827   else
828     protocol_tree = NULL;
829   dissect_packet(buf, &fdata, protocol_tree);
830   if (cf->rfcode)
831     passed = dfilter_apply(cf->rfcode, protocol_tree, buf);
832   if (passed) {
833     /* The packet passed the read filter. */
834     if (verbose) {
835       /* Print the information in the protocol tree. */
836       print_args.to_file = TRUE;
837       print_args.format = PR_FMT_TEXT;
838       print_args.print_summary = FALSE;
839       print_args.print_hex = print_hex;
840       print_args.expand_all = TRUE;
841       proto_tree_print(FALSE, &print_args, (GNode *)protocol_tree,
842                         buf, &fdata, stdout);
843       if (!print_hex) {
844         /* "print_hex_data()" will put out a leading blank line, as well
845            as a trailing one; print one here, to separate the packets,
846            only if "print_hex_data()" won't be called. */
847         printf("\n");
848       }
849     } else {
850       /* Just fill in the columns. */
851       fill_in_columns(&fdata);
852       if (cf->iface == NULL) {
853          printf("%3s %10s %12s -> %-12s %s %s\n",
854                   col_info(&fdata, COL_NUMBER),
855                   col_info(&fdata, COL_CLS_TIME),
856                   col_info(&fdata, COL_DEF_SRC),
857                   col_info(&fdata, COL_DEF_DST),
858                   col_info(&fdata, COL_PROTOCOL),
859                   col_info(&fdata, COL_INFO));
860       } else {
861         printf("%12s -> %-12s %s %s\n",
862                   col_info(&fdata, COL_DEF_SRC),
863                   col_info(&fdata, COL_DEF_DST),
864                   col_info(&fdata, COL_PROTOCOL),
865                   col_info(&fdata, COL_INFO));
866       }
867     }
868     if (print_hex) {
869       print_hex_data(stdout, print_args.format, buf,
870                         fdata.cap_len, fdata.encoding);
871       printf("\n");
872     }
873     fdata.cinfo = NULL;
874   }
875   if (protocol_tree != NULL)
876     proto_tree_free(protocol_tree);
877 }
878
879 char *
880 file_open_error_message(int err, int for_writing)
881 {
882   char *errmsg;
883   static char errmsg_errno[1024+1];
884
885   switch (err) {
886
887   case WTAP_ERR_NOT_REGULAR_FILE:
888     errmsg = "The file \"%s\" is invalid.";
889     break;
890
891   case WTAP_ERR_FILE_UNKNOWN_FORMAT:
892   case WTAP_ERR_UNSUPPORTED:
893     /* Seen only when opening a capture file for reading. */
894     errmsg = "The file \"%s\" is not a capture file in a format Ethereal understands.";
895     break;
896
897   case WTAP_ERR_UNSUPPORTED_FILE_TYPE:
898     /* Seen only when opening a capture file for writing. */
899     errmsg = "Ethereal does not support writing capture files in that format.";
900     break;
901
902   case WTAP_ERR_UNSUPPORTED_ENCAP:
903   case WTAP_ERR_ENCAP_PER_PACKET_UNSUPPORTED:
904     /* Seen only when opening a capture file for writing. */
905     errmsg = "Ethereal cannot save this capture in that format.";
906     break;
907
908   case WTAP_ERR_BAD_RECORD:
909     errmsg = "The file \"%s\" appears to be damaged or corrupt.";
910     break;
911
912   case WTAP_ERR_CANT_OPEN:
913     if (for_writing)
914       errmsg = "The file \"%s\" could not be created for some unknown reason.";
915     else
916       errmsg = "The file \"%s\" could not be opened for some unknown reason.";
917     break;
918
919   case WTAP_ERR_SHORT_READ:
920     errmsg = "The file \"%s\" appears to have been cut short"
921              " in the middle of a packet.";
922     break;
923
924   case WTAP_ERR_SHORT_WRITE:
925     errmsg = "A full header couldn't be written to the file \"%s\".";
926     break;
927
928   case ENOENT:
929     if (for_writing)
930       errmsg = "The path to the file \"%s\" does not exist.";
931     else
932       errmsg = "The file \"%s\" does not exist.";
933     break;
934
935   case EACCES:
936     if (for_writing)
937       errmsg = "You do not have permission to create or write to the file \"%s\".";
938     else
939       errmsg = "You do not have permission to read the file \"%s\".";
940     break;
941
942   default:
943     sprintf(errmsg_errno, "The file \"%%s\" could not be opened: %s.",
944                                 wtap_strerror(err));
945     errmsg = errmsg_errno;
946     break;
947   }
948   return errmsg;
949 }
950
951 int
952 open_cap_file(char *fname, gboolean is_tempfile, capture_file *cf)
953 {
954   wtap       *wth;
955   int         err;
956   FILE_T      fh;
957   int         fd;
958   struct stat cf_stat;
959   char        err_msg[2048+1];
960
961   wth = wtap_open_offline(fname, &err);
962   if (wth == NULL)
963     goto fail;
964
965   /* Find the size of the file. */
966   fh = wtap_file(wth);
967   fd = wtap_fd(wth);
968   if (fstat(fd, &cf_stat) < 0) {
969     err = errno;
970     wtap_close(wth);
971     goto fail;
972   }
973
974   /* The open succeeded.  Fill in the information for this file. */
975
976   /* Initialize the table of conversations. */
977   conversation_init();
978
979   /* Initialize protocol-specific variables */
980   init_all_protocols();
981
982   cf->wth = wth;
983   cf->fh = fh;
984   cf->filed = fd;
985   cf->f_len = cf_stat.st_size;
986
987   /* Set the file name because we need it to set the follow stream filter.
988      XXX - is that still true?  We need it for other reasons, though,
989      in any case. */
990   cf->filename = g_strdup(fname);
991
992   /* Indicate whether it's a permanent or temporary file. */
993   cf->is_tempfile = is_tempfile;
994
995   /* If it's a temporary capture buffer file, mark it as not saved. */
996   cf->user_saved = !is_tempfile;
997
998   cf->cd_t      = wtap_file_type(cf->wth);
999   cf->count     = 0;
1000   cf->drops     = 0;
1001   cf->esec      = 0;
1002   cf->eusec     = 0;
1003   cf->snap      = wtap_snapshot_length(cf->wth);
1004   cf->update_progbar = FALSE;
1005   cf->progbar_quantum = 0;
1006   cf->progbar_nextstep = 0;
1007   firstsec = 0, firstusec = 0;
1008   prevsec = 0, prevusec = 0;
1009  
1010   return (0);
1011
1012 fail:
1013   snprintf(err_msg, sizeof err_msg, file_open_error_message(err, FALSE), fname);
1014   fprintf(stderr, "tethereal: %s\n", err_msg);
1015   return (err);
1016 }
1017
1018 /* Get the text in a given column */
1019 static gchar *
1020 col_info(frame_data *fd, gint el) {
1021   int i;
1022   
1023   if (fd->cinfo) {
1024     for (i = 0; i < fd->cinfo->num_cols; i++) {
1025       if (fd->cinfo->fmt_matx[i][el])
1026         return fd->cinfo->col_data[i];
1027     }
1028   }
1029   return NULL;
1030 }