#include <wsutil/filesystem.h>
#include <wsutil/file_util.h>
#include <wsutil/privileges.h>
-#include <wsutil/report_err.h>
+#include <wsutil/report_message.h>
#include <ws_version_info.h>
#include "globals.h"
#include <epan/addr_resolv.h>
#include "ui/util.h"
#include "ui/decode_as_utils.h"
+#include "ui/dissect_opts.h"
#include "register.h"
#include <epan/epan_dissect.h>
#include <epan/tap.h>
#include <epan/stat_tap_ui.h>
#include <epan/ex-opt.h>
-#if defined(HAVE_HEIMDAL_KERBEROS) || defined(HAVE_MIT_KERBEROS)
-#include <epan/asn1.h>
-#include <epan/dissectors/packet-kerberos.h>
-#endif
-
#ifdef HAVE_EXTCAP
#include "extcap.h"
#endif
#include <wsutil/plugins.h>
#endif
+#define INVALID_OPTION 1
+#define INIT_ERROR 2
+#define INVALID_FILTER 2
+#define OPEN_ERROR 2
+
static guint32 cum_bytes;
static const frame_data *ref;
static frame_data ref_frame;
static const char *separator = "";
static int load_cap_file(capture_file *, int, gint64);
-static gboolean process_packet(capture_file *cf, epan_dissect_t *edt, gint64 offset,
- struct wtap_pkthdr *whdr, const guchar *pd, guint tap_flags);
+static gboolean process_packet_single_pass(capture_file *cf,
+ epan_dissect_t *edt, gint64 offset, struct wtap_pkthdr *whdr,
+ const guchar *pd, guint tap_flags);
static void show_print_file_io_error(int err);
static gboolean write_preamble(capture_file *cf);
static gboolean print_packet(capture_file *cf, epan_dissect_t *edt);
static const char *cf_open_error_message(int err, gchar *err_info,
gboolean for_writing, int file_type);
+static void failure_warning_message(const char *msg_format, va_list ap);
static void open_failure_message(const char *filename, int err,
gboolean for_writing);
-static void failure_message(const char *msg_format, va_list ap);
static void read_failure_message(const char *filename, int err);
static void write_failure_message(const char *filename, int err);
static void failure_message_cont(const char *msg_format, va_list ap);
/*fprintf(output, "\n");*/
fprintf(output, "Input file:\n");
- fprintf(output, " -r <infile> set the filename to read from (no pipes or stdin!)\n");
+ fprintf(output, " -r <infile> set the filename to read from (no pipes or stdin)\n");
fprintf(output, "\n");
fprintf(output, "Processing:\n");
fprintf(output, " -2 perform a two-pass analysis\n");
fprintf(output, " -R <read filter> packet Read filter in Wireshark display filter syntax\n");
+ fprintf(output, " (requires -2)\n");
fprintf(output, " -Y <display filter> packet displaY filter in Wireshark display filter\n");
fprintf(output, " syntax\n");
fprintf(output, " -d %s ...\n", DECODE_AS_ARG_TEMPLATE);
};
gboolean arg_error = FALSE;
- char *gpf_path, *pf_path;
- char *gdp_path, *dp_path;
- int gpf_open_errno, gpf_read_errno;
- int pf_open_errno, pf_read_errno;
- int gdp_open_errno, gdp_read_errno;
- int dp_open_errno, dp_read_errno;
int err;
volatile int exit_status = 0;
gboolean quiet = FALSE;
*
* Glibc and Solaris libc document that a leading + disables permutation
* of options, regardless of whether POSIXLY_CORRECT is set or not; *BSD
- * and OS X don't document it, but do so anyway.
+ * and macOS don't document it, but do so anyway.
*
* We do *not* use a leading - because the behavior of a leading - is
* platform-dependent.
/* Set the C-language locale to the native environment. */
setlocale(LC_ALL, "");
- cmdarg_err_init(failure_message, failure_message_cont);
+ cmdarg_err_init(failure_warning_message, failure_message_cont);
#ifdef _WIN32
arg_list_utf_16to8(argc, argv);
print_current_user();
/*
- * Attempt to get the pathname of the executable file.
+ * Attempt to get the pathname of the directory containing the
+ * executable file.
*/
init_progfile_dir_error = init_progfile_dir(argv[0], main);
if (init_progfile_dir_error != NULL) {
- fprintf(stderr, "tfshark: Can't get pathname of tfshark program: %s.\n",
+ fprintf(stderr,
+ "tfshark: Can't get pathname of directory containing the tfshark program: %s.\n",
init_progfile_dir_error);
+ g_free(init_progfile_dir_error);
}
initialize_funnel_ops();
(GLogLevelFlags)log_flags,
tfshark_log_handler, NULL /* user_data */);
- init_report_err(failure_message, open_failure_message, read_failure_message,
- write_failure_message);
+ init_report_message(failure_warning_message, failure_warning_message,
+ open_failure_message, read_failure_message,
+ write_failure_message);
timestamp_set_type(TS_RELATIVE);
timestamp_set_precision(TS_PREC_AUTO);
timestamp_set_seconds_type(TS_SECONDS_DEFAULT);
- init_open_routines();
+ wtap_init();
#ifdef HAVE_PLUGINS
/* Register all the plugin types we have. */
dissectors, and we must do it before we read the preferences, in
case any dissectors register preferences. */
if (!epan_init(register_all_protocols, register_all_protocol_handoffs, NULL,
- NULL))
- return 2;
+ NULL)) {
+ exit_status = INIT_ERROR;
+ goto clean_exit;
+ }
/* Register all tap listeners; we do this before we parse the arguments,
as the "-z" argument can specify a registered tap. */
if (strcmp(argv[2], "column-formats") == 0)
column_dump_column_formats();
else if (strcmp(argv[2], "currentprefs") == 0) {
- read_prefs(&gpf_open_errno, &gpf_read_errno, &gpf_path,
- &pf_open_errno, &pf_read_errno, &pf_path);
+ epan_load_settings();
write_prefs(NULL);
}
else if (strcmp(argv[2], "decodes") == 0)
glossary_option_help();
else {
cmdarg_err("Invalid \"%s\" option for -G flag, enter -G ? for more help.", argv[2]);
- return 1;
+ exit_status = INVALID_OPTION;
+ goto clean_exit;
}
}
- return 0;
- }
-
- prefs_p = read_prefs(&gpf_open_errno, &gpf_read_errno, &gpf_path,
- &pf_open_errno, &pf_read_errno, &pf_path);
- if (gpf_path != NULL) {
- if (gpf_open_errno != 0) {
- cmdarg_err("Can't open global preferences file \"%s\": %s.",
- pf_path, g_strerror(gpf_open_errno));
- }
- if (gpf_read_errno != 0) {
- cmdarg_err("I/O error reading global preferences file \"%s\": %s.",
- pf_path, g_strerror(gpf_read_errno));
- }
- }
- if (pf_path != NULL) {
- if (pf_open_errno != 0) {
- cmdarg_err("Can't open your preferences file \"%s\": %s.", pf_path,
- g_strerror(pf_open_errno));
- }
- if (pf_read_errno != 0) {
- cmdarg_err("I/O error reading your preferences file \"%s\": %s.",
- pf_path, g_strerror(pf_read_errno));
- }
- g_free(pf_path);
- pf_path = NULL;
+ goto clean_exit;
}
- /* Read the disabled protocols file. */
- read_disabled_protos_list(&gdp_path, &gdp_open_errno, &gdp_read_errno,
- &dp_path, &dp_open_errno, &dp_read_errno);
- read_disabled_heur_dissector_list(&gdp_path, &gdp_open_errno, &gdp_read_errno,
- &dp_path, &dp_open_errno, &dp_read_errno);
- if (gdp_path != NULL) {
- if (gdp_open_errno != 0) {
- cmdarg_err("Could not open global disabled protocols file\n\"%s\": %s.",
- gdp_path, g_strerror(gdp_open_errno));
- }
- if (gdp_read_errno != 0) {
- cmdarg_err("I/O error reading global disabled protocols file\n\"%s\": %s.",
- gdp_path, g_strerror(gdp_read_errno));
- }
- g_free(gdp_path);
- }
- if (dp_path != NULL) {
- if (dp_open_errno != 0) {
- cmdarg_err(
- "Could not open your disabled protocols file\n\"%s\": %s.", dp_path,
- g_strerror(dp_open_errno));
- }
- if (dp_read_errno != 0) {
- cmdarg_err(
- "I/O error reading your disabled protocols file\n\"%s\": %s.", dp_path,
- g_strerror(dp_read_errno));
- }
- g_free(dp_path);
- }
+ /* Load libwireshark settings from the current profile. */
+ prefs_p = epan_load_settings();
cap_file_init(&cfile);
/*
* To reset the options parser, set optreset to 1 on platforms that
- * have optreset (documented in *BSD and OS X, apparently present but
+ * have optreset (documented in *BSD and macOS, apparently present but
* not documented in Solaris - the Illumos repository seems to
* suggest that the first Solaris getopt_long(), at least as of 2004,
* was based on the NetBSD one, it had optreset) and set optind to 1,
case 'C':
/* already processed; just ignore it now */
break;
- case 'd': /* Decode as rule */
- if (!decode_as_command_option(optarg))
- return 1;
- break;
-#if defined(HAVE_HEIMDAL_KERBEROS) || defined(HAVE_MIT_KERBEROS)
- case 'K': /* Kerberos keytab file */
- read_keytab_file(optarg);
- break;
-#endif
case 'e':
/* Field entry */
output_fields_add(output_fields, optarg);
if (!output_fields_set_option(output_fields, optarg)) {
cmdarg_err("\"%s\" is not a valid field output option=value pair.", optarg);
output_fields_list_options(stderr);
- return 1;
+ exit_status = INVALID_OPTION;
+ goto clean_exit;
}
break;
"See https://www.wireshark.org for more information.\n",
get_ws_vcs_version_info());
print_usage(stdout);
- return 0;
+ goto clean_exit;
break;
case 'l': /* "Line-buffer" standard output */
- /* This isn't line-buffering, strictly speaking, it's just
- flushing the standard output after the information for
- each packet is printed; however, that should be good
- enough for all the purposes to which "-l" is put (and
- is probably actually better for "-V", as it does fewer
- writes).
-
- See the comment in "process_packet()" for an explanation of
- why we do that, and why we don't just use "setvbuf()" to
- make the standard output line-buffered (short version: in
- Windows, "line-buffered" is the same as "fully-buffered",
- and the output buffer is only flushed when it fills up). */
+ /* The ANSI C standard does not appear to *require* that a line-buffered
+ stream be flushed to the host environment whenever a newline is
+ written, it just says that, on such a stream, characters "are
+ intended to be transmitted to or from the host environment as a
+ block when a new-line character is encountered".
+
+ The Visual C++ 6.0 C implementation doesn't do what is intended;
+ even if you set a stream to be line-buffered, it still doesn't
+ flush the buffer at the end of every line.
+
+ The whole reason for the "-l" flag in either tcpdump or TShark
+ is to allow the output of a live capture to be piped to a program
+ or script and to have that script see the information for the
+ packet as soon as it's printed, rather than having to wait until
+ a standard I/O buffer fills up.
+
+ So, if the "-l" flag is specified, we flush the standard output
+ at the end of a packet. This will do the right thing if we're
+ printing packet summary lines, and, as we print the entire protocol
+ tree for a single packet without waiting for anything to happen,
+ it should be as good as line-buffered mode if we're printing
+ protocol trees - arguably even better, as it may do fewer
+ writes. */
line_buffered = TRUE;
break;
case 'o': /* Override preference from command line */
case PREFS_SET_NO_SUCH_PREF:
case PREFS_SET_OBSOLETE:
cmdarg_err("-o flag \"%s\" specifies unknown preference", optarg);
- return 1;
+ exit_status = INVALID_OPTION;
+ goto clean_exit;
break;
}
break;
case 'S': /* Set the line Separator to be printed between packets */
separator = g_strdup(optarg);
break;
- case 't': /* Time stamp type */
- if (strcmp(optarg, "r") == 0)
- timestamp_set_type(TS_RELATIVE);
- else if (strcmp(optarg, "a") == 0)
- timestamp_set_type(TS_ABSOLUTE);
- else if (strcmp(optarg, "ad") == 0)
- timestamp_set_type(TS_ABSOLUTE_WITH_YMD);
- else if (strcmp(optarg, "adoy") == 0)
- timestamp_set_type(TS_ABSOLUTE_WITH_YDOY);
- else if (strcmp(optarg, "d") == 0)
- timestamp_set_type(TS_DELTA);
- else if (strcmp(optarg, "dd") == 0)
- timestamp_set_type(TS_DELTA_DIS);
- else if (strcmp(optarg, "e") == 0)
- timestamp_set_type(TS_EPOCH);
- else if (strcmp(optarg, "u") == 0)
- timestamp_set_type(TS_UTC);
- else if (strcmp(optarg, "ud") == 0)
- timestamp_set_type(TS_UTC_WITH_YMD);
- else if (strcmp(optarg, "udoy") == 0)
- timestamp_set_type(TS_UTC_WITH_YDOY);
- else {
- cmdarg_err("Invalid time stamp type \"%s\"; it must be one of:", optarg);
- cmdarg_err_cont("\t\"a\" for absolute\n"
- "\t\"ad\" for absolute with YYYY-MM-DD date\n"
- "\t\"adoy\" for absolute with YYYY/DOY date\n"
- "\t\"d\" for delta\n"
- "\t\"dd\" for delta displayed\n"
- "\t\"e\" for epoch\n"
- "\t\"r\" for relative\n"
- "\t\"u\" for absolute UTC\n"
- "\t\"ud\" for absolute UTC with YYYY-MM-DD date\n"
- "\t\"udoy\" for absolute UTC with YYYY/DOY date");
- return 1;
- }
- break;
case 'T': /* printing Type */
if (strcmp(optarg, "text") == 0) {
output_action = WRITE_TEXT;
"\t packets, or a multi-line view of the details of each of the\n"
"\t packets, depending on whether the -V flag was specified.\n"
"\t This is the default.");
- return 1;
- }
- break;
- case 'u': /* Seconds type */
- if (strcmp(optarg, "s") == 0)
- timestamp_set_seconds_type(TS_SECONDS_DEFAULT);
- else if (strcmp(optarg, "hms") == 0)
- timestamp_set_seconds_type(TS_SECONDS_HOUR_MIN_SEC);
- else {
- cmdarg_err("Invalid seconds type \"%s\"; it must be one of:", optarg);
- cmdarg_err_cont("\t\"s\" for seconds\n"
- "\t\"hms\" for hours, minutes and seconds");
- return 1;
+ exit_status = INVALID_OPTION;
+ goto clean_exit;
}
break;
case 'v': /* Show version and exit */
show_version("TFShark (Wireshark)", comp_info_str, runtime_info_str);
g_string_free(comp_info_str, TRUE);
g_string_free(runtime_info_str, TRUE);
- /* We don't really have to cleanup here, but it's a convenient way to test
- * start-up and shut-down of the epan library without any UI-specific
- * cruft getting in the way. Makes the results of running
- * $ ./tools/valgrind-wireshark -n
- * much more useful. */
- epan_cleanup();
-#ifdef HAVE_EXTCAP
- extcap_cleanup();
-#endif
- return 0;
+ goto clean_exit;
case 'O': /* Only output these protocols */
/* already processed; just ignore it now */
break;
if (strcmp("help", optarg) == 0) {
fprintf(stderr, "tfshark: The available statistics for the \"-z\" option are:\n");
list_stat_cmd_args();
- return 0;
+ goto clean_exit;
}
if (!process_stat_cmd_arg(optarg)) {
cmdarg_err("Invalid -z argument \"%s\"; it must be one of:", optarg);
list_stat_cmd_args();
- return 1;
+ exit_status = INVALID_OPTION;
+ goto clean_exit;
+ }
+ break;
+ case 'd': /* Decode as rule */
+ case 'K': /* Kerberos keytab file */
+ case 't': /* Time stamp type */
+ case 'u': /* Seconds type */
+ case LONGOPT_DISABLE_PROTOCOL: /* disable dissection of protocol */
+ case LONGOPT_ENABLE_HEURISTIC: /* enable heuristic dissection of protocol */
+ case LONGOPT_DISABLE_HEURISTIC: /* disable heuristic dissection of protocol */
+ case LONGOPT_ENABLE_PROTOCOL: /* enable dissection of protocol (that is disabled by default) */
+ if (!dissect_opts_handle_opt(opt, optarg)) {
+ exit_status = INVALID_OPTION;
+ goto clean_exit;
}
break;
default:
case '?': /* Bad flag - print usage message */
print_usage(stderr);
- return 1;
+ exit_status = INVALID_OPTION;
+ goto clean_exit;
break;
}
}
cmdarg_err("\"-Tfields\" was specified, but no fields were "
"specified with \"-e\".");
- return 1;
+ exit_status = INVALID_OPTION;
+ goto clean_exit;
}
/* If no capture filter or display filter has been specified, and there are
if (dfilter != NULL) {
cmdarg_err("Display filters were specified both with \"-d\" "
"and with additional command-line arguments.");
- return 1;
+ exit_status = INVALID_OPTION;
+ goto clean_exit;
}
dfilter = get_args_as_string(argc, argv, optind);
}
if (arg_error) {
print_usage(stderr);
- return 1;
+ exit_status = INVALID_OPTION;
+ goto clean_exit;
}
if (print_hex) {
if (output_action != WRITE_TEXT) {
cmdarg_err("Raw packet hex data can only be printed as text or PostScript");
- return 1;
+ exit_status = INVALID_OPTION;
+ goto clean_exit;
}
}
if (!print_details) {
cmdarg_err("-O requires -V");
- return 1;
+ exit_status = INVALID_OPTION;
+ goto clean_exit;
}
output_only_tables = g_hash_table_new (g_str_hash, g_str_equal);
if (rfilter != NULL && !perform_two_pass_analysis) {
cmdarg_err("-R without -2 is deprecated. For single-pass filtering use -Y.");
- return 1;
+ exit_status = INVALID_OPTION;
+ goto clean_exit;
}
/* Notify all registered modules that have had any of their preferences
have a tap filter with one of MATE's late-registered fields as part
of the filter. We can now process all the "-z" arguments. */
start_requested_stats();
-
- /* disabled protocols as per configuration file */
- if (gdp_path == NULL && dp_path == NULL) {
- set_disabled_protos_list();
- set_disabled_heur_dissector_list();
+
+ /*
+ * Enabled and disabled protocols and heuristic dissectors as per
+ * command-line options.
+ */
+ if (!setup_enabled_and_disabled_protocols()) {
+ exit_status = INVALID_OPTION;
+ goto clean_exit;
}
/* Build the column format array */
if (!dfilter_compile(rfilter, &rfcode, &err_msg)) {
cmdarg_err("%s", err_msg);
g_free(err_msg);
- epan_cleanup();
-#ifdef HAVE_EXTCAP
- extcap_cleanup();
-#endif
- return 2;
+ exit_status = INVALID_FILTER;
+ goto clean_exit;
}
}
cfile.rfcode = rfcode;
if (!dfilter_compile(dfilter, &dfcode, &err_msg)) {
cmdarg_err("%s", err_msg);
g_free(err_msg);
- epan_cleanup();
-#ifdef HAVE_EXTCAP
- extcap_cleanup();
-#endif
- return 2;
+ exit_status = INVALID_FILTER;
+ goto clean_exit;
}
}
cfile.dfcode = dfcode;
/* TODO: if tfshark is ever changed to give the user a choice of which
open_routine reader to use, then the following needs to change. */
if (cf_open(&cfile, cf_name, WTAP_TYPE_AUTO, FALSE, &err) != CF_OK) {
- epan_cleanup();
-#ifdef HAVE_EXTCAP
- extcap_cleanup();
-#endif
- return 2;
+ exit_status = OPEN_ERROR;
+ goto clean_exit;
}
/* Process the packets in the file */
}
CATCH(OutOfMemoryError) {
fprintf(stderr,
- "Out Of Memory!\n"
+ "Out Of Memory.\n"
"\n"
- "Sorry, but TFShark has to terminate now!\n"
+ "Sorry, but TFShark has to terminate now.\n"
"\n"
"Some infos / workarounds can be found at:\n"
"https://wiki.wireshark.org/KnownBugs/OutOfMemory\n");
draw_tap_listeners(TRUE);
funnel_dump_all_text_windows();
+
+clean_exit:
+ destroy_print_stream(print_stream);
epan_free(cfile.epan);
epan_cleanup();
#ifdef HAVE_EXTCAP
output_fields_free(output_fields);
output_fields = NULL;
+ col_cleanup(&cfile.cinfo);
+ wtap_cleanup();
return exit_status;
}
static gboolean
process_packet_first_pass(capture_file *cf, epan_dissect_t *edt,
- gint64 offset, struct wtap_pkthdr *whdr,
- const guchar *pd)
+ gint64 offset, struct wtap_pkthdr *whdr,
+ const guchar *pd)
{
frame_data fdlocal;
guint32 framenum;
/* If we're running a read filter, prime the epan_dissect_t with that
filter. */
if (cf->rfcode)
- epan_dissect_prime_dfilter(edt, cf->rfcode);
+ epan_dissect_prime_with_dfilter(edt, cf->rfcode);
+
+ /* This is the first pass, so prime the epan_dissect_t with the
+ hfids postdissectors want on the first pass. */
+ prime_epan_dissect_with_postdissector_wanted_hfids(edt);
frame_data_set_before_dissect(&fdlocal, &cf->elapsed_time,
&ref, prev_dis);
}
static gboolean
-process_packet_second_pass(capture_file *cf, epan_dissect_t *edt, frame_data *fdata,
- struct wtap_pkthdr *phdr, Buffer *buf,
- guint tap_flags)
+process_packet_second_pass(capture_file *cf, epan_dissect_t *edt,
+ frame_data *fdata, struct wtap_pkthdr *phdr,
+ Buffer *buf, guint tap_flags)
{
column_info *cinfo;
gboolean passed;
/* If we're running a display filter, prime the epan_dissect_t with that
filter. */
if (cf->dfcode)
- epan_dissect_prime_dfilter(edt, cf->dfcode);
+ epan_dissect_prime_with_dfilter(edt, cf->dfcode);
+
+ /* This is the first and only pass, so prime the epan_dissect_t
+ with the hfids postdissectors want on the first pass. */
+ prime_epan_dissect_with_postdissector_wanted_hfids(edt);
col_custom_prime_edt(edt, &cf->cinfo);
this packet. */
print_packet(cf, edt);
- /* The ANSI C standard does not appear to *require* that a line-buffered
- stream be flushed to the host environment whenever a newline is
- written, it just says that, on such a stream, characters "are
- intended to be transmitted to or from the host environment as a
- block when a new-line character is encountered".
-
- The Visual C++ 6.0 C implementation doesn't do what is intended;
- even if you set a stream to be line-buffered, it still doesn't
- flush the buffer at the end of every line.
-
- So, if the "-l" flag was specified, we flush the standard output
- at the end of a packet. This will do the right thing if we're
- printing packet summary lines, and, as we print the entire protocol
- tree for a single packet without waiting for anything to happen,
- it should be as good as line-buffered mode if we're printing
- protocol trees. (The whole reason for the "-l" flag in either
- tcpdump or TShark is to allow the output of a live capture to
- be piped to a program or script and to have that script see the
- information for the packet as soon as it's printed, rather than
- having to wait until a standard I/O buffer fills up. */
+ /* If we're doing "line-buffering", flush the standard output
+ after every packet. See the comment above, for the "-l"
+ option, for an explanation of why we do that. */
if (line_buffered)
fflush(stdout);
if (ferror(stdout)) {
show_print_file_io_error(errno);
- exit(2);
+ return FALSE;
}
}
prev_dis = fdata;
cf->frames = new_frame_data_sequence();
if (do_dissection) {
- gboolean create_proto_tree = FALSE;
+ gboolean create_proto_tree;
- /* If we're going to be applying a filter, we'll need to
- create a protocol tree against which to apply the filter. */
- if (cf->rfcode)
- create_proto_tree = TRUE;
+ /*
+ * Determine whether we need to create a protocol tree.
+ * We do if:
+ *
+ * we're going to apply a read filter;
+ *
+ * a postdissector wants field values or protocols
+ * on the first pass.
+ */
+ create_proto_tree =
+ (cf->rfcode != NULL || postdissectors_want_hfids());
/* We're not going to display the protocol tree on this pass,
so it's not going to be "visible". */
}
while (local_wtap_read(cf, &file_phdr, &err, &err_info, &data_offset, &raw_data)) {
if (process_packet_first_pass(cf, edt, data_offset, &file_phdr/*wtap_phdr(cf->wth)*/,
- wtap_buf_ptr(cf->wth))) {
+ wtap_buf_ptr(cf->wth))) {
/* Stop reading if we have the maximum number of packets;
* When the -c option has not been used, max_packet_count
if (do_dissection) {
gboolean create_proto_tree;
- if (cf->dfcode || print_details || filtering_tap_listeners ||
- (tap_flags & TL_REQUIRES_PROTO_TREE) || have_custom_cols(&cf->cinfo))
- create_proto_tree = TRUE;
- else
- create_proto_tree = FALSE;
+ /*
+ * Determine whether we need to create a protocol tree.
+ * We do if:
+ *
+ * we're going to apply a display filter;
+ *
+ * we're going to print the protocol tree;
+ *
+ * one of the tap listeners requires a protocol tree;
+ *
+ * we have custom columns (which require field values, which
+ * currently requires that we build a protocol tree).
+ */
+ create_proto_tree =
+ (cf->dfcode || print_details || filtering_tap_listeners ||
+ (tap_flags & TL_REQUIRES_PROTO_TREE) || have_custom_cols(&cf->cinfo));
/* The protocol tree will be "visible", i.e., printed, only if we're
printing packet details, which is true if we're printing stuff
process_packet_second_pass(cf, edt, fdata, &cf->phdr, &buf, tap_flags);
}
#else
- process_packet_second_pass(cf, edt, fdata, &cf->phdr, &buf, tap_flags);
+ if (!process_packet_second_pass(cf, edt, fdata, &cf->phdr, &buf,
+ tap_flags))
+ return 2;
#endif
}
if (do_dissection) {
gboolean create_proto_tree;
- if (cf->rfcode || cf->dfcode || print_details || filtering_tap_listeners ||
- (tap_flags & TL_REQUIRES_PROTO_TREE) || have_custom_cols(&cf->cinfo))
- create_proto_tree = TRUE;
- else
- create_proto_tree = FALSE;
+ /*
+ * Determine whether we need to create a protocol tree.
+ * We do if:
+ *
+ * we're going to apply a read filter;
+ *
+ * we're going to apply a display filter;
+ *
+ * we're going to print the protocol tree;
+ *
+ * one of the tap listeners is going to apply a filter;
+ *
+ * one of the tap listeners requires a protocol tree;
+ *
+ * a postdissector wants field values or protocols
+ * on the first pass;
+ *
+ * we have custom columns (which require field values, which
+ * currently requires that we build a protocol tree).
+ */
+ create_proto_tree =
+ (cf->rfcode || cf->dfcode || print_details || filtering_tap_listeners ||
+ (tap_flags & TL_REQUIRES_PROTO_TREE) || postdissectors_want_hfids() ||
+ have_custom_cols(&cf->cinfo));
/* The protocol tree will be "visible", i.e., printed, only if we're
printing packet details, which is true if we're printing stuff
framenum++;
- process_packet(cf, edt, data_offset, &file_phdr/*wtap_phdr(cf->wth)*/,
- raw_data, tap_flags);
+ if (!process_packet_single_pass(cf, edt, data_offset,
+ &file_phdr/*wtap_phdr(cf->wth)*/,
+ raw_data, tap_flags))
+ return 2;
- /* Stop reading if we have the maximum number of packets;
- * When the -c option has not been used, max_packet_count
- * starts at 0, which practically means, never stop reading.
- * (unless we roll over max_packet_count ?)
- */
- if ( (--max_packet_count == 0) || (max_byte_count != 0 && data_offset >= max_byte_count)) {
- err = 0; /* This is not an error */
- break;
- }
+ /* Stop reading if we have the maximum number of packets;
+ * When the -c option has not been used, max_packet_count
+ * starts at 0, which practically means, never stop reading.
+ * (unless we roll over max_packet_count ?)
+ */
+ if ( (--max_packet_count == 0) || (max_byte_count != 0 && data_offset >= max_byte_count)) {
+ err = 0; /* This is not an error */
+ break;
+ }
}
if (edt) {
}
static gboolean
-process_packet(capture_file *cf, epan_dissect_t *edt, gint64 offset,
- struct wtap_pkthdr *whdr, const guchar *pd, guint tap_flags)
+process_packet_single_pass(capture_file *cf, epan_dissect_t *edt, gint64 offset,
+ struct wtap_pkthdr *whdr, const guchar *pd,
+ guint tap_flags)
{
frame_data fdata;
column_info *cinfo;
/* If we're running a filter, prime the epan_dissect_t with that
filter. */
if (cf->dfcode)
- epan_dissect_prime_dfilter(edt, cf->dfcode);
+ epan_dissect_prime_with_dfilter(edt, cf->dfcode);
col_custom_prime_edt(edt, &cf->cinfo);
this packet. */
print_packet(cf, edt);
- /* The ANSI C standard does not appear to *require* that a line-buffered
- stream be flushed to the host environment whenever a newline is
- written, it just says that, on such a stream, characters "are
- intended to be transmitted to or from the host environment as a
- block when a new-line character is encountered".
-
- The Visual C++ 6.0 C implementation doesn't do what is intended;
- even if you set a stream to be line-buffered, it still doesn't
- flush the buffer at the end of every line.
-
- So, if the "-l" flag was specified, we flush the standard output
- at the end of a packet. This will do the right thing if we're
- printing packet summary lines, and, as we print the entire protocol
- tree for a single packet without waiting for anything to happen,
- it should be as good as line-buffered mode if we're printing
- protocol trees. (The whole reason for the "-l" flag in either
- tcpdump or TShark is to allow the output of a live capture to
- be piped to a program or script and to have that script see the
- information for the packet as soon as it's printed, rather than
- having to wait until a standard I/O buffer fills up. */
+ /* If we're doing "line-buffering", flush the standard output
+ after every packet. See the comment above, for the "-l"
+ option, for an explanation of why we do that. */
if (line_buffered)
fflush(stdout);
if (ferror(stdout)) {
show_print_file_io_error(errno);
- exit(2);
+ return FALSE;
}
}
break;
case WRITE_XML:
- write_pdml_proto_tree(NULL, NULL, edt, stdout);
+ write_pdml_proto_tree(NULL, NULL, PF_NONE, edt, stdout);
printf("\n");
return !ferror(stdout);
case WRITE_FIELDS:
}
/*
- * Open/create errors are reported with an console message in TFShark.
+ * General errors and warnings are reported with an console message
+ * in TFShark.
*/
static void
-open_failure_message(const char *filename, int err, gboolean for_writing)
+failure_warning_message(const char *msg_format, va_list ap)
{
fprintf(stderr, "tfshark: ");
- fprintf(stderr, file_open_error_message(err, for_writing), filename);
+ vfprintf(stderr, msg_format, ap);
fprintf(stderr, "\n");
}
-
/*
- * General errors are reported with an console message in TFShark.
+ * Open/create errors are reported with an console message in TFShark.
*/
static void
-failure_message(const char *msg_format, va_list ap)
+open_failure_message(const char *filename, int err, gboolean for_writing)
{
fprintf(stderr, "tfshark: ");
- vfprintf(stderr, msg_format, ap);
+ fprintf(stderr, file_open_error_message(err, for_writing), filename);
fprintf(stderr, "\n");
}