#include <errno.h>
+#ifdef HAVE_WINSOCK2_H
+# include <winsock2.h>
+#endif
+
#ifndef _WIN32
#include <signal.h>
#endif
#define INVALID_CAPABILITY 2
#define INVALID_TAP 2
#define INVALID_DATA_LINK 2
+#define INVALID_TIMESTAMP_TYPE 2
#define INVALID_CAPTURE 2
#define INIT_FAILED 2
+/*
+ * values 128..65535 are capture+dissect options, 65536 is used by
+ * ui/commandline.c, so start tshark-specific options 1000 after this
+ */
+#define LONGOPT_COLOR (65536+1000)
+#define LONGOPT_NO_DUPLICATE_KEYS (65536+1001)
+
#if 0
#define tshark_debug(...) g_warning(__VA_ARGS__)
#else
static frame_data prev_cap_frame;
static gboolean perform_two_pass_analysis;
+static guint32 epan_auto_reset_count = 0;
+static gboolean epan_auto_reset = FALSE;
/*
* The way the packet decode is to be written.
static gboolean line_buffered;
static gboolean really_quiet = FALSE;
static gchar* delimiter_char = " ";
+static gboolean dissect_color = FALSE;
static print_format_e print_format = PR_FMT_TEXT;
static print_stream_t *print_stream = NULL;
static gchar **protocolfilter = NULL;
static pf_flags protocolfilter_flags = PF_NONE;
+static gboolean no_duplicate_keys = FALSE;
+static proto_node_children_grouper_func node_children_grouper = proto_node_group_children_by_unique;
+
/* The line separator used between packets, changeable via the -S option */
static const char *separator = "";
#endif /* HAVE_LIBPCAP */
-static int read_cap_file(capture_file *, char *, int, gboolean, int, gint64);
+static void reset_epan_mem(capture_file *cf, epan_dissect_t *edt, gboolean tree, gboolean visual);
+static gboolean process_cap_file(capture_file *, char *, int, gboolean, int, gint64);
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);
fprintf(output, "Capture interface:\n");
fprintf(output, " -i <interface> name or idx of interface (def: first non-loopback)\n");
fprintf(output, " -f <capture filter> packet filter in libpcap filter syntax\n");
- fprintf(output, " -s <snaplen> packet snapshot length (def: %u)\n", WTAP_MAX_PACKET_SIZE);
+#ifdef HAVE_PCAP_CREATE
+ fprintf(output, " -s <snaplen> packet snapshot length (def: appropriate maximum)\n");
+#else
+ fprintf(output, " -s <snaplen> packet snapshot length (def: %u)\n", WTAP_MAX_PACKET_SIZE_STANDARD);
+#endif
fprintf(output, " -p don't capture in promiscuous mode\n");
#ifdef HAVE_PCAP_CREATE
fprintf(output, " -I capture in monitor mode, if available\n");
fprintf(output, " -B <buffer size> size of kernel buffer (def: %dMB)\n", DEFAULT_CAPTURE_BUFFER_SIZE);
#endif
fprintf(output, " -y <link type> link layer type (def: first appropriate)\n");
+ fprintf(output, " --time-stamp-type <type> timestamp method for interface\n");
fprintf(output, " -D print list of interfaces and exit\n");
fprintf(output, " -L print list of link-layer types of iface and exit\n");
+ fprintf(output, " --list-time-stamp-types print list of timestamp types for iface and exit\n");
fprintf(output, "\n");
fprintf(output, "Capture stop conditions:\n");
fprintf(output, " -c <packet count> stop after n packets (def: infinite)\n");
/*fprintf(output, "\n");*/
fprintf(output, "Capture output:\n");
fprintf(output, " -b <ringbuffer opt.> ... duration:NUM - switch to next file after NUM secs\n");
+ fprintf(output, " interval:NUM - create time intervals of NUM secs\n");
fprintf(output, " filesize:NUM - switch to next file after NUM KB\n");
fprintf(output, " files:NUM - ringbuffer: replace after NUM files\n");
#endif /* HAVE_LIBPCAP */
fprintf(output, "\n");
fprintf(output, "Processing:\n");
fprintf(output, " -2 perform a two-pass analysis\n");
+ fprintf(output, " -M <packet count> perform session auto reset\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, " output file (only for pcapng)\n");
fprintf(output, " --export-objects <protocol>,<destdir> save exported objects for a protocol to\n");
fprintf(output, " a directory named \"destdir\"\n");
+ fprintf(output, " --color color output text similarly to the Wireshark GUI,\n");
+ fprintf(output, " requires a terminal with 24-bit color support\n");
+ fprintf(output, " Also supplies color attributes to pdml and psml formats\n");
+ fprintf(output, " (Note that attributes are nonstandard)\n");
+ fprintf(output, " --no-duplicate-keys If -T json is specified, merge duplicate keys in an object\n");
+ fprintf(output, " into a single key with as value a json array containing all\n");
+ fprintf(output, " values");
fprintf(output, "\n");
fprintf(output, "Miscellaneous:\n");
LONGOPT_CAPTURE_COMMON
LONGOPT_DISSECT_COMMON
{"export-objects", required_argument, NULL, LONGOPT_EXPORT_OBJECTS},
+ {"color", no_argument, NULL, LONGOPT_COLOR},
+ {"no-duplicate-keys", no_argument, NULL, LONGOPT_NO_DUPLICATE_KEYS},
{0, 0, 0, 0 }
};
gboolean arg_error = FALSE;
#endif /* _WIN32 */
int err;
+ volatile gboolean success;
volatile int exit_status = EXIT_SUCCESS;
#ifdef HAVE_LIBPCAP
- gboolean list_link_layer_types = FALSE;
+ int caps_queries = 0;
gboolean start_capture = FALSE;
GList *if_list;
gchar *err_str;
* We do *not* use a leading - because the behavior of a leading - is
* platform-dependent.
*/
-#define OPTSTRING "+2" OPTSTRING_CAPTURE_COMMON OPTSTRING_DISSECT_COMMON "C:e:E:F:gG:hH:j:J:lo:O:PqQr:R:S:T:U:vVw:W:xX:Y:z:"
+#define OPTSTRING "+2" OPTSTRING_CAPTURE_COMMON OPTSTRING_DISSECT_COMMON "M:C:e:E:F:gG:hH:j:J:lo:O:PqQr:R:S:T:U:vVw:W:xX:Y:z:"
static const char optstring[] = OPTSTRING;
#ifdef _WIN32
ws_init_dll_search_path();
+#ifdef HAVE_LIBPCAP
/* Load wpcap if possible. Do this before collecting the run-time version information */
load_wpcap();
fprintf(stderr, "The NPF driver isn't running. You may have trouble "
"capturing or\nlisting interfaces.\n");
}
-#endif
+#endif /* HAVE_LIBPCAP */
+#endif /* _WIN32 */
/* Get the compile-time version information string */
comp_info_str = get_compiled_version_info(get_tshark_compiled_version_info,
while ((opt = getopt_long(argc, argv, optstring, long_options, NULL)) != -1) {
switch (opt) {
case '2': /* Perform two pass analysis */
+ if(epan_auto_reset){
+ cmdarg_err("-2 does not support auto session reset.");
+ arg_error=TRUE;
+ }
perform_two_pass_analysis = TRUE;
break;
+ case 'M':
+ if(perform_two_pass_analysis){
+ cmdarg_err("-M does not support two pass analysis.");
+ arg_error=TRUE;
+ }
+ epan_auto_reset_count = get_positive_int(optarg, "epan reset count");
+ epan_auto_reset = TRUE;
+ break;
case 'a': /* autostop criteria */
case 'b': /* Ringbuffer option */
case 'c': /* Capture x packets */
case 'f': /* capture filter */
case 'g': /* enable group read access on file(s) */
case 'i': /* Use interface x */
+ case LONGOPT_SET_TSTAMP_TYPE: /* Set capture timestamp type */
case 'p': /* Don't capture in promiscuous mode */
#ifdef HAVE_PCAP_REMOTE
case 'A': /* Authentication */
break;
case 'L': /* Print list of link-layer types and exit */
#ifdef HAVE_LIBPCAP
- list_link_layer_types = TRUE;
+ caps_queries |= CAPS_QUERY_LINK_TYPES;
+#else
+ capture_option_specified = TRUE;
+ arg_error = TRUE;
+#endif
+ break;
+ case LONGOPT_LIST_TSTAMP_TYPES: /* List possible timestamp types */
+#ifdef HAVE_LIBPCAP
+ caps_queries |= CAPS_QUERY_TIMESTAMP_TYPES;
#else
capture_option_specified = TRUE;
arg_error = TRUE;
#endif
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);
exit_status = INVALID_OPTION;
goto clean_exit;
break;
break;
}
break;
+ }
case 'q': /* Quiet */
quiet = TRUE;
break;
goto clean_exit;
}
break;
+ case LONGOPT_COLOR: /* print in color where appropriate */
+ dissect_color = TRUE;
+ break;
+ case LONGOPT_NO_DUPLICATE_KEYS:
+ no_duplicate_keys = TRUE;
+ node_children_grouper = proto_node_group_children_by_json_key;
+ break;
default:
case '?': /* Bad flag - print usage message */
switch(optopt) {
}
}
+ if (no_duplicate_keys && output_action != WRITE_JSON && output_action != WRITE_JSON_RAW) {
+ cmdarg_err("--no-duplicate-keys can only be used with \"-T json\" and \"-T jsonraw\"");
+ exit_status = INVALID_OPTION;
+ goto clean_exit;
+ }
+
/* If we specified output fields, but not the output field type... */
if ((WRITE_FIELDS != output_action && WRITE_XML != output_action && WRITE_JSON != output_action && WRITE_EK != output_action) && 0 != output_fields_num_fields(output_fields)) {
cmdarg_err("Output fields were specified with \"-e\", "
goto clean_exit;
}
+ if (dissect_color) {
+ if (!color_filters_init(&err_msg, NULL)) {
+ fprintf(stderr, "%s\n", err_msg);
+ g_free(err_msg);
+ }
+ }
+
/* 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"
goto clean_exit;
}
for (i = 0; i < global_capture_opts.ifaces->len; i++) {
- interface_options interface_opts;
- interface_opts = g_array_index(global_capture_opts.ifaces, interface_options, i);
- if (interface_opts.cfilter == NULL) {
- interface_opts.cfilter = get_args_as_string(argc, argv, optind);
- global_capture_opts.ifaces = g_array_remove_index(global_capture_opts.ifaces, i);
- g_array_insert_val(global_capture_opts.ifaces, i, interface_opts);
+ interface_options *interface_opts;
+ interface_opts = &g_array_index(global_capture_opts.ifaces, interface_options, i);
+ if (interface_opts->cfilter == NULL) {
+ interface_opts->cfilter = get_args_as_string(argc, argv, optind);
} else {
cmdarg_err("A capture filter was specified both with \"-f\""
" and with additional command-line arguments.");
}
#ifdef HAVE_LIBPCAP
- if (list_link_layer_types) {
- /* We're supposed to list the link-layer types for an interface;
+ if (caps_queries) {
+ /* We're supposed to list the link-layer/timestamp types for an interface;
did the user also specify a capture file to be read? */
if (cf_name) {
/* Yes - that's bogus. */
- cmdarg_err("You can't specify -L and a capture file to be read.");
+ cmdarg_err("You can't specify %s and a capture file to be read.",
+ caps_queries & CAPS_QUERY_LINK_TYPES ? "-L" : "--list-time-stamp-types");
exit_status = INVALID_OPTION;
goto clean_exit;
}
goto clean_exit;
}
if (global_capture_opts.has_file_duration) {
+ cmdarg_err("Switching capture files after a time period was specified, but "
+ "a capture isn't being done.");
+ exit_status = INVALID_OPTION;
+ goto clean_exit;
+ }
+ if (global_capture_opts.has_file_interval) {
cmdarg_err("Switching capture files after a time interval was specified, but "
"a capture isn't being done.");
exit_status = INVALID_OPTION;
goto clean_exit;
}
if (!global_capture_opts.has_autostop_filesize &&
- !global_capture_opts.has_file_duration) {
+ !global_capture_opts.has_file_duration &&
+ !global_capture_opts.has_file_interval) {
cmdarg_err("Multiple capture files requested, but "
- "no maximum capture file size or duration was specified.");
+ "no maximum capture file size, duration or interval was specified.");
exit_status = INVALID_OPTION;
goto clean_exit;
}
we're using any taps that need dissection. */
do_dissection = print_packet_info || rfcode || dfcode || pdu_export_arg ||
- tap_listeners_require_dissection();
+ tap_listeners_require_dissection() || dissect_color;
tshark_debug("tshark: do_dissection = %s", do_dissection ? "TRUE" : "FALSE");
if (cf_name) {
}
/* Process the packets in the file */
- tshark_debug("tshark: invoking read_cap_file() to process the packets");
+ tshark_debug("tshark: invoking process_cap_file() to process the packets");
TRY {
#ifdef HAVE_LIBPCAP
- err = read_cap_file(&cfile, global_capture_opts.save_file, out_file_type, out_file_name_res,
+ success = process_cap_file(&cfile, global_capture_opts.save_file, out_file_type, out_file_name_res,
global_capture_opts.has_autostop_packets ? global_capture_opts.autostop_packets : 0,
global_capture_opts.has_autostop_filesize ? global_capture_opts.autostop_filesize : 0);
#else
- err = read_cap_file(&cfile, output_file_name, out_file_type, out_file_name_res, 0, 0);
+ success = process_cap_file(&cfile, output_file_name, out_file_type, out_file_name_res, 0, 0);
#endif
}
CATCH(OutOfMemoryError) {
"\n"
"More information and workarounds can be found at\n"
"https://wiki.wireshark.org/KnownBugs/OutOfMemory\n");
- err = ENOMEM;
+ success = FALSE;
}
ENDTRY;
- if (err != 0) {
+
+ 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;
}
/* if requested, list the link layer types and exit */
- if (list_link_layer_types) {
+ if (caps_queries) {
guint i;
/* Get the list of link-layer types for the capture devices. */
for (i = 0; i < global_capture_opts.ifaces->len; i++) {
- interface_options interface_opts;
+ interface_options *interface_opts;
if_capabilities_t *caps;
char *auth_str = NULL;
+ int if_caps_queries = caps_queries;
- interface_opts = g_array_index(global_capture_opts.ifaces, interface_options, i);
+ interface_opts = &g_array_index(global_capture_opts.ifaces, interface_options, i);
#ifdef HAVE_PCAP_REMOTE
- if (interface_opts.auth_type == CAPTURE_AUTH_PWD) {
- auth_str = g_strdup_printf("%s:%s", interface_opts.auth_username, interface_opts.auth_password);
+ if (interface_opts->auth_type == CAPTURE_AUTH_PWD) {
+ auth_str = g_strdup_printf("%s:%s", interface_opts->auth_username, interface_opts->auth_password);
}
#endif
- caps = capture_get_if_capabilities(interface_opts.name, interface_opts.monitor_mode, auth_str, &err_str, NULL);
+ caps = capture_get_if_capabilities(interface_opts->name, interface_opts->monitor_mode, auth_str, &err_str, NULL);
g_free(auth_str);
if (caps == NULL) {
cmdarg_err("%s", err_str);
exit_status = INVALID_CAPABILITY;
goto clean_exit;
}
- if (caps->data_link_types == NULL) {
- cmdarg_err("The capture device \"%s\" has no data link types.", interface_opts.name);
+ if ((if_caps_queries & CAPS_QUERY_LINK_TYPES) && caps->data_link_types == NULL) {
+ cmdarg_err("The capture device \"%s\" has no data link types.", interface_opts->name);
exit_status = INVALID_DATA_LINK;
goto clean_exit;
}
- capture_opts_print_if_capabilities(caps, interface_opts.name, interface_opts.monitor_mode);
+ if ((if_caps_queries & CAPS_QUERY_TIMESTAMP_TYPES) && caps->timestamp_types == NULL) {
+ cmdarg_err("The capture device \"%s\" has no timestamp types.", interface_opts->name);
+ exit_status = INVALID_TIMESTAMP_TYPE;
+ goto clean_exit;
+ }
+ if (interface_opts->monitor_mode)
+ if_caps_queries |= CAPS_MONITOR_MODE;
+ capture_opts_print_if_capabilities(caps, interface_opts->name, if_caps_queries);
free_if_capabilities(caps);
}
exit_status = EXIT_SUCCESS;
if (print_packet_info) {
if (!write_finale()) {
- err = errno;
- show_print_file_io_error(err);
+ show_print_file_io_error(errno);
}
}
#else
/* Let the user know which interfaces were chosen. */
for (i = 0; i < global_capture_opts.ifaces->len; i++) {
- interface_options interface_opts;
+ interface_options *interface_opts;
- interface_opts = g_array_index(global_capture_opts.ifaces, interface_options, i);
- interface_opts.descr = get_interface_descriptive_name(interface_opts.name);
- global_capture_opts.ifaces = g_array_remove_index(global_capture_opts.ifaces, i);
- g_array_insert_val(global_capture_opts.ifaces, i, interface_opts);
+ interface_opts = &g_array_index(global_capture_opts.ifaces, interface_options, i);
+ interface_opts->descr = get_interface_descriptive_name(interface_opts->name);
}
str = get_iface_list_string(&global_capture_opts, IFLIST_QUOTE_IF_DESCRIPTION);
if (really_quiet == FALSE)
{
capture_options *capture_opts = cap_session->capture_opts;
dfilter_t *rfcode = NULL;
- interface_options interface_opts;
+ interface_options *interface_opts;
g_assert(i < capture_opts->ifaces->len);
- interface_opts = g_array_index(capture_opts->ifaces, interface_options, i);
+ interface_opts = &g_array_index(capture_opts->ifaces, interface_options, i);
- if (dfilter_compile(interface_opts.cfilter, &rfcode, NULL) && rfcode != NULL) {
+ if (dfilter_compile(interface_opts->cfilter, &rfcode, NULL) && rfcode != NULL) {
cmdarg_err(
"Invalid capture filter \"%s\" for interface '%s'.\n"
"\n"
"so you can't use most display filter expressions as capture filters.\n"
"\n"
"See the User's Guide for a description of the capture filter syntax.",
- interface_opts.cfilter, interface_opts.descr, error_message);
+ interface_opts->cfilter, interface_opts->descr, error_message);
dfilter_free(rfcode);
} else {
cmdarg_err(
"\n"
"That string isn't a valid capture filter (%s).\n"
"See the User's Guide for a description of the capture filter syntax.",
- interface_opts.cfilter, interface_opts.descr, error_message);
+ interface_opts->cfilter, interface_opts->descr, error_message);
}
}
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));
+ have_custom_cols(&cf->cinfo) || dissect_color);
/* The protocol tree will be "visible", i.e., printed, only if we're
printing packet details, which is true if we're printing stuff
while (to_read-- && cf->wth) {
wtap_cleareof(cf->wth);
ret = wtap_read(cf->wth, &err, &err_info, &data_offset);
+ reset_epan_mem(cf, edt, create_proto_tree, print_packet_info && print_details);
if (ret == FALSE) {
/* read from file failed, tell the capture child to stop */
sync_pipe_stop(cap_session);
ref = &ref_frame;
}
+ if (dissect_color) {
+ color_filters_prime_edt(edt);
+ fdata->flags.need_colorize = 1;
+ }
+
epan_dissect_run_with_taps(edt, cf->cd_t, phdr, frame_tvbuff_new_buffer(fdata, buf), fdata, cinfo);
/* Run the read/display filter if we have one. */
return passed || fdata->flags.dependent_of_displayed;
}
-static int
-read_cap_file(capture_file *cf, char *save_file, int out_file_type,
+static gboolean
+process_cap_file(capture_file *cf, char *save_file, int out_file_type,
gboolean out_file_name_res, int max_packet_count, gint64 max_byte_count)
{
+ gboolean success = TRUE;
gint linktype;
int snapshot_length;
wtap_dumper *pdh;
guint32 framenum;
- int err;
- gchar *err_info = NULL;
+ int err = 0, err_pass1 = 0;
+ gchar *err_info = NULL, *err_info_pass1 = NULL;
gint64 data_offset;
gboolean filtering_tap_listeners;
guint tap_flags;
snapshot_length = wtap_snapshot_length(cf->wth);
if (snapshot_length == 0) {
/* Snapshot length of input file not known. */
- snapshot_length = WTAP_MAX_PACKET_SIZE;
+ snapshot_length = WTAP_MAX_PACKET_SIZE_STANDARD;
}
tshark_debug("tshark: snapshot_length = %d", snapshot_length);
if (pdh == NULL) {
/* We couldn't set up to write to the capture file. */
cfile_dump_open_failure_message("TShark", save_file, err, out_file_type);
+ success = FALSE;
goto out;
}
} else {
+ /* Set up to print packet information. */
if (print_packet_info) {
if (!write_preamble(cf)) {
- err = errno;
- show_print_file_io_error(err);
+ show_print_file_io_error(errno);
+ success = FALSE;
goto out;
}
}
* on the first pass.
*/
create_proto_tree =
- (cf->rfcode != NULL || cf->dfcode != NULL || postdissectors_want_hfids());
+ (cf->rfcode != NULL || cf->dfcode != NULL || postdissectors_want_hfids() || dissect_color);
tshark_debug("tshark: create_proto_tree = %s", create_proto_tree ? "TRUE" : "FALSE");
}
}
+ /*
+ * If we got a read error on the first pass, remember the error, so
+ * but do the second pass, so we can at least process the packets we
+ * read, and then report the first-pass error after the second pass
+ * (and before we report any second-pass errors), so all the the
+ * errors show up at the end.
+ */
+ if (err != 0) {
+ err_pass1 = err;
+ err_info_pass1 = err_info;
+ err = 0;
+ err_info = NULL;
+ }
+
if (edt) {
epan_dissect_free(edt);
edt = NULL;
*/
create_proto_tree =
(cf->dfcode || print_details || filtering_tap_listeners ||
- (tap_flags & TL_REQUIRES_PROTO_TREE) || have_custom_cols(&cf->cinfo));
+ (tap_flags & TL_REQUIRES_PROTO_TREE) || have_custom_cols(&cf->cinfo) || dissect_color);
tshark_debug("tshark: create_proto_tree = %s", create_proto_tree ? "TRUE" : "FALSE");
else {
/* !perform_two_pass_analysis */
framenum = 0;
-
+ gboolean create_proto_tree = FALSE;
tshark_debug("tshark: perform one pass analysis, do_dissection=%s", do_dissection ? "TRUE" : "FALSE");
if (do_dissection) {
- gboolean create_proto_tree;
-
/*
* Determine whether we need to create a protocol tree.
* We do if:
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))
+ have_custom_cols(&cf->cinfo) || dissect_color);
tshark_debug("tshark: create_proto_tree = %s", create_proto_tree ? "TRUE" : "FALSE");
tshark_debug("tshark: processing packet #%d", framenum);
+ reset_epan_mem(cf, edt, create_proto_tree, print_packet_info && print_details);
+
if (process_packet_single_pass(cf, edt, data_offset, wtap_phdr(cf->wth),
wtap_buf_ptr(cf->wth), tap_flags)) {
/* Either there's no read filtering or this packet passed the
wtap_phdr_cleanup(&phdr);
- if (err != 0) {
+ if (err != 0 || err_pass1 != 0) {
tshark_debug("tshark: something failed along the line (%d)", err);
/*
* Print a message noting that the read failed somewhere along the line.
}
}
#endif
- cfile_read_failure_message("TShark", cf->filename, err, err_info);
- if (save_file != NULL) {
- /* Now close the capture file. */
- if (!wtap_dump_close(pdh, &err))
- cfile_close_failure_message(save_file, err);
+ if (err_pass1 != 0) {
+ /* Error on pass 1 of two-pass processing. */
+ cfile_read_failure_message("TShark", cf->filename, err_pass1,
+ err_info_pass1);
}
- } else {
- if (save_file != NULL) {
- if (pdh && out_file_name_res) {
- if (!wtap_dump_set_addrinfo_list(pdh, get_addrinfo_list())) {
- cmdarg_err("The file format \"%s\" doesn't support name resolution information.",
- wtap_file_type_subtype_short_string(out_file_type));
- }
+ if (err != 0) {
+ /* Error on pass 2 of two-pass processing or on the only pass of
+ one-pass processing. */
+ cfile_read_failure_message("TShark", cf->filename, err, err_info);
+ }
+ success = FALSE;
+ }
+ if (save_file != NULL) {
+ if (pdh && out_file_name_res) {
+ if (!wtap_dump_set_addrinfo_list(pdh, get_addrinfo_list())) {
+ cmdarg_err("The file format \"%s\" doesn't support name resolution information.",
+ wtap_file_type_subtype_short_string(out_file_type));
}
- /* Now close the capture file. */
- if (!wtap_dump_close(pdh, &err))
- cfile_close_failure_message(save_file, err);
- } else {
- if (print_packet_info) {
- if (!write_finale()) {
- err = errno;
- show_print_file_io_error(err);
- }
+ }
+ /* Now close the capture file. */
+ if (!wtap_dump_close(pdh, &err)) {
+ cfile_close_failure_message(save_file, err);
+ success = FALSE;
+ }
+ } else {
+ if (print_packet_info) {
+ if (!write_finale()) {
+ show_print_file_io_error(errno);
+ success = FALSE;
}
}
}
wtap_block_array_free(shb_hdrs);
wtap_block_array_free(nrb_hdrs);
- return err;
+ return success;
}
static gboolean
ref = &ref_frame;
}
+ if (dissect_color) {
+ color_filters_prime_edt(edt);
+ fdata.flags.need_colorize = 1;
+ }
+
epan_dissect_run_with_taps(edt, cf->cd_t, whdr, frame_tvbuff_new(&fdata, pd), &fdata, cinfo);
/* Run the filter if we have it. */
if (print_packet_info) {
/* We're printing packet information; print the information for
this packet. */
+ g_assert(edt);
print_packet(cf, edt);
/* If we're doing "line-buffering", flush the standard output
}
static gboolean
-print_columns(capture_file *cf)
+print_columns(capture_file *cf, const epan_dissect_t *edt)
{
char *line_bufp;
int i;
size_t col_len;
col_item_t* col_item;
gchar str_format[11];
+ const color_filter_t *color_filter = NULL;
line_bufp = get_line_buf(256);
buf_offset = 0;
*line_bufp = '\0';
+
+ if (dissect_color)
+ color_filter = edt->pi.fd->color_filter;
+
for (i = 0; i < cf->cinfo.num_cols; i++) {
col_item = &cf->cinfo.columns[i];
/* Skip columns not marked as visible. */
case COL_DEF_DST:
case COL_RES_DST:
case COL_UNRES_DST:
- g_snprintf(str_format, sizeof(str_format), " %s%s", UTF8_RIGHTWARDS_ARROW, delimiter_char);
+ g_snprintf(str_format, sizeof(str_format), "%s%s%s", delimiter_char, UTF8_RIGHTWARDS_ARROW, delimiter_char);
put_string(line_bufp + buf_offset, str_format, 5);
buf_offset += 5;
break;
case COL_DEF_DL_DST:
case COL_RES_DL_DST:
case COL_UNRES_DL_DST:
- g_snprintf(str_format, sizeof(str_format), " %s%s", UTF8_RIGHTWARDS_ARROW, delimiter_char);
+ g_snprintf(str_format, sizeof(str_format), "%s%s%s", delimiter_char, UTF8_RIGHTWARDS_ARROW, delimiter_char);
put_string(line_bufp + buf_offset, str_format, 5);
buf_offset += 5;
break;
case COL_DEF_NET_DST:
case COL_RES_NET_DST:
case COL_UNRES_NET_DST:
- g_snprintf(str_format, sizeof(str_format), " %s%s", UTF8_RIGHTWARDS_ARROW, delimiter_char);
+ g_snprintf(str_format, sizeof(str_format), "%s%s%s", delimiter_char, UTF8_RIGHTWARDS_ARROW, delimiter_char);
put_string(line_bufp + buf_offset, str_format, 5);
buf_offset += 5;
break;
case COL_DEF_SRC:
case COL_RES_SRC:
case COL_UNRES_SRC:
- g_snprintf(str_format, sizeof(str_format), " %s%s", UTF8_LEFTWARDS_ARROW, delimiter_char);
+ g_snprintf(str_format, sizeof(str_format), "%s%s%s", delimiter_char, UTF8_LEFTWARDS_ARROW, delimiter_char);
put_string(line_bufp + buf_offset, str_format, 5);
buf_offset += 5;
break;
case COL_DEF_DL_SRC:
case COL_RES_DL_SRC:
case COL_UNRES_DL_SRC:
- g_snprintf(str_format, sizeof(str_format), " %s%s", UTF8_LEFTWARDS_ARROW, delimiter_char);
+ g_snprintf(str_format, sizeof(str_format), "%s%s%s", delimiter_char, UTF8_LEFTWARDS_ARROW, delimiter_char);
put_string(line_bufp + buf_offset, str_format, 5);
buf_offset += 5;
break;
case COL_DEF_NET_SRC:
case COL_RES_NET_SRC:
case COL_UNRES_NET_SRC:
- g_snprintf(str_format, sizeof(str_format), " %s%s", UTF8_LEFTWARDS_ARROW, delimiter_char);
+ g_snprintf(str_format, sizeof(str_format), "%s%s%s", delimiter_char, UTF8_LEFTWARDS_ARROW, delimiter_char);
put_string(line_bufp + buf_offset, str_format, 5);
buf_offset += 5;
break;
}
}
}
- return print_line(print_stream, 0, line_bufp);
+
+ if (dissect_color && color_filter != NULL)
+ return print_line_color(print_stream, 0, line_bufp, &color_filter->fg_color, &color_filter->bg_color);
+ else
+ return print_line(print_stream, 0, line_bufp);
}
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);
switch (output_action) {
case WRITE_TEXT:
- if (!print_columns(cf))
+ if (!print_columns(cf, edt))
return FALSE;
break;
case WRITE_XML:
- write_psml_columns(edt, stdout);
+ write_psml_columns(edt, stdout, dissect_color);
return !ferror(stdout);
case WRITE_FIELDS: /*No non-verbose "fields" format */
case WRITE_JSON:
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(output_fields, protocolfilter, protocolfilter_flags, edt, stdout);
+ write_pdml_proto_tree(output_fields, protocolfilter, protocolfilter_flags, edt, stdout, dissect_color);
printf("\n");
return !ferror(stdout);
case WRITE_FIELDS:
printf("\n");
return !ferror(stdout);
case WRITE_JSON:
- print_args.print_dissections = print_dissections_expanded;
- print_args.print_hex = print_hex;
- write_json_proto_tree(output_fields, &print_args, protocolfilter, protocolfilter_flags, edt, stdout);
- printf("\n");
+ write_json_proto_tree(output_fields, print_dissections_expanded,
+ print_hex, protocolfilter, protocolfilter_flags,
+ edt, node_children_grouper, stdout);
return !ferror(stdout);
case WRITE_JSON_RAW:
- print_args.print_dissections = print_dissections_none;
- print_args.print_hex = TRUE;
- write_json_proto_tree(output_fields, &print_args, protocolfilter, protocolfilter_flags, edt, stdout);
- printf("\n");
+ write_json_proto_tree(output_fields, print_dissections_none, TRUE,
+ protocolfilter, protocolfilter_flags,
+ edt, node_children_grouper, stdout);
return !ferror(stdout);
case WRITE_EK:
- print_args.print_hex = print_hex;
- write_ek_proto_tree(output_fields, &print_args, protocolfilter, protocolfilter_flags, edt, stdout);
+ write_ek_proto_tree(output_fields, print_hex, protocolfilter,
+ protocolfilter_flags, edt, stdout);
return !ferror(stdout);
}
}
cf->drops_known = FALSE;
cf->drops = 0;
cf->snap = wtap_snapshot_length(cf->wth);
- if (cf->snap == 0) {
- /* Snapshot length not known. */
- cf->has_snap = FALSE;
- cf->snap = WTAP_MAX_PACKET_SIZE;
- } else
- cf->has_snap = TRUE;
nstime_set_zero(&cf->elapsed_time);
ref = NULL;
prev_dis = NULL;
filename, g_strerror(err));
}
+static void reset_epan_mem(capture_file *cf,epan_dissect_t *edt, gboolean tree, gboolean visual)
+{
+ if (!epan_auto_reset || (cf->count < epan_auto_reset_count))
+ return;
+
+ fprintf(stderr, "resetting session.\n");
+
+ epan_dissect_cleanup(edt);
+ epan_free(cf->epan);
+
+ cf->epan = tshark_epan_new(cf);
+ epan_dissect_init(edt, cf->epan, tree, visual);
+ cf->count = 0;
+}
+
/*
* Report additional information for an error in command-line arguments.
*/