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