3 * $Id: tethereal.c,v 1.131 2002/03/10 23:19:43 guy Exp $
5 * Ethereal - Network traffic analyzer
6 * By Gerald Combs <gerald@ethereal.com>
7 * Copyright 1998 Gerald Combs
9 * Text-mode variant, by Gilbert Ramirez <gram@alumni.rice.edu>
10 * and Guy Harris <guy@alum.mit.edu>.
12 * This program is free software; you can redistribute it and/or
13 * modify it under the terms of the GNU General Public License
14 * as published by the Free Software Foundation; either version 2
15 * of the License, or (at your option) any later version.
17 * This program is distributed in the hope that it will be useful,
18 * but WITHOUT ANY WARRANTY; without even the implied warranty of
19 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
20 * GNU General Public License for more details.
22 * You should have received a copy of the GNU General Public License
23 * along with this program; if not, write to the Free Software
24 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
44 #ifdef HAVE_SYS_TYPES_H
45 #include <sys/types.h>
48 #ifdef HAVE_SYS_STAT_H
64 #include <zlib.h> /* to get the libz version number */
67 #ifdef NEED_SNPRINTF_H
68 # include "snprintf.h"
71 #if defined(HAVE_UCD_SNMP_SNMP_H)
72 #ifdef HAVE_UCD_SNMP_VERSION_H
73 #include <ucd-snmp/version.h>
74 #endif /* HAVE_UCD_SNMP_VERSION_H */
75 #endif /* HAVE_UCD_SNMP_SNMP_H */
77 #ifdef NEED_STRERROR_H
86 #include <epan/epan.h>
89 #include <epan/timestamp.h>
90 #include <epan/packet.h>
95 #include <epan/resolv.h>
98 #include "pcap-util.h"
100 #include <epan/conversation.h>
101 #include <epan/plugins.h>
102 #include "register.h"
103 #include "conditions.h"
104 #include "capture_stop_conditions.h"
105 #include "ringbuffer.h"
106 #include <epan/epan_dissect.h>
109 #include "capture-wpcap.h"
112 static guint32 firstsec, firstusec;
113 static guint32 prevsec, prevusec;
114 static GString *comp_info_str;
115 static gboolean verbose;
116 static gboolean print_hex;
117 static gboolean line_buffered;
120 typedef struct _loop_data {
121 gboolean go; /* TRUE as long as we're supposed to keep capturing */
130 static int capture(volatile int, int);
131 static void capture_pcap_cb(u_char *, const struct pcap_pkthdr *,
133 static void capture_cleanup(int);
141 static int load_cap_file(capture_file *, int);
142 static void wtap_dispatch_cb_write(u_char *, const struct wtap_pkthdr *, long,
143 union wtap_pseudo_header *, const u_char *);
144 static void show_capture_file_io_error(const char *, int, gboolean);
145 static void wtap_dispatch_cb_print(u_char *, const struct wtap_pkthdr *, long,
146 union wtap_pseudo_header *, const u_char *);
149 ts_type timestamp_type = RELATIVE;
152 int snaplen; /* Maximum captured packet length */
153 int promisc_mode; /* Capture in promiscuous mode */
154 int autostop_count; /* Maximum packet count */
155 gboolean has_autostop_duration; /* TRUE if maximum capture duration
157 gint32 autostop_duration; /* Maximum capture duration */
158 gboolean has_autostop_filesize; /* TRUE if maximum capture file size
160 gint32 autostop_filesize; /* Maximum capture file size */
161 gboolean ringbuffer_on; /* TRUE if ring buffer in use */
162 guint32 ringbuffer_num_files; /* Number of ring buffer files */
165 static capture_options capture_opts = {
166 WTAP_MAX_PACKET_SIZE, /* snapshot length - default is
167 infinite, in effect */
168 TRUE, /* promiscuous mode is the default */
169 0, /* max packet count - default is 0,
171 FALSE, /* maximum capture duration not
172 specified by default */
173 0, /* maximum capture duration */
174 FALSE, /* maximum capture file size not
175 specified by default */
176 0, /* maximum capture file size */
177 FALSE, /* ring buffer off by default */
178 RINGBUFFER_MIN_NUM_FILES /* default number of ring buffer
188 fprintf(stderr, "This is GNU t%s %s, compiled %s\n", PACKAGE, VERSION,
191 fprintf(stderr, "t%s [ -DvVhlp ] [ -a <capture autostop condition> ] ...\n",
193 fprintf(stderr, "\t[ -b <number of ring buffer files> ] [ -c <count> ]\n");
194 fprintf(stderr, "\t[ -f <capture filter> ] [ -F <capture file type> ]\n");
195 fprintf(stderr, "\t[ -i <interface> ] [ -n ] [ -N <resolving> ]\n");
196 fprintf(stderr, "\t[ -o <preference setting> ] ... [ -r <infile> ] [ -R <read filter> ]\n");
197 fprintf(stderr, "\t[ -s <snaplen> ] [ -t <time stamp format> ] [ -w <savefile> ] [ -x ]\n");
199 fprintf(stderr, "t%s [ -vVhl ] [ -F <capture file type> ] [ -n ] [ -N <resolving> ]\n", PACKAGE);
200 fprintf(stderr, "\t[ -o <preference setting> ] ... [ -r <infile> ] [ -R <read filter> ]\n");
201 fprintf(stderr, "\t[ -t <time stamp format> ] [ -w <savefile> ] [ -x ]\n");
203 fprintf(stderr, "Valid file type arguments to the \"-F\" flag:\n");
204 for (i = 0; i < WTAP_NUM_FILE_TYPES; i++) {
205 if (wtap_dump_can_open(i))
206 fprintf(stderr, "\t%s - %s\n",
207 wtap_file_type_short_string(i), wtap_file_type_string(i));
209 fprintf(stderr, "\tdefault is libpcap\n");
213 get_positive_int(const char *string, const char *name)
218 number = strtol(string, &p, 10);
219 if (p == string || *p != '\0') {
220 fprintf(stderr, "tethereal: The specified %s \"%s\" is not a decimal number\n",
225 fprintf(stderr, "tethereal: The specified %s is a negative number\n",
230 fprintf(stderr, "tethereal: The specified %s is zero\n",
234 if (number > INT_MAX) {
235 fprintf(stderr, "tethereal: The specified %s is too large (greater than %d)\n",
244 * Given a string of the form "<autostop criterion>:<value>", as might appear
245 * as an argument to a "-a" option, parse it and set the criterion in
246 * question. Return an indication of whether it succeeded or failed
250 set_autostop_criterion(const char *autostoparg)
254 colonp = strchr(autostoparg, ':');
262 * Skip over any white space (there probably won't be any, but
263 * as we allow it in the preferences file, we might as well
270 * Put the colon back, so if our caller uses, in an
271 * error message, the string they passed us, the message
277 if (strcmp(autostoparg,"duration") == 0) {
278 capture_opts.has_autostop_duration = TRUE;
279 capture_opts.autostop_duration = get_positive_int(p,"autostop duration");
280 } else if (strcmp(autostoparg,"filesize") == 0) {
281 capture_opts.has_autostop_filesize = TRUE;
282 capture_opts.autostop_filesize = get_positive_int(p,"autostop filesize");
286 *colonp = ':'; /* put the colon back */
292 main(int argc, char *argv[])
296 gboolean arg_error = FALSE;
298 #ifdef HAVE_PCAP_VERSION
299 extern char pcap_version[];
300 #endif /* HAVE_PCAP_VERSION */
301 #endif /* HAVE_LIBPCAP */
309 int gpf_open_errno, pf_open_errno;
312 gboolean capture_filter_specified = FALSE;
313 GList *if_list, *if_entry;
314 gchar err_str[PCAP_ERRBUF_SIZE];
316 gboolean capture_option_specified = FALSE;
318 int out_file_type = WTAP_FILE_PCAP;
319 gchar *cf_name = NULL, *rfilter = NULL;
320 dfilter_t *rfcode = NULL;
324 /* Register all dissectors; we must do this before checking for the
325 "-G" flag, as the "-G" flag dumps a list of fields registered
326 by the dissectors, and we must do it before we read the preferences,
327 in case any dissectors register preferences. */
328 epan_init(PLUGIN_DIR,register_all_protocols,register_all_protocol_handoffs);
330 /* Now register the preferences for any non-dissector modules.
331 We must do that before we read the preferences as well. */
332 prefs_register_modules();
334 /* If invoked with the "-G" flag, we dump out a glossary of
335 display filter symbols.
337 We do this here to mirror what happens in the GTK+ version, although
338 it's not necessary here. */
339 if (argc >= 2 && strcmp(argv[1], "-G") == 0) {
340 proto_registrar_dump();
344 /* Set the C-language locale to the native environment. */
345 setlocale(LC_ALL, "");
347 prefs = read_prefs(&gpf_open_errno, &gpf_path, &pf_open_errno, &pf_path);
348 if (gpf_path != NULL) {
349 fprintf(stderr, "Can't open global preferences file \"%s\": %s.\n", pf_path,
350 strerror(gpf_open_errno));
352 if (pf_path != NULL) {
353 fprintf(stderr, "Can't open your preferences file \"%s\": %s.\n", pf_path,
354 strerror(pf_open_errno));
357 /* Set the name resolution code's flags from the preferences. */
358 g_resolv_flags = prefs->name_resolve;
361 /* Load Wpcap, if possible */
365 /* Initialize the capture file struct */
367 cfile.plist_end = NULL;
369 cfile.filename = NULL;
370 cfile.user_saved = FALSE;
371 cfile.is_tempfile = FALSE;
373 cfile.dfilter = NULL;
376 cfile.cfilter = g_strdup("");
379 cfile.save_file = NULL;
380 cfile.save_file_fd = -1;
381 cfile.has_snap = FALSE;
382 cfile.snap = WTAP_MAX_PACKET_SIZE;
384 col_init(&cfile.cinfo, prefs->num_cols);
386 /* Assemble the compile-time options */
387 comp_info_str = g_string_new("");
389 g_string_append(comp_info_str, "with ");
390 g_string_sprintfa(comp_info_str,
391 #ifdef GLIB_MAJOR_VERSION
392 "GLib %d.%d.%d", GLIB_MAJOR_VERSION, GLIB_MINOR_VERSION,
395 "GLib (version unknown)");
399 g_string_append(comp_info_str, ", with libpcap ");
400 #ifdef HAVE_PCAP_VERSION
401 g_string_append(comp_info_str, pcap_version);
402 #else /* HAVE_PCAP_VERSION */
403 g_string_append(comp_info_str, "(version unknown)");
404 #endif /* HAVE_PCAP_VERSION */
405 #else /* HAVE_LIBPCAP */
406 g_string_append(comp_info_str, ", without libpcap");
407 #endif /* HAVE_LIBPCAP */
410 g_string_append(comp_info_str, ", with libz ");
412 g_string_append(comp_info_str, ZLIB_VERSION);
413 #else /* ZLIB_VERSION */
414 g_string_append(comp_info_str, "(version unknown)");
415 #endif /* ZLIB_VERSION */
416 #else /* HAVE_LIBZ */
417 g_string_append(comp_info_str, ", without libz");
418 #endif /* HAVE_LIBZ */
420 /* Oh, this is pretty */
421 #if defined(HAVE_UCD_SNMP_SNMP_H)
422 g_string_append(comp_info_str, ", with UCD SNMP ");
423 #ifdef HAVE_UCD_SNMP_VERSION_H
424 g_string_append(comp_info_str, VersionInfo);
425 #else /* HAVE_UCD_SNMP_VERSION_H */
426 g_string_append(comp_info_str, "(version unknown)");
427 #endif /* HAVE_UCD_SNMP_VERSION_H */
428 #else /* no SNMP library */
429 g_string_append(comp_info_str, ", without SNMP MIB support");
432 /* Now get our args */
433 while ((opt = getopt(argc, argv, "a:b:c:Df:F:hi:lnN:o:pr:R:s:t:vw:Vx")) != -1) {
435 case 'a': /* autostop criteria */
437 if (set_autostop_criterion(optarg) == FALSE) {
438 fprintf(stderr, "ethereal: Invalid or unknown -a flag \"%s\"\n", optarg);
442 capture_option_specified = TRUE;
446 case 'b': /* Ringbuffer option */
448 capture_opts.ringbuffer_on = TRUE;
449 capture_opts.ringbuffer_num_files =
450 get_positive_int(optarg, "number of ring buffer files");
452 capture_option_specified = TRUE;
456 case 'c': /* Capture xxx packets */
458 capture_opts.autostop_count =
459 get_positive_int(optarg, "packet count");
461 capture_option_specified = TRUE;
465 case 'D': /* Print a list of capture devices */
467 if_list = get_interface_list(&err, err_str);
468 if (if_list == NULL) {
471 case CANT_GET_INTERFACE_LIST:
472 fprintf(stderr, "tethereal: Can't get list of interfaces: %s\n",
476 case NO_INTERFACES_FOUND:
477 fprintf(stderr, "tethereal: There are no interfaces on which a capture can be done\n");
482 for (if_entry = g_list_first(if_list); if_entry != NULL;
483 if_entry = g_list_next(if_entry))
484 printf("%s\n", (char *)if_entry->data);
485 free_interface_list(if_list);
488 capture_option_specified = TRUE;
494 capture_filter_specified = TRUE;
495 cfile.cfilter = g_strdup(optarg);
497 capture_option_specified = TRUE;
502 out_file_type = wtap_short_string_to_file_type(optarg);
503 if (out_file_type < 0) {
504 fprintf(stderr, "tethereal: \"%s\" is not a valid capture file type\n",
509 case 'h': /* Print help and exit */
513 case 'i': /* Use interface xxx */
515 cfile.iface = g_strdup(optarg);
517 capture_option_specified = TRUE;
521 case 'l': /* "Line-buffer" standard output */
522 /* This isn't line-buffering, strictly speaking, it's just
523 flushing the standard output after the information for
524 each packet is printed; however, that should be good
525 enough for all the purposes to which "-l" is put.
527 See the comment in "wtap_dispatch_cb_print()" for an
528 explanation of why we do that, and why we don't just
529 use "setvbuf()" to make the standard output line-buffered
530 (short version: in Windows, "line-buffered" is the same
531 as "fully-buffered", and the output buffer is only flushed
532 when it fills up). */
533 line_buffered = TRUE;
535 case 'n': /* No name resolution */
536 g_resolv_flags = RESOLV_NONE;
538 case 'N': /* Select what types of addresses/port #s to resolve */
539 if (g_resolv_flags == RESOLV_ALL)
540 g_resolv_flags = RESOLV_NONE;
541 badopt = string_to_name_resolve(optarg, &g_resolv_flags);
542 if (badopt != '\0') {
543 fprintf(stderr, "tethereal: -N specifies unknown resolving option '%c'; valid options are 'm', 'n', and 't'\n",
548 case 'o': /* Override preference from command line */
549 switch (prefs_set_pref(optarg)) {
551 case PREFS_SET_SYNTAX_ERR:
552 fprintf(stderr, "tethereal: Invalid -o flag \"%s\"\n", optarg);
556 case PREFS_SET_NO_SUCH_PREF:
557 case PREFS_SET_OBSOLETE:
558 fprintf(stderr, "tethereal: -o flag \"%s\" specifies unknown preference\n",
564 case 'p': /* Don't capture in promiscuous mode */
566 capture_opts.promisc_mode = FALSE;
568 capture_option_specified = TRUE;
572 case 'r': /* Read capture file xxx */
573 cf_name = g_strdup(optarg);
575 case 'R': /* Read file filter */
578 case 's': /* Set the snapshot (capture) length */
580 capture_opts.snaplen = get_positive_int(optarg, "snapshot length");
582 capture_option_specified = TRUE;
586 case 't': /* Time stamp type */
587 if (strcmp(optarg, "r") == 0)
588 timestamp_type = RELATIVE;
589 else if (strcmp(optarg, "a") == 0)
590 timestamp_type = ABSOLUTE;
591 else if (strcmp(optarg, "ad") == 0)
592 timestamp_type = ABSOLUTE_WITH_DATE;
593 else if (strcmp(optarg, "d") == 0)
594 timestamp_type = DELTA;
596 fprintf(stderr, "tethereal: Invalid time stamp type \"%s\"\n",
598 fprintf(stderr, "It must be \"r\" for relative, \"a\" for absolute,\n");
599 fprintf(stderr, "\"ad\" for absolute with date, or \"d\" for delta.\n");
603 case 'v': /* Show version and exit */
604 printf("t%s %s, %s\n", PACKAGE, VERSION, comp_info_str->str);
607 case 'w': /* Write to capture file xxx */
608 cfile.save_file = g_strdup(optarg);
610 case 'V': /* Verbose */
613 case 'x': /* Print packet data in hex (and ASCII) */
619 /* If no capture filter or read filter has been specified, and there are
620 still command-line arguments, treat them as the tokens of a capture
621 filter (if no "-r" flag was specified) or a read filter (if a "-r"
622 flag was specified. */
624 if (cf_name != NULL) {
625 if (rfilter != NULL) {
627 "tethereal: Read filters were specified both with \"-R\" and with additional command-line arguments\n");
630 rfilter = get_args_as_string(argc, argv, optind);
633 if (capture_filter_specified) {
635 "tethereal: Capture filters were specified both with \"-f\" and with additional command-line arguments\n");
638 cfile.cfilter = get_args_as_string(argc, argv, optind);
640 capture_option_specified = TRUE;
646 /* If they didn't specify a "-w" flag, but specified a maximum capture
647 file size, tell them that this doesn't work, and exit. */
648 if (capture_opts.has_autostop_filesize && cfile.save_file == NULL) {
649 fprintf(stderr, "tethereal: Maximum capture file size specified, but capture isn't being saved to a file.\n");
653 if (capture_opts.ringbuffer_on) {
654 /* Ring buffer works only under certain conditions:
655 a) ring buffer does not work if you're not saving the capture to
657 b) ring buffer only works if you're saving in libpcap format;
658 c) it makes no sense to enable the ring buffer if the maximum
659 file size is set to "infinite". */
660 if (cfile.save_file == NULL) {
661 fprintf(stderr, "tethereal: Ring buffer requested, but capture isn't being saved to a file.\n");
664 if (out_file_type != WTAP_FILE_PCAP) {
665 fprintf(stderr, "tethereal: Ring buffer requested, but capture isn't being saved in libpcap format.\n");
668 if (!capture_opts.has_autostop_filesize) {
669 fprintf(stderr, "tethereal: Ring buffer requested, but no maximum capture file size was specified.\n");
676 /* Start windows sockets */
677 WSAStartup( MAKEWORD( 1, 1 ), &wsaData );
680 /* Notify all registered modules that have had any of their preferences
681 changed either from one of the preferences file or from the command
682 line that its preferences have changed. */
686 if (capture_option_specified)
687 fprintf(stderr, "This version of Tethereal was not built with support for capturing packets.\n");
692 /* Build the column format array */
693 for (i = 0; i < cfile.cinfo.num_cols; i++) {
694 cfile.cinfo.col_fmt[i] = get_column_format(i);
695 cfile.cinfo.col_title[i] = g_strdup(get_column_title(i));
696 cfile.cinfo.fmt_matx[i] = (gboolean *) g_malloc0(sizeof(gboolean) *
698 get_column_format_matches(cfile.cinfo.fmt_matx[i], cfile.cinfo.col_fmt[i]);
699 cfile.cinfo.col_data[i] = NULL;
700 if (cfile.cinfo.col_fmt[i] == COL_INFO)
701 cfile.cinfo.col_buf[i] = (gchar *) g_malloc(sizeof(gchar) * COL_MAX_INFO_LEN);
703 cfile.cinfo.col_buf[i] = (gchar *) g_malloc(sizeof(gchar) * COL_MAX_LEN);
705 cfile.cinfo.col_expr[i] = (gchar *) g_malloc(sizeof(gchar) * COL_MAX_LEN);
706 cfile.cinfo.col_expr_val[i] = (gchar *) g_malloc(sizeof(gchar) * COL_MAX_LEN);
710 if (capture_opts.snaplen < 1)
711 capture_opts.snaplen = WTAP_MAX_PACKET_SIZE;
712 else if (capture_opts.snaplen < MIN_PACKET_SIZE)
713 capture_opts.snaplen = MIN_PACKET_SIZE;
715 /* Check the value range of the ringbuffer_num_files parameter */
716 if (capture_opts.ringbuffer_num_files < RINGBUFFER_MIN_NUM_FILES)
717 capture_opts.ringbuffer_num_files = RINGBUFFER_MIN_NUM_FILES;
718 else if (capture_opts.ringbuffer_num_files > RINGBUFFER_MAX_NUM_FILES)
719 capture_opts.ringbuffer_num_files = RINGBUFFER_MAX_NUM_FILES;
722 if (rfilter != NULL) {
723 if (!dfilter_compile(rfilter, &rfcode)) {
724 fprintf(stderr, "tethereal: %s\n", dfilter_error_msg);
729 cfile.rfcode = rfcode;
731 err = open_cap_file(cf_name, FALSE, &cfile);
736 err = load_cap_file(&cfile, out_file_type);
743 /* No capture file specified, so we're supposed to do a live capture;
744 do we have support for live captures? */
749 fprintf(stderr, "tethereal: Could not load wpcap.dll.\n");
754 /* Yes; did the user specify an interface to use? */
755 if (cfile.iface == NULL) {
756 /* No - is a default specified in the preferences file? */
757 if (prefs->capture_device != NULL) {
759 cfile.iface = g_strdup(prefs->capture_device);
761 /* No - pick the first one from the list of interfaces. */
762 if_list = get_interface_list(&err, err_str);
763 if (if_list == NULL) {
766 case CANT_GET_INTERFACE_LIST:
767 fprintf(stderr, "tethereal: Can't get list of interfaces: %s\n",
771 case NO_INTERFACES_FOUND:
772 fprintf(stderr, "tethereal: There are no interfaces on which a capture can be done\n");
777 cfile.iface = g_strdup(if_list->data); /* first interface */
778 free_interface_list(if_list);
781 capture(capture_opts.autostop_count, out_file_type);
783 if (capture_opts.ringbuffer_on) {
788 fprintf(stderr, "This version of Tethereal was not built with support for capturing packets.\n");
799 /* Do the low-level work of a capture.
800 Returns TRUE if it succeeds, FALSE otherwise. */
802 capture(volatile int packet_count, int out_file_type)
804 gchar open_err_str[PCAP_ERRBUF_SIZE];
805 gchar lookup_net_err_str[PCAP_ERRBUF_SIZE];
806 bpf_u_int32 netnum, netmask;
807 struct bpf_program fcode;
808 void (*oldhandler)(int);
810 volatile int inpkts = 0;
812 condition *volatile cnd_stop_capturesize = NULL;
813 condition *volatile cnd_stop_timeout = NULL;
815 static const char ppamsg[] = "can't find PPA for ";
818 struct pcap_stat stats;
821 /* Initialize all data structures used for dissection. */
824 ld.linktype = WTAP_ENCAP_UNKNOWN;
827 /* Open the network interface to capture from it.
828 Some versions of libpcap may put warnings into the error buffer
829 if they succeed; to tell if that's happened, we have to clear
830 the error buffer, and check if it's still a null string. */
831 open_err_str[0] = '\0';
832 ld.pch = pcap_open_live(cfile.iface, capture_opts.snaplen,
833 capture_opts.promisc_mode, 1000, open_err_str);
835 if (ld.pch == NULL) {
836 /* Well, we couldn't start the capture. */
838 /* On Win32 OSes, the capture devices are probably available to all
839 users; don't warn about permissions problems.
841 Do, however, warn that Token Ring and PPP devices aren't supported. */
842 snprintf(errmsg, sizeof errmsg,
843 "The capture session could not be initiated (%s).\n"
844 "Please check that you have the proper interface specified.\n"
846 "Note that the driver Tethereal uses for packet capture on Windows\n"
847 "doesn't support capturing on Token Ring interfaces, and doesn't\n"
848 "support capturing on PPP/WAN interfaces in Windows NT/2000.\n",
851 /* If we got a "can't find PPA for XXX" message, warn the user (who
852 is running Ethereal on HP-UX) that they don't have a version
853 of libpcap that properly handles HP-UX (libpcap 0.6.x and later
854 versions, which properly handle HP-UX, say "can't find /dev/dlpi
855 PPA for XXX" rather than "can't find PPA for XXX"). */
856 if (strncmp(open_err_str, ppamsg, sizeof ppamsg - 1) == 0)
859 "You are running Tethereal with a version of the libpcap library\n"
860 "that doesn't handle HP-UX network devices well; this means that\n"
861 "Tethereal may not be able to capture packets.\n"
863 "To fix this, you should install libpcap 0.6.2, or a later version\n"
864 "of libpcap, rather than libpcap 0.4 or 0.5.x. It is available in\n"
865 "packaged binary form from the Software Porting And Archive Centre\n"
866 "for HP-UX; the Centre is at http://hpux.connect.org.uk/ - the page\n"
867 "at the URL lists a number of mirror sites.";
870 snprintf(errmsg, sizeof errmsg,
871 "The capture session could not be initiated (%s).\n"
872 "Please check to make sure you have sufficient permissions, and that\n"
873 "you have the proper interface specified.%s", open_err_str, libpcap_warn);
879 /* A capture filter was specified; set it up. */
880 if (pcap_lookupnet(cfile.iface, &netnum, &netmask, lookup_net_err_str) < 0) {
882 * Well, we can't get the netmask for this interface; it's used
883 * only for filters that check for broadcast IP addresses, so
884 * we just warn the user, and punt and use 0.
887 "Warning: Couldn't obtain netmask info (%s).\n", lookup_net_err_str);
890 if (pcap_compile(ld.pch, &fcode, cfile.cfilter, 1, netmask) < 0) {
891 snprintf(errmsg, sizeof errmsg, "Unable to parse filter string (%s).",
892 pcap_geterr(ld.pch));
895 if (pcap_setfilter(ld.pch, &fcode) < 0) {
896 snprintf(errmsg, sizeof errmsg, "Can't install filter (%s).",
897 pcap_geterr(ld.pch));
902 ld.linktype = wtap_pcap_encap_to_wtap_encap(get_pcap_linktype(ld.pch,
904 if (cfile.save_file != NULL) {
905 /* Set up to write to the capture file. */
906 if (ld.linktype == WTAP_ENCAP_UNKNOWN) {
907 strcpy(errmsg, "The network you're capturing from is of a type"
908 " that Tethereal doesn't support.");
911 if (capture_opts.ringbuffer_on) {
912 cfile.save_file_fd = ringbuf_init(cfile.save_file,
913 capture_opts.ringbuffer_num_files);
914 if (cfile.save_file_fd != -1) {
915 ld.pdh = ringbuf_init_wtap_dump_fdopen(out_file_type, ld.linktype,
916 pcap_snapshot(ld.pch), &err);
921 ld.pdh = wtap_dump_open(cfile.save_file, out_file_type,
922 ld.linktype, pcap_snapshot(ld.pch), &err);
925 if (ld.pdh == NULL) {
926 snprintf(errmsg, sizeof errmsg, file_open_error_message(errno, TRUE),
932 /* Does "open_err_str" contain a non-empty string? If so, "pcap_open_live()"
933 returned a warning; print it, but keep capturing. */
934 if (open_err_str[0] != '\0')
935 fprintf(stderr, "tethereal: WARNING: %s.\n", open_err_str);
937 /* Catch SIGINT and SIGTERM and, if we get either of them, clean up
939 XXX - deal with signal semantics on various platforms. Or just
940 use "sigaction()" and be done with it? */
941 signal(SIGTERM, capture_cleanup);
942 signal(SIGINT, capture_cleanup);
944 if ((oldhandler = signal(SIGHUP, capture_cleanup)) != SIG_DFL)
945 signal(SIGHUP, oldhandler);
948 /* Let the user know what interface was chosen. */
949 fprintf(stderr, "Capturing on %s\n", cfile.iface);
952 /* initialize capture stop conditions */
953 init_capture_stop_conditions();
954 /* create stop conditions */
955 if (capture_opts.has_autostop_filesize)
956 cnd_stop_capturesize = cnd_new((char*)CND_CLASS_CAPTURESIZE,
957 (long)capture_opts.autostop_filesize * 1000);
958 if (capture_opts.has_autostop_duration)
959 cnd_stop_timeout = cnd_new((char*)CND_CLASS_TIMEOUT,
960 (gint32)capture_opts.autostop_duration);
962 if (packet_count == 0)
963 packet_count = -1; /* infinite capturng */
964 if (!setjmp(ld.stopenv))
969 if (packet_count > 0)
971 inpkts = pcap_dispatch(ld.pch, 1, capture_pcap_cb, (u_char *) &ld);
972 if (packet_count == 0 || inpkts < 0) {
974 } else if (cnd_stop_timeout != NULL && cnd_eval(cnd_stop_timeout)) {
975 /* The specified capture time has elapsed; stop the capture. */
977 } else if (ld.pdh != NULL && cnd_stop_capturesize != NULL &&
978 cnd_eval(cnd_stop_capturesize,
979 (guint32)wtap_get_bytes_dumped(ld.pdh))) {
980 /* We're saving the capture to a file, and the capture file reached
982 if (capture_opts.ringbuffer_on) {
983 /* Switch to the next ringbuffer file */
984 if (ringbuf_switch_file(&cfile, &ld.pdh, &err) == TRUE) {
985 /* File switch failed: reset the condition */
986 cnd_reset(cnd_stop_capturesize);
988 /* File switch failed: stop here */
993 /* No ringbuffer - just stop. */
999 /* delete stop conditions */
1000 if (cnd_stop_capturesize != NULL)
1001 cnd_delete(cnd_stop_capturesize);
1002 if (cnd_stop_timeout != NULL)
1003 cnd_delete(cnd_stop_timeout);
1005 if (cfile.save_file != NULL) {
1006 /* We're saving to a file, which means we're printing packet counts
1007 to the standard output. Send a newline so that we move to the
1008 line after the packet count. */
1009 fprintf(stderr, "\n");
1012 /* If we got an error while capturing, report it. */
1014 fprintf(stderr, "tethereal: Error while capturing packets: %s\n",
1015 pcap_geterr(ld.pch));
1018 /* Get the capture statistics, and, if any packets were dropped, report
1020 if (pcap_stats(ld.pch, &stats) >= 0) {
1021 if (stats.ps_drop != 0) {
1022 fprintf(stderr, "%u packets dropped\n", stats.ps_drop);
1025 fprintf(stderr, "tethereal: Can't get packet-drop statistics: %s\n",
1026 pcap_geterr(ld.pch));
1031 if (cfile.save_file != NULL) {
1032 /* We're saving to a file or files; close all files. */
1033 if (capture_opts.ringbuffer_on) {
1034 dump_ok = ringbuf_wtap_dump_close(&cfile, &err);
1036 dump_ok = wtap_dump_close(ld.pdh, &err);
1039 show_capture_file_io_error(cfile.save_file, err, TRUE);
1045 if (capture_opts.ringbuffer_on) {
1046 ringbuf_error_cleanup();
1048 g_free(cfile.save_file);
1049 cfile.save_file = NULL;
1050 fprintf(stderr, "tethereal: %s\n", errmsg);
1058 capture_pcap_cb(u_char *user, const struct pcap_pkthdr *phdr,
1061 struct wtap_pkthdr whdr;
1062 loop_data *ld = (loop_data *) user;
1065 whdr.ts.tv_sec = phdr->ts.tv_sec;
1066 whdr.ts.tv_usec = phdr->ts.tv_usec;
1067 whdr.caplen = phdr->caplen;
1068 whdr.len = phdr->len;
1069 whdr.pkt_encap = ld->linktype;
1074 wtap_dispatch_cb_write((u_char *)&args, &whdr, 0, NULL, pd);
1075 fprintf(stderr, "\r%u ", cfile.count);
1078 wtap_dispatch_cb_print((u_char *)&args, &whdr, 0, NULL, pd);
1083 capture_cleanup(int signum)
1085 /* Longjmp back to the starting point; "pcap_dispatch()", on many
1086 platforms, just keeps looping if it gets EINTR, so if we set
1087 "ld.go" to FALSE and return, we won't break out of it and quit
1089 longjmp(ld.stopenv, 1);
1091 #endif /* HAVE_LIBPCAP */
1094 load_cap_file(capture_file *cf, int out_file_type)
1097 int snapshot_length;
1103 linktype = wtap_file_encap(cf->wth);
1104 if (cf->save_file != NULL) {
1105 /* Set up to write to the capture file. */
1106 snapshot_length = wtap_snapshot_length(cf->wth);
1107 if (snapshot_length == 0) {
1108 /* Snapshot length of input file not known. */
1109 snapshot_length = WTAP_MAX_PACKET_SIZE;
1111 pdh = wtap_dump_open(cf->save_file, out_file_type,
1112 linktype, snapshot_length, &err);
1115 /* We couldn't set up to write to the capture file. */
1118 case WTAP_ERR_UNSUPPORTED_FILE_TYPE:
1120 "tethereal: Capture files can't be written in that format.\n");
1123 case WTAP_ERR_UNSUPPORTED_ENCAP:
1124 case WTAP_ERR_ENCAP_PER_PACKET_UNSUPPORTED:
1126 "tethereal: The capture file being read cannot be written in that format.\n");
1129 case WTAP_ERR_CANT_OPEN:
1131 "tethereal: The file \"%s\" couldn't be created for some unknown reason.\n",
1135 case WTAP_ERR_SHORT_WRITE:
1137 "tethereal: A full header couldn't be written to the file \"%s\".\n",
1144 "tethereal: The file \"%s\" could not be opened: Error %d.\n",
1145 cf->save_file, err);
1148 "tethereal: The file \"%s\" could not be opened: %s\n.",
1149 cf->save_file, strerror(err));
1157 success = wtap_loop(cf->wth, 0, wtap_dispatch_cb_write, (u_char *) &args,
1160 /* Now close the capture file. */
1161 if (!wtap_dump_close(pdh, &err))
1162 show_capture_file_io_error(cfile.save_file, err, TRUE);
1166 success = wtap_loop(cf->wth, 0, wtap_dispatch_cb_print, (u_char *) &args,
1170 /* Print up a message box noting that the read failed somewhere along
1174 case WTAP_ERR_UNSUPPORTED_ENCAP:
1176 "tethereal: \"%s\" is a capture file is for a network type that Tethereal doesn't support.\n",
1180 case WTAP_ERR_CANT_READ:
1182 "tethereal: An attempt to read from \"%s\" failed for some unknown reason.\n",
1186 case WTAP_ERR_SHORT_READ:
1188 "tethereal: \"%s\" appears to have been cut short in the middle of a packet.\n",
1192 case WTAP_ERR_BAD_RECORD:
1194 "tethereal: \"%s\" appears to be damaged or corrupt.\n",
1200 "tethereal: An error occurred while reading \"%s\": %s.\n",
1201 cf->filename, wtap_strerror(err));
1207 wtap_close(cf->wth);
1214 fill_in_fdata(frame_data *fdata, capture_file *cf,
1215 const struct wtap_pkthdr *phdr,
1216 const union wtap_pseudo_header *pseudo_header, long offset)
1221 fdata->data_src = NULL;
1222 fdata->num = cf->count;
1223 fdata->pkt_len = phdr->len;
1224 fdata->cap_len = phdr->caplen;
1225 fdata->file_off = offset;
1226 fdata->lnk_t = phdr->pkt_encap;
1227 fdata->abs_secs = phdr->ts.tv_sec;
1228 fdata->abs_usecs = phdr->ts.tv_usec;
1229 fdata->flags.passed_dfilter = 0;
1230 fdata->flags.encoding = CHAR_ASCII;
1231 fdata->flags.visited = 0;
1232 fdata->flags.marked = 0;
1234 /* If we don't have the time stamp of the first packet in the
1235 capture, it's because this is the first packet. Save the time
1236 stamp of this packet as the time stamp of the first packet. */
1237 if (!firstsec && !firstusec) {
1238 firstsec = fdata->abs_secs;
1239 firstusec = fdata->abs_usecs;
1242 /* If we don't have the time stamp of the previous displayed packet,
1243 it's because this is the first displayed packet. Save the time
1244 stamp of this packet as the time stamp of the previous displayed
1246 if (!prevsec && !prevusec) {
1247 prevsec = fdata->abs_secs;
1248 prevusec = fdata->abs_usecs;
1251 /* Get the time elapsed between the first packet and this packet. */
1252 compute_timestamp_diff(&fdata->rel_secs, &fdata->rel_usecs,
1253 fdata->abs_secs, fdata->abs_usecs, firstsec, firstusec);
1255 /* If it's greater than the current elapsed time, set the elapsed time
1256 to it (we check for "greater than" so as not to be confused by
1257 time moving backwards). */
1258 if ((gint32)cf->esec < fdata->rel_secs
1259 || ((gint32)cf->esec == fdata->rel_secs && (gint32)cf->eusec < fdata->rel_usecs)) {
1260 cf->esec = fdata->rel_secs;
1261 cf->eusec = fdata->rel_usecs;
1264 /* Get the time elapsed between the previous displayed packet and
1266 compute_timestamp_diff(&fdata->del_secs, &fdata->del_usecs,
1267 fdata->abs_secs, fdata->abs_usecs, prevsec, prevusec);
1268 prevsec = fdata->abs_secs;
1269 prevusec = fdata->abs_usecs;
1272 /* Free up all data attached to a "frame_data" structure. */
1274 clear_fdata(frame_data *fdata)
1277 g_slist_free(fdata->pfd);
1278 free_data_sources(fdata); /* release data source list */
1282 wtap_dispatch_cb_write(u_char *user, const struct wtap_pkthdr *phdr,
1283 long offset, union wtap_pseudo_header *pseudo_header, const u_char *buf)
1285 cb_args_t *args = (cb_args_t *) user;
1286 capture_file *cf = args->cf;
1287 wtap_dumper *pdh = args->pdh;
1291 epan_dissect_t *edt;
1295 fill_in_fdata(&fdata, cf, phdr, pseudo_header, offset);
1296 edt = epan_dissect_new(TRUE, FALSE);
1297 epan_dissect_prime_dfilter(edt, cf->rfcode);
1298 epan_dissect_run(edt, pseudo_header, buf, &fdata, NULL);
1299 passed = dfilter_apply_edt(cf->rfcode, edt);
1305 if (!wtap_dump(pdh, phdr, pseudo_header, buf, &err)) {
1307 if (ld.pch != NULL) {
1308 /* We're capturing packets, so we're printing a count of packets
1309 captured; move to the line after the count. */
1310 fprintf(stderr, "\n");
1313 show_capture_file_io_error(cf->save_file, err, FALSE);
1318 wtap_dump_close(pdh, &err);
1323 epan_dissect_free(edt);
1325 clear_fdata(&fdata);
1329 show_capture_file_io_error(const char *fname, int err, gboolean is_close)
1335 "tethereal: Not all the packets could be written to \"%s\" because there is "
1336 "no space left on the file system.\n",
1343 "tethereal: Not all the packets could be written to \"%s\" because you are "
1344 "too close to, or over your disk quota.\n",
1349 case WTAP_ERR_CANT_CLOSE:
1351 "tethereal: \"%s\" couldn't be closed for some unknown reason.\n",
1355 case WTAP_ERR_SHORT_WRITE:
1357 "tethereal: Not all the packets could be written to \"%s\".\n",
1364 "tethereal: \"%s\" could not be closed: %s.\n",
1365 fname, wtap_strerror(err));
1368 "tethereal: An error occurred while writing to \"%s\": %s.\n",
1369 fname, wtap_strerror(err));
1376 wtap_dispatch_cb_print(u_char *user, const struct wtap_pkthdr *phdr,
1377 long offset, union wtap_pseudo_header *pseudo_header, const u_char *buf)
1379 cb_args_t *args = (cb_args_t *) user;
1380 capture_file *cf = args->cf;
1383 print_args_t print_args;
1384 epan_dissect_t *edt;
1385 gboolean create_proto_tree;
1390 fill_in_fdata(&fdata, cf, phdr, pseudo_header, offset);
1393 if (cf->rfcode || verbose)
1394 create_proto_tree = TRUE;
1396 create_proto_tree = FALSE;
1397 /* The protocol tree will be "visible", i.e., printed, only if we're
1398 not printing a summary.
1400 We only need the columns if we're *not* verbose; in verbose mode,
1401 we print the protocol tree, not the protocol summary. */
1402 edt = epan_dissect_new(create_proto_tree, verbose);
1404 epan_dissect_prime_dfilter(edt, cf->rfcode);
1406 epan_dissect_run(edt, pseudo_header, buf, &fdata, verbose ? NULL : &cf->cinfo);
1408 passed = dfilter_apply_edt(cf->rfcode, edt);
1411 /* The packet passed the read filter. */
1413 /* Print the information in the protocol tree. */
1414 print_args.to_file = TRUE;
1415 print_args.format = PR_FMT_TEXT;
1416 print_args.print_summary = FALSE;
1417 print_args.print_hex = print_hex;
1418 print_args.expand_all = TRUE;
1419 print_args.suppress_unmarked = FALSE;
1420 proto_tree_print(FALSE, &print_args, (GNode *)edt->tree,
1423 /* "print_hex_data()" will put out a leading blank line, as well
1424 as a trailing one; print one here, to separate the packets,
1425 only if "print_hex_data()" won't be called. */
1429 /* Just fill in the columns. */
1430 epan_dissect_fill_in_columns(edt);
1432 /* Now print them. */
1433 for (i = 0; i < cf->cinfo.num_cols; i++) {
1434 switch (cf->cinfo.col_fmt[i]) {
1437 * Don't print this if we're doing a live capture from a network
1438 * interface - if we're doing a live capture, you won't be
1439 * able to look at the capture in the future (it's not being
1440 * saved anywhere), so the frame numbers are unlikely to be
1443 * (XXX - it might be nice to be able to save and print at
1444 * the same time, sort of like an "Update list of packets
1445 * in real time" capture in Ethereal.)
1447 if (cf->iface != NULL)
1449 printf("%3s", cf->cinfo.col_data[i]);
1455 case COL_ABS_DATE_TIME: /* XXX - wider */
1456 printf("%10s", cf->cinfo.col_data[i]);
1462 case COL_DEF_DL_SRC:
1463 case COL_RES_DL_SRC:
1464 case COL_UNRES_DL_SRC:
1465 case COL_DEF_NET_SRC:
1466 case COL_RES_NET_SRC:
1467 case COL_UNRES_NET_SRC:
1468 printf("%12s", cf->cinfo.col_data[i]);
1474 case COL_DEF_DL_DST:
1475 case COL_RES_DL_DST:
1476 case COL_UNRES_DL_DST:
1477 case COL_DEF_NET_DST:
1478 case COL_RES_NET_DST:
1479 case COL_UNRES_NET_DST:
1480 printf("%-12s", cf->cinfo.col_data[i]);
1484 printf("%s", cf->cinfo.col_data[i]);
1487 if (i != cf->cinfo.num_cols - 1) {
1489 * This isn't the last column, so we need to print a
1490 * separator between this column and the next.
1492 * If we printed a network source and are printing a
1493 * network destination of the same type next, separate
1494 * them with "->"; if we printed a network destination
1495 * and are printing a network source of the same type
1496 * next, separate them with "<-"; otherwise separate them
1499 switch (cf->cinfo.col_fmt[i]) {
1504 switch (cf->cinfo.col_fmt[i + 1]) {
1518 case COL_DEF_DL_SRC:
1519 case COL_RES_DL_SRC:
1520 case COL_UNRES_DL_SRC:
1521 switch (cf->cinfo.col_fmt[i + 1]) {
1523 case COL_DEF_DL_DST:
1524 case COL_RES_DL_DST:
1525 case COL_UNRES_DL_DST:
1535 case COL_DEF_NET_SRC:
1536 case COL_RES_NET_SRC:
1537 case COL_UNRES_NET_SRC:
1538 switch (cf->cinfo.col_fmt[i + 1]) {
1540 case COL_DEF_NET_DST:
1541 case COL_RES_NET_DST:
1542 case COL_UNRES_NET_DST:
1555 switch (cf->cinfo.col_fmt[i + 1]) {
1569 case COL_DEF_DL_DST:
1570 case COL_RES_DL_DST:
1571 case COL_UNRES_DL_DST:
1572 switch (cf->cinfo.col_fmt[i + 1]) {
1574 case COL_DEF_DL_SRC:
1575 case COL_RES_DL_SRC:
1576 case COL_UNRES_DL_SRC:
1586 case COL_DEF_NET_DST:
1587 case COL_RES_NET_DST:
1588 case COL_UNRES_NET_DST:
1589 switch (cf->cinfo.col_fmt[i + 1]) {
1591 case COL_DEF_NET_SRC:
1592 case COL_RES_NET_SRC:
1593 case COL_UNRES_NET_SRC:
1612 print_hex_data(stdout, print_args.format, &fdata);
1617 /* The ANSI C standard does not appear to *require* that a line-buffered
1618 stream be flushed to the host environment whenever a newline is
1619 written, it just says that, on such a stream, characters "are
1620 intended to be transmitted to or from the host environment as a
1621 block when a new-line character is encountered".
1623 The Visual C++ 6.0 C implementation doesn't do what is intended;
1624 even if you set a stream to be line-buffered, it still doesn't
1625 flush the buffer at the end of every line.
1627 So, if the "-l" flag was specified, we flush the standard output
1628 at the end of a packet. This will do the right thing if we're
1629 printing packet summary lines, and, as we print the entire protocol
1630 tree for a single packet without waiting for anything to happen,
1631 it should be as good as line-buffered mode if we're printing
1632 protocol trees. (The whole reason for the "-l" flag in either
1633 tcpdump or Tethereal is to allow the output of a live capture to
1634 be piped to a program or script and to have that script see the
1635 information for the packet as soon as it's printed, rather than
1636 having to wait until a standard I/O buffer fills up. */
1640 epan_dissect_free(edt);
1642 clear_fdata(&fdata);
1646 file_open_error_message(int err, gboolean for_writing)
1649 static char errmsg_errno[1024+1];
1653 case WTAP_ERR_NOT_REGULAR_FILE:
1654 errmsg = "The file \"%s\" is a \"special file\" or socket or other non-regular file.";
1657 case WTAP_ERR_FILE_UNKNOWN_FORMAT:
1658 case WTAP_ERR_UNSUPPORTED:
1659 /* Seen only when opening a capture file for reading. */
1660 errmsg = "The file \"%s\" is not a capture file in a format Tethereal understands.";
1663 case WTAP_ERR_UNSUPPORTED_FILE_TYPE:
1664 /* Seen only when opening a capture file for writing. */
1665 errmsg = "Tethereal does not support writing capture files in that format.";
1668 case WTAP_ERR_UNSUPPORTED_ENCAP:
1669 case WTAP_ERR_ENCAP_PER_PACKET_UNSUPPORTED:
1671 errmsg = "Tethereal cannot save this capture in that format.";
1673 errmsg = "The file \"%s\" is a capture for a network type that Tethereal doesn't support.";
1676 case WTAP_ERR_BAD_RECORD:
1677 errmsg = "The file \"%s\" appears to be damaged or corrupt.";
1680 case WTAP_ERR_CANT_OPEN:
1682 errmsg = "The file \"%s\" could not be created for some unknown reason.";
1684 errmsg = "The file \"%s\" could not be opened for some unknown reason.";
1687 case WTAP_ERR_SHORT_READ:
1688 errmsg = "The file \"%s\" appears to have been cut short"
1689 " in the middle of a packet or other data.";
1692 case WTAP_ERR_SHORT_WRITE:
1693 errmsg = "A full header couldn't be written to the file \"%s\".";
1698 errmsg = "The path to the file \"%s\" does not exist.";
1700 errmsg = "The file \"%s\" does not exist.";
1705 errmsg = "You do not have permission to create or write to the file \"%s\".";
1707 errmsg = "You do not have permission to read the file \"%s\".";
1711 errmsg = "\"%s\" is a directory (folder), not a file.";
1715 snprintf(errmsg_errno, sizeof(errmsg_errno),
1716 "The file \"%%s\" could not be opened: %s.",
1717 wtap_strerror(err));
1718 errmsg = errmsg_errno;
1725 open_cap_file(char *fname, gboolean is_tempfile, capture_file *cf)
1730 struct stat cf_stat;
1731 char err_msg[2048+1];
1733 wth = wtap_open_offline(fname, &err, FALSE);
1737 /* Find the size of the file. */
1739 if (fstat(fd, &cf_stat) < 0) {
1745 /* The open succeeded. Fill in the information for this file. */
1747 /* Initialize all data structures used for dissection. */
1752 cf->f_len = cf_stat.st_size;
1754 /* Set the file name because we need it to set the follow stream filter.
1755 XXX - is that still true? We need it for other reasons, though,
1757 cf->filename = g_strdup(fname);
1759 /* Indicate whether it's a permanent or temporary file. */
1760 cf->is_tempfile = is_tempfile;
1762 /* If it's a temporary capture buffer file, mark it as not saved. */
1763 cf->user_saved = !is_tempfile;
1765 cf->cd_t = wtap_file_type(cf->wth);
1767 cf->drops_known = FALSE;
1771 cf->snap = wtap_snapshot_length(cf->wth);
1772 if (cf->snap == 0) {
1773 /* Snapshot length not known. */
1774 cf->has_snap = FALSE;
1775 cf->snap = WTAP_MAX_PACKET_SIZE;
1777 cf->has_snap = TRUE;
1778 cf->progbar_quantum = 0;
1779 cf->progbar_nextstep = 0;
1780 firstsec = 0, firstusec = 0;
1781 prevsec = 0, prevusec = 0;
1786 snprintf(err_msg, sizeof err_msg, file_open_error_message(err, FALSE), fname);
1787 fprintf(stderr, "tethereal: %s\n", err_msg);