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