* By Gerald Combs <gerald@wireshark.org>
* Copyright 1998 Gerald Combs
*
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License
- * as published by the Free Software Foundation; either version 2
- * of the License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ * SPDX-License-Identifier: GPL-2.0-or-later
*/
#include <config.h>
#include <glib.h>
#include <epan/exceptions.h>
-#include <epan/epan-int.h>
#include <epan/epan.h>
#include <wsutil/clopts_common.h>
#include <wsutil/filesystem.h>
#include <wsutil/file_util.h>
#include <wsutil/privileges.h>
-#include <wsutil/report_err.h>
-#include <ws_version_info.h>
+#include <wsutil/report_message.h>
+#include <version_info.h>
#include "globals.h"
#include <epan/timestamp.h>
#include <epan/addr_resolv.h>
#include "ui/util.h"
#include "ui/decode_as_utils.h"
-#include "register.h"
+#include "ui/dissect_opts.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 <wiretap/wtap-int.h>
#include <wiretap/file_wrappers.h>
#include <wsutil/plugins.h>
#endif
+#define INVALID_OPTION 1
+#define NO_FILE_SPECIFIED 1
+#define INIT_ERROR 2
+#define INVALID_FILTER 2
+#define OPEN_ERROR 2
+
+capture_file cfile;
+
static guint32 cum_bytes;
-static const frame_data *ref;
static frame_data ref_frame;
-static frame_data *prev_dis;
static frame_data prev_dis_frame;
-static frame_data *prev_cap;
static frame_data prev_cap_frame;
+static gboolean prefs_loaded = FALSE;
+
static gboolean perform_two_pass_analysis;
/*
/* The line separator used between packets, changeable via the -S option */
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_file(capture_file *, int, gint64);
+static gboolean process_packet_single_pass(capture_file *cf,
+ epan_dissect_t *edt, gint64 offset, wtap_rec *rec,
+ 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);
-capture_file cfile;
-
static GHashTable *output_only_tables = NULL;
#if 0
/*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);
{
/* ignore log message, if log_level isn't interesting based
upon the console log preferences.
- If the preferences haven't been loaded loaded yet, display the
+ If the preferences haven't been loaded yet, display the
message anyway.
The default console_log_level preference value is such that only
ERROR and CRITICAL level messages so the current code is a behavioral
change. The current behavior is the same as in Wireshark.
*/
- if ((log_level & G_LOG_LEVEL_MASK & prefs.console_log_level) == 0 &&
- prefs.console_log_level != 0) {
+ if (prefs_loaded && (log_level & G_LOG_LEVEL_MASK & prefs.console_log_level) == 0) {
return;
}
epan_get_runtime_version_info(str);
}
-int
-main(int argc, char *argv[])
+static int
+real_main(int argc, char *argv[])
{
GString *comp_info_str;
GString *runtime_info_str;
};
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 gboolean success;
volatile int exit_status = 0;
gboolean quiet = FALSE;
gchar *volatile cf_name = NULL;
*
* 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);
create_app_running_mutex();
-#if !GLIB_CHECK_VERSION(2,31,0)
- g_thread_init(NULL);
-#endif
#endif /* _WIN32 */
/*
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);
+ init_progfile_dir_error = init_progfile_dir(argv[0]);
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();
-
-#ifdef HAVE_PLUGINS
- /* Register all the plugin types we have. */
- epan_register_plugin_types(); /* Types known to libwireshark */
-
- /* Scan for plugins. This does *not* call their registration routines;
- that's done later. */
- scan_plugins(REPORT_LOAD_FAILURE);
-
-#endif
+ wtap_init(TRUE);
/* Register all dissectors; we must do this before checking for the
"-G" flag, as the "-G" flag dumps information registered by the
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;
+ if (!epan_init(NULL, NULL, TRUE)) {
+ 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();
+ prefs_loaded = TRUE;
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 */
- switch (prefs_set_pref(optarg)) {
+ {
+ char *errmsg = NULL;
+
+ switch (prefs_set_pref(optarg, &errmsg)) {
case PREFS_SET_OK:
break;
case PREFS_SET_SYNTAX_ERR:
- cmdarg_err("Invalid -o flag \"%s\"", optarg);
+ cmdarg_err("Invalid -o flag \"%s\"%s%s", optarg,
+ errmsg ? ": " : "", errmsg ? errmsg : "");
+ g_free(errmsg);
return 1;
break;
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 'q': /* Quiet */
quiet = TRUE;
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
- still command-line arguments, treat them as the tokens of a capture
- filter (if no "-r" flag was specified) or a display filter (if a "-r"
- flag was specified. */
+ /* We require a -r flag specifying a file to read. */
+ if (cf_name == NULL) {
+ cmdarg_err("A file to read must be specified with \"-r\".");
+ exit_status = NO_FILE_SPECIFIED;
+ goto clean_exit;
+ }
+
+ /* If no display filter has been specified, and there are still command-
+ line arguments, treat them as the tokens of a display filter. */
if (optind < argc) {
- if (cf_name != NULL) {
- if (dfilter != NULL) {
- cmdarg_err("Display filters were specified both with \"-d\" "
- "and with additional command-line arguments.");
- return 1;
- }
- dfilter = get_args_as_string(argc, argv, optind);
+ if (dfilter != NULL) {
+ cmdarg_err("Display filters were specified both with \"-d\" "
+ "and with additional command-line arguments.");
+ exit_status = INVALID_OPTION;
+ goto clean_exit;
}
+ dfilter = get_args_as_string(argc, argv, optind);
}
/* if "-q" wasn't specified, we should print packet information */
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
line that their preferences have changed. */
prefs_apply_all();
- /* At this point MATE will have registered its field array so we can
- 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;
we're using any taps that need dissection. */
do_dissection = print_packet_info || rfcode || dfcode || tap_listeners_require_dissection();
- if (cf_name) {
- /*
- * We're reading a capture file.
- */
+ /*
+ * Read the file.
+ */
- /* 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;
- }
+ /* 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) {
+ exit_status = OPEN_ERROR;
+ goto clean_exit;
+ }
- /* Process the packets in the file */
- TRY {
- /* XXX - for now there is only 1 packet */
- err = load_cap_file(&cfile, 1, 0);
- }
- CATCH(OutOfMemoryError) {
- fprintf(stderr,
- "Out Of Memory!\n"
- "\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");
- err = ENOMEM;
- }
- ENDTRY;
+ /* Start statistics taps; we do so after successfully opening the
+ capture file, so we know we have something to compute stats
+ on, and after registering all dissectors, so that MATE will
+ have registered its field array so we can have a tap filter
+ with one of MATE's late-registered fields as part of the
+ filter. */
+ start_requested_stats();
- if (err != 0) {
- /* We still dump out the results of taps, etc., as we might have
- read some packets; however, we exit with an error status. */
- exit_status = 2;
- }
+ /* Process the packets in the file */
+ TRY {
+ /* XXX - for now there is only 1 packet */
+ success = process_file(&cfile, 1, 0);
+ }
+ CATCH(OutOfMemoryError) {
+ fprintf(stderr,
+ "Out Of Memory.\n"
+ "\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");
+ success = FALSE;
+ }
+ ENDTRY;
+
+ if (!success) {
+ /* We still dump out the results of taps, etc., as we might have
+ read some packets; however, we exit with an error status. */
+ exit_status = 2;
}
g_free(cf_name);
- if (cfile.frames != NULL) {
- free_frame_data_sequence(cfile.frames);
- cfile.frames = NULL;
+ if (cfile.provider.frames != NULL) {
+ free_frame_data_sequence(cfile.provider.frames);
+ cfile.provider.frames = NULL;
}
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
extcap_cleanup();
-#endif
output_fields_free(output_fields);
output_fields = NULL;
+ col_cleanup(&cfile.cinfo);
+ wtap_cleanup();
return exit_status;
}
-static const nstime_t *
-tfshark_get_frame_ts(void *data, guint32 frame_num)
+#ifdef _WIN32
+int
+wmain(int argc, wchar_t *wc_argv[])
{
- capture_file *cf = (capture_file *) data;
+ char **argv;
- if (ref && ref->num == frame_num)
- return &ref->abs_ts;
+ argv = arg_list_utf_16to8(argc, wc_argv);
+ return real_main(argc, argv);
+}
+#else
+int
+main(int argc, char *argv[])
+{
+ return real_main(argc, argv);
+}
+#endif
+
+static const nstime_t *
+tfshark_get_frame_ts(struct packet_provider_data *prov, guint32 frame_num)
+{
+ if (prov->ref && prov->ref->num == frame_num)
+ return &prov->ref->abs_ts;
- if (prev_dis && prev_dis->num == frame_num)
- return &prev_dis->abs_ts;
+ if (prov->prev_dis && prov->prev_dis->num == frame_num)
+ return &prov->prev_dis->abs_ts;
- if (prev_cap && prev_cap->num == frame_num)
- return &prev_cap->abs_ts;
+ if (prov->prev_cap && prov->prev_cap->num == frame_num)
+ return &prov->prev_cap->abs_ts;
- if (cf->frames) {
- frame_data *fd = frame_data_sequence_find(cf->frames, frame_num);
+ if (prov->frames) {
+ frame_data *fd = frame_data_sequence_find(prov->frames, frame_num);
return (fd) ? &fd->abs_ts : NULL;
}
}
static const char *
-no_interface_name(void *data _U_, guint32 interface_id _U_)
+no_interface_name(struct packet_provider_data *prov _U_, guint32 interface_id _U_)
{
return "";
}
static epan_t *
tfshark_epan_new(capture_file *cf)
{
- epan_t *epan = epan_new();
-
- epan->data = cf;
- epan->get_frame_ts = tfshark_get_frame_ts;
- epan->get_interface_name = no_interface_name;
- epan->get_user_comment = NULL;
+ static const struct packet_provider_funcs funcs = {
+ tfshark_get_frame_ts,
+ no_interface_name,
+ NULL,
+ NULL,
+ };
- return epan;
+ return epan_new(&cf->provider, &funcs);
}
static gboolean
process_packet_first_pass(capture_file *cf, epan_dissect_t *edt,
- gint64 offset, struct wtap_pkthdr *whdr,
- const guchar *pd)
+ gint64 offset, wtap_rec *rec,
+ const guchar *pd)
{
frame_data fdlocal;
guint32 framenum;
that all packets can be marked as 'passed'. */
passed = TRUE;
- frame_data_init(&fdlocal, framenum, whdr, offset, cum_bytes);
+ frame_data_init(&fdlocal, framenum, rec, offset, cum_bytes);
/* If we're going to print packet information, or we're going to
run a read filter, or display filter, or we're going to process taps, set up to
/* 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);
- if (ref == &fdlocal) {
+ &cf->provider.ref, cf->provider.prev_dis);
+ if (cf->provider.ref == &fdlocal) {
ref_frame = fdlocal;
- ref = &ref_frame;
+ cf->provider.ref = &ref_frame;
}
- epan_dissect_file_run(edt, whdr, file_tvbuff_new(&fdlocal, pd), &fdlocal, NULL);
+ epan_dissect_file_run(edt, rec,
+ file_tvbuff_new(&cf->provider, &fdlocal, pd),
+ &fdlocal, NULL);
/* Run the read filter if we have one. */
if (cf->rfcode)
if (passed) {
frame_data_set_after_dissect(&fdlocal, &cum_bytes);
- prev_cap = prev_dis = frame_data_sequence_add(cf->frames, &fdlocal);
+ cf->provider.prev_cap = cf->provider.prev_dis = frame_data_sequence_add(cf->provider.frames, &fdlocal);
/* If we're not doing dissection then there won't be any dependent frames.
* More importantly, edt.pi.dependent_frames won't be initialized because
* epan hasn't been initialized.
*/
if (edt) {
- g_slist_foreach(edt->pi.dependent_frames, find_and_mark_frame_depended_upon, cf->frames);
+ g_slist_foreach(edt->pi.dependent_frames, find_and_mark_frame_depended_upon, cf->provider.frames);
}
cf->count++;
}
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, wtap_rec *rec,
+ 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);
cinfo = NULL;
frame_data_set_before_dissect(fdata, &cf->elapsed_time,
- &ref, prev_dis);
- if (ref == fdata) {
+ &cf->provider.ref, cf->provider.prev_dis);
+ if (cf->provider.ref == fdata) {
ref_frame = *fdata;
- ref = &ref_frame;
+ cf->provider.ref = &ref_frame;
}
- epan_dissect_file_run_with_taps(edt, phdr, file_tvbuff_new_buffer(fdata, buf), fdata, cinfo);
+ epan_dissect_file_run_with_taps(edt, rec,
+ file_tvbuff_new_buffer(&cf->provider, fdata, buf), fdata, cinfo);
/* Run the read/display filter if we have one. */
if (cf->dfcode)
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->provider.prev_dis = fdata;
}
- prev_cap = fdata;
+ cf->provider.prev_cap = fdata;
if (edt) {
epan_dissect_reset(edt);
}
static gboolean
-local_wtap_read(capture_file *cf, struct wtap_pkthdr* file_phdr _U_, int *err, gchar **err_info _U_, gint64 *data_offset _U_, guint8** data_buffer)
+local_wtap_read(capture_file *cf, wtap_rec *file_rec _U_, int *err, gchar **err_info _U_, gint64 *data_offset _U_, guint8** data_buffer)
{
/* int bytes_read; */
- gint64 packet_size = wtap_file_size(cf->wth, err);
+ gint64 packet_size = wtap_file_size(cf->provider.wth, err);
*data_buffer = (guint8*)g_malloc((gsize)packet_size);
- /* bytes_read =*/ file_read(*data_buffer, (unsigned int)packet_size, cf->wth->fh);
+ /* bytes_read =*/ file_read(*data_buffer, (unsigned int)packet_size, cf->provider.wth->fh);
#if 0 /* no more filetap */
if (bytes_read < 0) {
- *err = file_error(cf->wth->fh, err_info);
+ *err = file_error(cf->provider.wth->fh, err_info);
if (*err == 0)
*err = FTAP_ERR_SHORT_READ;
return FALSE;
/* XXX - SET FRAME SIZE EQUAL TO TOTAL FILE SIZE */
- file_phdr->caplen = (guint32)packet_size;
- file_phdr->len = (guint32)packet_size;
+ file_rec->rec_header.packet_header.caplen = (guint32)packet_size;
+ file_rec->rec_header.packet_header.len = (guint32)packet_size;
/*
* Set the packet encapsulation to the file's encapsulation
* *is* WTAP_ENCAP_PER_PACKET, the caller needs to set it
* anyway.
*/
- wth->phdr.pkt_encap = wth->file_encap;
+ wth->rec.rec_header.packet_header.pkt_encap = wth->file_encap;
if (!wth->subtype_read(wth, err, err_info, data_offset)) {
/*
* It makes no sense for the captured data length to be bigger
* than the actual data length.
*/
- if (wth->phdr.caplen > wth->phdr.len)
- wth->phdr.caplen = wth->phdr.len;
+ if (wth->rec.rec_header.packet_header.caplen > wth->rec.rec_header.packet_header.len)
+ wth->rec.rec_header.packet_header.caplen = wth->rec.rec_header.packet_header.len;
/*
* Make sure that it's not WTAP_ENCAP_PER_PACKET, as that
* but the read routine didn't set this packet's
* encapsulation type.
*/
- g_assert(wth->phdr.pkt_encap != WTAP_ENCAP_PER_PACKET);
+ g_assert(wth->rec.rec_header.packet_header.pkt_encap != WTAP_ENCAP_PER_PACKET);
#endif
return TRUE; /* success */
}
-static int
-load_cap_file(capture_file *cf, int max_packet_count, gint64 max_byte_count)
+static gboolean
+process_file(capture_file *cf, int max_packet_count, gint64 max_byte_count)
{
guint32 framenum;
int err;
guint tap_flags;
Buffer buf;
epan_dissect_t *edt = NULL;
- struct wtap_pkthdr file_phdr;
+ wtap_rec file_rec;
guint8* raw_data;
if (print_packet_info) {
/* Get the union of the flags for all tap listeners. */
tap_flags = union_of_tap_listener_flags();
- wtap_phdr_init(&file_phdr);
+ wtap_rec_init(&file_rec);
/* XXX - TEMPORARY HACK TO ELF DISSECTOR */
- file_phdr.pkt_encap = 1234;
+ file_rec.rec_header.packet_header.pkt_encap = 1234;
if (perform_two_pass_analysis) {
frame_data *fdata;
/* Allocate a frame_data_sequence for all the frames. */
- cf->frames = new_frame_data_sequence();
+ cf->provider.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". */
edt = epan_dissect_new(cf->epan, create_proto_tree, FALSE);
}
- 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))) {
+ while (local_wtap_read(cf, &file_rec, &err, &err_info, &data_offset, &raw_data)) {
+ if (process_packet_first_pass(cf, edt, data_offset, &file_rec/*wtap_get_rec(cf->provider.wth)*/,
+ wtap_get_buf_ptr(cf->provider.wth))) {
/* Stop reading if we have the maximum number of packets;
* When the -c option has not been used, max_packet_count
#if 0
/* Close the sequential I/O side, to free up memory it requires. */
- wtap_sequential_close(cf->wth);
+ wtap_sequential_close(cf->provider.wth);
#endif
/* Allow the protocol dissectors to free up memory that they
* don't need after the sequential run-through of the packets. */
postseq_cleanup_all_protocols();
- prev_dis = NULL;
- prev_cap = NULL;
+ cf->provider.prev_dis = NULL;
+ cf->provider.prev_cap = NULL;
ws_buffer_init(&buf, 1500);
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
}
for (framenum = 1; err == 0 && framenum <= cf->count; framenum++) {
- fdata = frame_data_sequence_find(cf->frames, framenum);
+ fdata = frame_data_sequence_find(cf->provider.frames, framenum);
#if 0
- if (wtap_seek_read(cf->wth, fdata->file_off,
+ if (wtap_seek_read(cf->provider.wth, fdata->file_off,
&buf, fdata->cap_len, &err, &err_info)) {
- process_packet_second_pass(cf, edt, fdata, &cf->phdr, &buf, tap_flags);
+ process_packet_second_pass(cf, edt, fdata, &cf->rec, &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->rec, &buf,
+ tap_flags))
+ return FALSE;
#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
edt = epan_dissect_new(cf->epan, create_proto_tree, print_packet_info && print_details);
}
- while (local_wtap_read(cf, &file_phdr, &err, &err_info, &data_offset, &raw_data)) {
+ while (local_wtap_read(cf, &file_rec, &err, &err_info, &data_offset, &raw_data)) {
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_rec/*wtap_get_rec(cf->provider.wth)*/,
+ raw_data, tap_flags))
+ return FALSE;
- /* 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) {
}
}
- wtap_phdr_cleanup(&file_phdr);
+ wtap_rec_cleanup(&file_rec);
if (err != 0) {
/*
}
out:
- wtap_close(cf->wth);
- cf->wth = NULL;
+ wtap_close(cf->provider.wth);
+ cf->provider.wth = NULL;
- return err;
+ return (err != 0);
}
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,
+ wtap_rec *rec, const guchar *pd,
+ guint tap_flags)
{
frame_data fdata;
column_info *cinfo;
that all packets can be marked as 'passed'. */
passed = TRUE;
- frame_data_init(&fdata, cf->count, whdr, offset, cum_bytes);
+ frame_data_init(&fdata, cf->count, rec, offset, cum_bytes);
/* If we're going to print packet information, or we're going to
run a read filter, or we're going to process taps, set up to
/* 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);
cinfo = NULL;
frame_data_set_before_dissect(&fdata, &cf->elapsed_time,
- &ref, prev_dis);
- if (ref == &fdata) {
+ &cf->provider.ref, cf->provider.prev_dis);
+ if (cf->provider.ref == &fdata) {
ref_frame = fdata;
- ref = &ref_frame;
+ cf->provider.ref = &ref_frame;
}
- epan_dissect_file_run_with_taps(edt, whdr, frame_tvbuff_new(&fdata, pd), &fdata, cinfo);
+ epan_dissect_file_run_with_taps(edt, rec,
+ frame_tvbuff_new(&cf->provider, &fdata, pd),
+ &fdata, cinfo);
/* Run the filter if we have it. */
if (cf->dfcode)
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;
}
}
/* this must be set after print_packet() [bug #8160] */
prev_dis_frame = fdata;
- prev_dis = &prev_dis_frame;
+ cf->provider.prev_dis = &prev_dis_frame;
}
prev_cap_frame = fdata;
- prev_cap = &prev_cap_frame;
+ cf->provider.prev_cap = &prev_cap_frame;
if (edt) {
epan_dissect_reset(edt);
static gboolean
print_packet(capture_file *cf, epan_dissect_t *edt)
{
- print_args_t print_args;
-
if (print_summary || output_fields_has_cols(output_fields)) {
/* Just fill in the columns. */
epan_dissect_fill_in_columns(edt, FALSE, TRUE);
break;
case WRITE_XML:
- write_psml_columns(edt, stdout);
+ write_psml_columns(edt, stdout, FALSE);
return !ferror(stdout);
case WRITE_FIELDS: /*No non-verbose "fields" format */
g_assert_not_reached();
switch (output_action) {
case WRITE_TEXT:
- /* Only initialize the fields that are actually used in proto_tree_print.
- * This is particularly important for .range, as that's heap memory which
- * we would otherwise have to g_free().
- print_args.to_file = TRUE;
- print_args.format = print_format;
- print_args.print_summary = print_summary;
- print_args.print_formfeed = FALSE;
- packet_range_init(&print_args.range, &cfile);
- */
- print_args.print_hex = print_hex;
- print_args.print_dissections = print_details ? print_dissections_expanded : print_dissections_none;
-
- if (!proto_tree_print(&print_args, edt, output_only_tables, print_stream))
+ if (!proto_tree_print(print_details ? print_dissections_expanded : print_dissections_none,
+ print_hex, edt, output_only_tables, print_stream))
return FALSE;
if (!print_hex) {
if (!print_line(print_stream, 0, separator))
break;
case WRITE_XML:
- write_pdml_proto_tree(NULL, NULL, edt, stdout);
+ write_pdml_proto_tree(NULL, NULL, PF_NONE, edt, &cf->cinfo, stdout, FALSE);
printf("\n");
return !ferror(stdout);
case WRITE_FIELDS:
epan_free(cf->epan);
cf->epan = tfshark_epan_new(cf);
- cf->wth = NULL; /**** XXX - DOESN'T WORK RIGHT NOW!!!! */
+ cf->provider.wth = NULL; /**** XXX - DOESN'T WORK RIGHT NOW!!!! */
cf->f_datalen = 0; /* not used, but set it anyway */
/* Set the file name because we need it to set the follow stream filter.
cf->drops_known = FALSE;
cf->drops = 0;
cf->snap = 0; /**** XXX - DOESN'T WORK RIGHT NOW!!!! */
- if (cf->snap == 0) {
- /* Snapshot length not known. */
- cf->has_snap = FALSE;
- cf->snap = 0;
- } else
- cf->has_snap = TRUE;
nstime_set_zero(&cf->elapsed_time);
- ref = NULL;
- prev_dis = NULL;
- prev_cap = NULL;
+ cf->provider.ref = NULL;
+ cf->provider.prev_dis = NULL;
+ cf->provider.prev_cap = NULL;
cf->state = FILE_READ_IN_PROGRESS;
}
/*
- * 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");
}