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