#include <glib.h>
#include <epan/epan.h>
#include <epan/filesystem.h>
+#include <wsutil/crash_info.h>
#include <wsutil/privileges.h>
#include <wsutil/file_util.h>
#include <epan/timestamp.h>
#include <epan/packet.h>
#include "file.h"
-#include "disabled_protos.h"
+#include "frame_tvbuff.h"
+#include <epan/disabled_protos.h>
#include <epan/prefs.h>
#include <epan/column.h>
-#include "print.h"
+#include <epan/print.h>
#include <epan/addr_resolv.h>
#include "ui/util.h"
#include "clopts_common.h"
-#include "console_io.h"
#include "cmdarg_err.h"
#include "version_info.h"
#include <epan/plugins.h>
#include "capture-wpcap.h"
#include <wsutil/unicode-utils.h>
#endif /* _WIN32 */
+#include "capture_session.h"
#include "capture_sync.h"
+#include "capture_opts.h"
#endif /* HAVE_LIBPCAP */
#include "log.h"
#include <epan/funnel.h>
-#include "capture_opts.h"
/*
* This is the template for the decode as option; it is shared between the
static frame_data *prev_cap;
static frame_data prev_cap_frame;
-static gboolean print_packet_info; /* TRUE if we're to print packet information */
static const char* prev_display_dissector_name = NULL;
static gboolean perform_two_pass_analysis;
} output_action_e;
static output_action_e output_action;
-static gboolean do_dissection; /* TRUE if we have to dissect each packet */
-static gboolean verbose;
-static gboolean print_hex;
+static gboolean do_dissection; /* TRUE if we have to dissect each packet */
+static gboolean print_packet_info; /* TRUE if we're to print packet information */
+static gint print_summary = -1; /* TRUE if we're to print packet summary information */
+static gboolean print_details; /* TRUE if we're to print packet details information */
+static gboolean print_hex; /* TRUE if we're to print hex/ascci information */
static gboolean line_buffered;
+static gboolean really_quiet = FALSE;
static print_format_e print_format = PR_FMT_TEXT;
static print_stream_t *print_stream;
static output_fields_t* output_fields = NULL;
/* The line separator used between packets, changeable via the -S option */
-static char *separator = "";
+static const char *separator = "";
#ifdef HAVE_LIBPCAP
/*
* TRUE if we're to print packet counts to keep track of captured packets.
*/
-static gboolean print_packet_counts;
+static gboolean print_packet_counts = TRUE;
static capture_options global_capture_opts;
+static capture_session global_capture_session;
#ifdef SIGINFO
static gboolean infodelay; /* if TRUE, don't print capture info in SIGINFO handler */
static int load_cap_file(capture_file *, char *, int, gboolean, int, gint64);
static gboolean process_packet(capture_file *cf, gint64 offset,
- struct wtap_pkthdr *whdr,
- const guchar *pd, gboolean filtering_tap_listeners, guint tap_flags);
+ struct wtap_pkthdr *whdr, const guchar *pd,
+ gboolean filtering_tap_listeners, guint tap_flags);
static void show_capture_file_io_error(const char *, int, gboolean);
static void show_print_file_io_error(int err);
static gboolean write_preamble(capture_file *cf);
static void
list_capture_types(void) {
- int i;
+ int i;
struct string_elem *captypes;
- GSList *list = NULL;
+ GSList *list = NULL;
- captypes = g_malloc(sizeof(struct string_elem) * WTAP_NUM_FILE_TYPES);
+ captypes = g_new(struct string_elem, WTAP_NUM_FILE_TYPES);
fprintf(stderr, "tshark: The available capture file types for the \"-F\" flag are:\n");
for (i = 0; i < WTAP_NUM_FILE_TYPES; i++) {
fprintf(output, " -I capture in monitor mode, if available\n");
#endif
#if defined(_WIN32) || defined(HAVE_PCAP_CREATE)
- fprintf(output, " -B <buffer size> size of kernel buffer (def: 1MB)\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, " -D print list of interfaces and exit\n");
fprintf(output, "\n");
fprintf(output, "Processing:\n");
fprintf(output, " -2 perform a two-pass analysis\n");
- fprintf(output, " -R <read filter> packet filter in Wireshark display filter syntax\n");
+ fprintf(output, " -R <read filter> packet Read filter in Wireshark display filter syntax\n");
+ fprintf(output, " -Y <display filter> packet displaY filter in Wireshark display filter syntax\n");
fprintf(output, " -n disable all name resolutions (def: all enabled)\n");
fprintf(output, " -N <name resolve flags> enable specific name resolution(s): \"mntC\"\n");
fprintf(output, " -d %s ...\n", decode_as_arg_template);
fprintf(output, " -V add output of packet tree (Packet Details)\n");
fprintf(output, " -O <protocols> Only show packet details of these protocols, comma\n");
fprintf(output, " separated\n");
- fprintf(output, " -P print packets even when writing to a file\n");
+ fprintf(output, " -P print packet summary even when writing to a file\n");
fprintf(output, " -S <separator> the line separator to print between packets\n");
fprintf(output, " -x add output of hex and ASCII dump (Packet Bytes)\n");
fprintf(output, " -T pdml|ps|psml|text|fields\n");
fprintf(output, " format of text output (def: text)\n");
- fprintf(output, " -e <field> field to print if -Tfields selected (e.g. tcp.port);\n");
+ fprintf(output, " -e <field> field to print if -Tfields selected (e.g. tcp.port, col.Info);\n");
fprintf(output, " this option can be repeated to print multiple fields\n");
fprintf(output, " -E<fieldsoption>=<value> set options for output when -Tfields selected:\n");
fprintf(output, " header=y|n switch headers on and off\n");
fprintf(output, " aggregator=,|/s|<char> select comma, space, printable character as\n");
fprintf(output, " aggregator\n");
fprintf(output, " quote=d|s|n select double, single, no quotes for values\n");
- fprintf(output, " -t ad|a|r|d|dd|e output format of time stamps (def: r: rel. to first)\n");
+ fprintf(output, " -t a|ad|d|dd|e|r|u|ud output format of time stamps (def: r: rel. to first)\n");
fprintf(output, " -u s|hms output format of seconds (def: s: seconds)\n");
fprintf(output, " -l flush standard output after each packet\n");
fprintf(output, " -q be more quiet on stdout (e.g. when using statistics)\n");
+ fprintf(output, " -Q only log true errors to stderr (quieter than -q)\n");
+ fprintf(output, " -g enable group read access on the output file(s)\n");
fprintf(output, " -W n Save extra information in the file, if supported.\n");
fprintf(output, " n = write network address resolution information\n");
fprintf(output, " -X <key>:<value> eXtension options, see the man page for details\n");
fprintf(output, "Usage: tshark -G [report]\n");
fprintf(output, "\n");
fprintf(output, "Glossary table reports:\n");
- fprintf(output, " -G [fields] dump glossary in original format and exit\n");
- fprintf(output, " -G fields2 dump glossary in format 2 and exit\n");
- fprintf(output, " -G fields3 dump glossary in format 3 and exit\n");
+ fprintf(output, " -G fields dump fields glossary and exit\n");
fprintf(output, " -G protocols dump protocols in registration database and exit\n");
fprintf(output, " -G values dump value, range, true/false strings and exit\n");
fprintf(output, " -G ftypes dump field type basic and descriptive names\n");
fprintf(output, " -G defaultprefs dump default preferences and exit\n");
fprintf(output, " -G currentprefs dump current preferences and exit\n");
fprintf(output, "\n");
-
}
/*
static void
display_dissector_names(const gchar *table _U_, gpointer handle, gpointer output)
{
- int proto_id;
- const gchar* proto_filter_name;
- const gchar* proto_ui_name;
+ int proto_id;
+ const gchar *proto_filter_name;
+ const gchar *proto_ui_name;
proto_id = dissector_handle_get_protocol_index((dissector_handle_t)handle);
find_protocol_name_func(const gchar *table _U_, gpointer handle, gpointer user_data)
{
- int proto_id;
- const gchar *protocol_filter_name;
- protocol_name_search_t search_info;
+ int proto_id;
+ const gchar *protocol_filter_name;
+ protocol_name_search_t search_info;
g_assert(handle);
add_decode_as(const gchar *cl_param)
{
gchar *table_name;
- guint32 selector;
+ guint32 selector, selector2;
gchar *decoded_param;
gchar *remaining_param;
gchar *selector_str;
dissector_table_t table_matching;
ftenum_t dissector_table_selector_type;
struct protocol_name_search user_protocol_name;
+ guint64 i;
+ char op;
/* The following code will allocate and copy the command-line options in a string pointed by decoded_param */
/* The selector for this table is an unsigned number. Parse it as such.
There's no need to remove leading and trailing spaces from the
selector number string, because sscanf will do that for us. */
- if ( sscanf(selector_str, "%u", &selector) != 1 ) {
- cmdarg_err("Invalid selector number \"%s\"", selector_str);
- g_free(decoded_param);
- return FALSE;
+ switch (sscanf(selector_str, "%u%c%u", &selector, &op, &selector2)) {
+ case 1:
+ op = '\0';
+ break;
+ case 3:
+ if (op != ':' && op != '-') {
+ cmdarg_err("Invalid selector numeric range \"%s\"", selector_str);
+ g_free(decoded_param);
+ return FALSE;
+ }
+ if (op == ':') {
+ if ((selector2 == 0) || ((guint64)selector + selector2 - 1) > G_MAXUINT32) {
+ cmdarg_err("Invalid selector numeric range \"%s\"", selector_str);
+ g_free(decoded_param);
+ return FALSE;
+ }
+ }
+ else if (selector2 < selector) {
+ /* We could swap them for the user, but maybe it's better to call
+ * this out as an error in case it's not what was intended? */
+ cmdarg_err("Invalid selector numeric range \"%s\"", selector_str);
+ g_free(decoded_param);
+ return FALSE;
+ }
+ break;
+ default:
+ cmdarg_err("Invalid selector number \"%s\"", selector_str);
+ g_free(decoded_param);
+ return FALSE;
}
break;
case FT_UINT24:
case FT_UINT32:
/* The selector for this table is an unsigned number. */
- dissector_change_uint(table_name, selector, dissector_matching);
+ if (op == '\0') {
+ dissector_change_uint(table_name, selector, dissector_matching);
+ } else if (op == ':') {
+ for (i = selector; i < (guint64)selector + selector2; i++) {
+ dissector_change_uint(table_name, (guint32)i, dissector_matching);
+ }
+ } else { /* op == '-' */
+ for (i = selector; i <= selector2; i++) {
+ dissector_change_uint(table_name, (guint32)i, dissector_matching);
+ }
+ }
break;
case FT_STRING:
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 &&
+ if ((log_level & G_LOG_LEVEL_MASK & prefs.console_log_level) == 0 &&
prefs.console_log_level != 0) {
return;
}
static void
print_current_user(void) {
gchar *cur_user, *cur_group;
+
if (started_with_special_privs()) {
cur_user = get_cur_username();
cur_group = get_cur_groupname();
int
main(int argc, char *argv[])
{
+ GString *comp_info_str;
+ GString *runtime_info_str;
char *init_progfile_dir_error;
int opt;
gboolean arg_error = FALSE;
int status;
GList *if_list;
gchar *err_str;
- guint i;
- interface_options interface_opts;
#else
gboolean capture_option_specified = FALSE;
#endif
volatile gboolean out_file_name_res = FALSE;
gchar *volatile cf_name = NULL;
gchar *rfilter = NULL;
+ gchar *dfilter = NULL;
#ifdef HAVE_PCAP_OPEN_DEAD
struct bpf_program fcode;
#endif
dfilter_t *rfcode = NULL;
+ dfilter_t *dfcode = NULL;
e_prefs *prefs_p;
char badopt;
- GLogLevelFlags log_flags;
+ int log_flags;
int optind_initial;
gchar *output_only = NULL;
#define OPTSTRING_I ""
#endif
-#define OPTSTRING "2a:" OPTSTRING_A "b:" OPTSTRING_B "c:C:d:De:E:f:F:G:hH:i:" OPTSTRING_I "K:lLnN:o:O:pPqr:R:s:S:t:T:u:vVw:W:xX:y:z:"
+#define OPTSTRING "2a:" OPTSTRING_A "b:" OPTSTRING_B "c:C:d:De:E:f:F:gG:hH:i:" OPTSTRING_I "K:lLnN:o:O:pPqQr:R:s:S:t:T:u:vVw:W:xX:y:Y:z:"
static const char optstring[] = OPTSTRING;
+ /* Assemble the compile-time version information string */
+ comp_info_str = g_string_new("Compiled ");
+ get_compiled_version_info(comp_info_str, NULL, epan_get_compiled_version_info);
+
+ /* Assemble the run-time version information string */
+ runtime_info_str = g_string_new("Running ");
+ get_runtime_version_info(runtime_info_str, NULL);
+
+ /* Add it to the information to be reported on a crash. */
+ ws_add_crash_info("TShark " VERSION "%s\n"
+ "\n"
+ "%s"
+ "\n"
+ "%s",
+ wireshark_svnversion, comp_info_str->str, runtime_info_str->str);
+
#ifdef _WIN32
arg_list_utf_16to8(argc, argv);
+ create_app_running_mutex();
#if !GLIB_CHECK_VERSION(2,31,0)
g_thread_init(NULL);
#endif
return 1;
}
break;
+ case 'P': /* Print packet summary info even when writing to a file */
+ print_packet_info = TRUE;
+ print_summary = TRUE;
+ break;
+ case 'O': /* Only output these protocols */
+ output_only = g_strdup(optarg);
+ /* FALLTHROUGH */
+ case 'V': /* Verbose */
+ print_details = TRUE;
+ print_packet_info = TRUE;
+ break;
+ case 'x': /* Print packet data in hex (and ASCII) */
+ print_hex = TRUE;
+ /* The user asked for hex output, so let's ensure they get it,
+ * even if they're writing to a file.
+ */
+ print_packet_info = TRUE;
+ break;
case 'X':
ex_opt_add(optarg);
break;
}
}
+ /*
+ * Print packet summary information is the default, unless either -V or -x
+ * were specified and -P was not. Note that this is new behavior, which
+ * allows for the possibility of printing only hex/ascii output without
+ * necessarily requiring that either the summary or details be printed too.
+ */
+ if (print_summary == -1)
+ print_summary = (print_details || print_hex) ? FALSE : TRUE;
+
optind = optind_initial;
opterr = 1;
G_LOG_FLAG_FATAL|G_LOG_FLAG_RECURSION;
g_log_set_handler(NULL,
- log_flags,
+ (GLogLevelFlags)log_flags,
tshark_log_handler, NULL /* user_data */);
g_log_set_handler(LOG_DOMAIN_MAIN,
- log_flags,
+ (GLogLevelFlags)log_flags,
tshark_log_handler, NULL /* user_data */);
#ifdef HAVE_LIBPCAP
g_log_set_handler(LOG_DOMAIN_CAPTURE,
- log_flags,
+ (GLogLevelFlags)log_flags,
tshark_log_handler, NULL /* user_data */);
g_log_set_handler(LOG_DOMAIN_CAPTURE_CHILD,
- log_flags,
+ (GLogLevelFlags)log_flags,
tshark_log_handler, NULL /* user_data */);
#endif
initialize_funnel_ops();
#ifdef HAVE_LIBPCAP
- capture_opts_init(&global_capture_opts, &cfile);
+ capture_opts_init(&global_capture_opts);
+ capture_session_init(&global_capture_session, (void *)&cfile);
#endif
timestamp_set_type(TS_RELATIVE);
proto_initialize_all_prefixes();
if (argc == 2)
- proto_registrar_dump_fields(1);
+ proto_registrar_dump_fields();
else {
if (strcmp(argv[2], "fields") == 0)
- proto_registrar_dump_fields(1);
- else if (strcmp(argv[2], "fields2") == 0)
- proto_registrar_dump_fields(2);
- else if (strcmp(argv[2], "fields3") == 0)
- proto_registrar_dump_fields(3);
+ proto_registrar_dump_fields();
else if (strcmp(argv[2], "protocols") == 0)
proto_registrar_dump_protocols();
else if (strcmp(argv[2], "values") == 0)
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 'p': /* Don't capture in promiscuous mode */
#ifdef HAVE_PCAP_REMOTE
#endif /* _WIN32 or HAVE_PCAP_CREATE */
#ifdef HAVE_LIBPCAP
status = capture_opts_add_opt(&global_capture_opts, opt, optarg, &start_capture);
- if(status != 0) {
+ if (status != 0) {
return status;
}
#else
#endif
case 'D': /* Print a list of capture devices and exit */
#ifdef HAVE_LIBPCAP
- if_list = capture_interface_list(&err, &err_str);
+ if_list = capture_interface_list(&err, &err_str,NULL);
if (if_list == NULL) {
switch (err) {
case CANT_GET_INTERFACE_LIST:
break;
case 'E':
/* Field option */
- if(!output_fields_set_option(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;
break;
case 'W': /* Select extra information to save in our capture file */
/* This is patterned after the -N flag which may not be the best idea. */
- if (strchr(optarg, 'n'))
+ if (strchr(optarg, 'n')) {
out_file_name_res = TRUE;
+ } else {
+ cmdarg_err("Invalid -W argument \"%s\"", optarg);
+ return 1;
+ }
break;
case 'H': /* Read address to name mappings from a hosts file */
- if (! read_hosts_file(optarg))
+ if (! add_hosts_file(optarg))
{
cmdarg_err("Can't read host entries from \"%s\"", optarg);
return 1;
case 'q': /* Quiet */
quiet = TRUE;
break;
+ case 'Q': /* Really quiet */
+ quiet = TRUE;
+ really_quiet = TRUE;
+ break;
case 'r': /* Read capture file x */
cf_name = g_strdup(optarg);
break;
case 'R': /* Read file filter */
rfilter = optarg;
break;
- case 'P': /* Print packets even when writing to a file */
- print_packet_info = TRUE;
- break;
+ case 'P':
+ /* already processed; just ignore it now */
+ break;
case 'S': /* Set the line Separator to be printed between packets */
separator = strdup(optarg);
break;
else {
cmdarg_err("Invalid time stamp type \"%s\"",
optarg);
- cmdarg_err_cont("It must be \"r\" for relative, \"a\" for absolute,");
- cmdarg_err_cont("\"ad\" for absolute with date, or \"d\" for delta.");
+ cmdarg_err_cont("It must be \"a\" for absolute, \"ad\" for absolute with date, \"d\" for delta,");
+ cmdarg_err_cont("\"dd\" for delta displayed, \"e\" for epoch, \"r\" for relative, \"u\" for UTC, ");
+ cmdarg_err_cont("or \"ud\" for UTC with date.");
return 1;
}
break;
print_format = PR_FMT_PS;
} else if (strcmp(optarg, "pdml") == 0) {
output_action = WRITE_XML;
- verbose = TRUE;
+ print_details = TRUE; /* Need details */
+ print_summary = FALSE; /* Don't allow summary */
} else if (strcmp(optarg, "psml") == 0) {
output_action = WRITE_XML;
- verbose = FALSE;
- } else if(strcmp(optarg, "fields") == 0) {
+ print_details = FALSE; /* Don't allow details */
+ print_summary = TRUE; /* Need summary */
+ } else if (strcmp(optarg, "fields") == 0) {
output_action = WRITE_FIELDS;
- verbose = TRUE; /* Need full tree info */
+ print_details = TRUE; /* Need full tree info */
+ print_summary = FALSE; /* Don't allow summary */
} else {
cmdarg_err("Invalid -T parameter.");
cmdarg_err_cont("It must be \"ps\", \"text\", \"pdml\", \"psml\" or \"fields\".");
break;
case 'v': /* Show version and exit */
{
- GString *comp_info_str;
- GString *runtime_info_str;
- /* Assemble the compile-time version information string */
- comp_info_str = g_string_new("Compiled ");
- get_compiled_version_info(comp_info_str, NULL, epan_get_compiled_version_info);
-
- /* Assemble the run-time version information string */
- runtime_info_str = g_string_new("Running ");
- get_runtime_version_info(runtime_info_str, NULL);
show_version(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();
return 0;
}
case 'O': /* Only output these protocols */
- output_only = g_strdup(optarg);
- /* FALLTHROUGH */
+ /* already processed; just ignore it now */
+ break;
case 'V': /* Verbose */
- verbose = TRUE;
- /* The user asked for a verbose output, so let's ensure they get it,
- * even if they're writing to a file.
- */
- print_packet_info = TRUE;
+ /* already processed; just ignore it now */
break;
case 'x': /* Print packet data in hex (and ASCII) */
- print_hex = TRUE;
- /* The user asked for hex output, so let's ensure they get it,
- * even if they're writing to a file.
- */
- print_packet_info = TRUE;
+ /* already processed; just ignore it now */
break;
case 'X':
break;
+ case 'Y':
+ dfilter = optarg;
+ break;
case 'z':
/* We won't call the init function for the stat this soon
as it would disallow MATE's fields (which are registered
part of a tap filter. Instead, we just add the argument
to a list of stat arguments. */
if (!process_stat_cmd_arg(optarg)) {
- cmdarg_err("invalid -z argument.");
+ if (strcmp("help", optarg)==0) {
+ fprintf(stderr, "tshark: The available statistics for the \"-z\" option are:\n");
+ list_stat_cmd_args();
+ return 0;
+ }
+ cmdarg_err("Invalid -z argument \"%s\".", optarg);
cmdarg_err_cont(" -z argument must be one of :");
list_stat_cmd_args();
return 1;
}
/* If we specified output fields, but not the output field type... */
- if(WRITE_FIELDS != output_action && 0 != output_fields_num_fields(output_fields)) {
+ if (WRITE_FIELDS != output_action && 0 != output_fields_num_fields(output_fields)) {
cmdarg_err("Output fields were specified with \"-e\", "
"but \"-Tfields\" was not specified.");
return 1;
- } else if(WRITE_FIELDS == output_action && 0 == output_fields_num_fields(output_fields)) {
+ } else if (WRITE_FIELDS == output_action && 0 == output_fields_num_fields(output_fields)) {
cmdarg_err("\"-Tfields\" was specified, but no fields were "
"specified with \"-e\".");
return 1;
}
- /* If no capture filter or read filter has been specified, and there are
+ /* 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 read filter (if a "-r"
+ filter (if no "-r" flag was specified) or a display filter (if a "-r"
flag was specified. */
if (optind < argc) {
if (cf_name != NULL) {
- if (rfilter != NULL) {
- cmdarg_err("Read filters were specified both with \"-R\" "
+ if (dfilter != NULL) {
+ cmdarg_err("Display filters were specified both with \"-d\" "
"and with additional command-line arguments.");
return 1;
}
- rfilter = get_args_as_string(argc, argv, optind);
+ dfilter = get_args_as_string(argc, argv, optind);
} else {
#ifdef HAVE_LIBPCAP
+ guint i;
+
if (global_capture_opts.default_options.cfilter) {
cmdarg_err("A default capture filter was specified both with \"-f\""
" and with additional command-line arguments.");
return 1;
}
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);
if (output_only != NULL) {
char *ps;
- if (!verbose) {
+ if (!print_details) {
cmdarg_err("-O requires -V");
return 1;
}
}
}
+ if (rfilter != NULL && !perform_two_pass_analysis) {
+ /* Just a warning, so we don't return */
+ cmdarg_err("-R without -2 is deprecated. For single-pass filtering use -Y.");
+ }
+
#ifdef HAVE_LIBPCAP
if (list_link_layer_types) {
/* We're supposed to list the link-layer types for an interface;
return 1;
}
}
- /* Currently, we don't support read filters when capturing
+ /* Currently, we don't support read or display filters when capturing
and saving the packets. */
if (rfilter != NULL) {
cmdarg_err("Read filters aren't supported when capturing and saving the captured packets.");
return 1;
}
+ if (dfilter != NULL) {
+ cmdarg_err("Display filters aren't supported when capturing and saving the captured packets.");
+ return 1;
+ }
} else {
/* They didn't specify a "-w" flag, so we won't be saving to a
capture file. Check for options that only make sense if
if (pc != NULL) {
if (pcap_compile(pc, &fcode, rfilter, 0, 0) != -1) {
cmdarg_err_cont(
- " Note: That display filter code looks like a valid capture filter;");
+ " Note: That read filter code looks like a valid capture filter;");
cmdarg_err_cont(
" maybe you mixed them up?");
}
}
cfile.rfcode = rfcode;
+ if (dfilter != NULL) {
+ if (!dfilter_compile(dfilter, &dfcode)) {
+ cmdarg_err("%s", dfilter_error_msg);
+ epan_cleanup();
+#ifdef HAVE_PCAP_OPEN_DEAD
+ {
+ pcap_t *pc;
+
+ pc = pcap_open_dead(DLT_EN10MB, MIN_PACKET_SIZE);
+ if (pc != NULL) {
+ if (pcap_compile(pc, &fcode, dfilter, 0, 0) != -1) {
+ cmdarg_err_cont(
+ " Note: That display filter code looks like a valid capture filter;");
+ cmdarg_err_cont(
+ " maybe you mixed them up?");
+ }
+ pcap_close(pc);
+ }
+ }
+#endif
+ return 2;
+ }
+ }
+ cfile.dfcode = dfcode;
+
if (print_packet_info) {
/* If we're printing as text or PostScript, we have
to create a print stream. */
we're using a read filter on the packets;
+ we're using a display filter on the packets;
+
we're using any taps that need dissection. */
- do_dissection = print_packet_info || rfcode || tap_listeners_require_dissection();
+ do_dissection = print_packet_info || rfcode || dfcode || tap_listeners_require_dissection();
if (cf_name) {
/*
}
} else {
/* No capture file specified, so we're supposed to do a live capture
- (or get a list of link-layer types for a live capture device);
+ or get a list of link-layer types for a live capture device;
do we have support for live captures? */
#ifdef HAVE_LIBPCAP
- /* trim the interface name and exit if that failed */
- if (!capture_opts_trim_iface(&global_capture_opts,
- ((prefs_p->capture_device) && (*prefs_p->capture_device != '\0')) ? get_if_name(prefs_p->capture_device) : NULL)) {
- return 2;
- }
+ /* if no interface was specified, pick a default */
+ exit_status = capture_opts_default_iface_if_necessary(&global_capture_opts,
+ ((prefs_p->capture_device) && (*prefs_p->capture_device != '\0')) ? get_if_name(prefs_p->capture_device) : NULL);
+ if (exit_status != 0)
+ return exit_status;
/* if requested, list the link layer types and exit */
if (list_link_layer_types) {
guint i;
- interface_options interface_opts;
/* Get the list of link-layer types for the capture devices. */
for (i = 0; i < global_capture_opts.ifaces->len; i++) {
- if_capabilities_t *caps;
-
- interface_opts = g_array_index(global_capture_opts.ifaces, interface_options, i);
- caps = capture_get_if_capabilities(interface_opts.name, interface_opts.monitor_mode, &err_str);
- if (caps == NULL) {
- cmdarg_err("%s", err_str);
- g_free(err_str);
- return 2;
- }
- if (caps->data_link_types == NULL) {
- cmdarg_err("The capture device \"%s\" has no data link types.", interface_opts.name);
- return 2;
- }
- capture_opts_print_if_capabilities(caps, interface_opts.name, interface_opts.monitor_mode);
- free_if_capabilities(caps);
+ interface_options interface_opts;
+ if_capabilities_t *caps;
+
+ interface_opts = g_array_index(global_capture_opts.ifaces, interface_options, i);
+ caps = capture_get_if_capabilities(interface_opts.name, interface_opts.monitor_mode, &err_str, NULL);
+ if (caps == NULL) {
+ cmdarg_err("%s", err_str);
+ g_free(err_str);
+ return 2;
+ }
+ if (caps->data_link_types == NULL) {
+ cmdarg_err("The capture device \"%s\" has no data link types.", interface_opts.name);
+ return 2;
+ }
+ capture_opts_print_if_capabilities(caps, interface_opts.name, interface_opts.monitor_mode);
+ free_if_capabilities(caps);
}
return 0;
}
* Instead, pass on the exit status from the capture child.
*/
capture();
- exit_status = global_capture_opts.fork_child_status;
+ exit_status = global_capture_session.fork_child_status;
if (print_packet_info) {
if (!write_finale()) {
typedef gboolean (*pipe_input_cb_t) (gint source, gpointer user_data);
typedef struct pipe_input_tag {
- gint source;
- gpointer user_data;
- int *child_process;
- pipe_input_cb_t input_cb;
- guint pipe_input_id;
+ gint source;
+ gpointer user_data;
+ int *child_process;
+ pipe_input_cb_t input_cb;
+ guint pipe_input_id;
#ifdef _WIN32
- GMutex *callback_running;
+ GMutex *callback_running;
#endif
} pipe_input_t;
static gint
pipe_timer_cb(gpointer data)
{
- HANDLE handle;
- DWORD avail = 0;
- gboolean result;
- DWORD childstatus;
+ HANDLE handle;
+ DWORD avail = 0;
+ gboolean result;
+ DWORD childstatus;
pipe_input_t *pipe_input_p = data;
- gint iterations = 0;
+ gint iterations = 0;
g_mutex_lock (pipe_input_p->callback_running);
static gboolean
capture(void)
{
- gboolean ret;
- guint i;
- GString *str = g_string_new("");
+ gboolean ret;
+ guint i;
+ GString *str = g_string_new("");
#ifdef USE_TSHARK_SELECT
- fd_set readfds;
+ fd_set readfds;
#endif
#ifndef _WIN32
- struct sigaction action, oldaction;
+ struct sigaction action, oldaction;
#endif
/*
relinquish_special_privs_perm();
print_current_user();
- /* Cleanup all data structures used for dissection. */
- cleanup_dissection();
- /* Initialize all data structures used for dissection. */
- init_dissection();
+ /* Create new dissection section. */
+ epan_free(cfile.epan);
+ cfile.epan = epan_new();
#ifdef _WIN32
/* Catch a CTRL+C event and, if we get it, clean up and exit. */
#endif /* SIGINFO */
#endif /* _WIN32 */
- global_capture_opts.state = CAPTURE_PREPARING;
+ global_capture_session.state = CAPTURE_PREPARING;
/* Let the user know which interfaces were chosen. */
for (i = 0; i < global_capture_opts.ifaces->len; i++) {
g_string_append_printf(str, "and ");
}
}
- g_string_append_printf(str, "%s", interface_opts.descr);
+ g_string_append_printf(str, "'%s'", interface_opts.descr);
}
} else {
g_string_append_printf(str, "%u interfaces", global_capture_opts.ifaces->len);
}
- fprintf(stderr, "Capturing on %s\n", str->str);
+ if (really_quiet == FALSE)
+ fprintf(stderr, "Capturing on %s\n", str->str);
+ fflush(stderr);
g_string_free(str, TRUE);
- ret = sync_pipe_start(&global_capture_opts);
+ ret = sync_pipe_start(&global_capture_opts, &global_capture_session, NULL);
if (!ret)
return FALSE;
return TRUE;
}
-
-/* XXX - move the call to main_window_update() out of capture_sync.c */
-/* dummy for capture_sync.c to make linker happy */
-void main_window_update(void)
-{
-}
-
/* capture child detected an error */
void
-capture_input_error_message(capture_options *capture_opts _U_, char *error_msg, char *secondary_error_msg)
+capture_input_error_message(capture_session *cap_session _U_, char *error_msg, char *secondary_error_msg)
{
cmdarg_err("%s", error_msg);
cmdarg_err_cont("%s", secondary_error_msg);
/* capture child detected an capture filter related error */
void
-capture_input_cfilter_error_message(capture_options *capture_opts, guint i, char *error_message)
+capture_input_cfilter_error_message(capture_session *cap_session, guint i, char *error_message)
{
- dfilter_t *rfcode = NULL;
- interface_options interface_opts;
+ capture_options *capture_opts = cap_session->capture_opts;
+ dfilter_t *rfcode = NULL;
+ interface_options interface_opts;
g_assert(i < capture_opts->ifaces->len);
interface_opts = g_array_index(capture_opts->ifaces, interface_options, i);
/* capture child tells us we have a new (or the first) capture file */
gboolean
-capture_input_new_file(capture_options *capture_opts, gchar *new_file)
+capture_input_new_file(capture_session *cap_session, gchar *new_file)
{
+ capture_options *capture_opts = cap_session->capture_opts;
gboolean is_tempfile;
- int err;
+ int err;
- if(capture_opts->state == CAPTURE_PREPARING) {
+ if (cap_session->state == CAPTURE_PREPARING) {
g_log(LOG_DOMAIN_CAPTURE, G_LOG_LEVEL_MESSAGE, "Capture started!");
}
g_log(LOG_DOMAIN_CAPTURE, G_LOG_LEVEL_MESSAGE, "File: \"%s\"", new_file);
- g_assert(capture_opts->state == CAPTURE_PREPARING || capture_opts->state == CAPTURE_RUNNING);
+ g_assert(cap_session->state == CAPTURE_PREPARING || cap_session->state == CAPTURE_RUNNING);
/* free the old filename */
if (capture_opts->save_file != NULL) {
/* we start a new capture file, close the old one (if we had one before) */
- if( ((capture_file *) capture_opts->cf)->state != FILE_CLOSED) {
- if ( ((capture_file *) capture_opts->cf)->wth != NULL) {
- wtap_close(((capture_file *) capture_opts->cf)->wth);
+ if ( ((capture_file *) cap_session->cf)->state != FILE_CLOSED) {
+ if ( ((capture_file *) cap_session->cf)->wth != NULL) {
+ wtap_close(((capture_file *) cap_session->cf)->wth);
}
- ((capture_file *) capture_opts->cf)->state = FILE_CLOSED;
+ ((capture_file *) cap_session->cf)->state = FILE_CLOSED;
}
g_free(capture_opts->save_file);
capture_opts->save_file = g_strdup(new_file);
/* if we are in real-time mode, open the new file now */
- if(do_dissection) {
+ if (do_dissection) {
/* Attempt to open the capture file and set up to read from it. */
- switch(cf_open(capture_opts->cf, capture_opts->save_file, is_tempfile, &err)) {
+ switch(cf_open((capture_file *)cap_session->cf, capture_opts->save_file, is_tempfile, &err)) {
case CF_OK:
break;
case CF_ERROR:
}
}
- capture_opts->state = CAPTURE_RUNNING;
+ cap_session->state = CAPTURE_RUNNING;
return TRUE;
}
/* capture child tells us we have new packets to read */
void
-capture_input_new_packets(capture_options *capture_opts, int to_read)
+capture_input_new_packets(capture_session *cap_session, int to_read)
{
- gboolean ret;
- int err;
+ gboolean ret;
+ int err;
gchar *err_info;
- gint64 data_offset;
- capture_file *cf = capture_opts->cf;
- gboolean filtering_tap_listeners;
- guint tap_flags;
+ gint64 data_offset;
+ capture_file *cf = (capture_file *)cap_session->cf;
+ gboolean filtering_tap_listeners;
+ guint tap_flags;
#ifdef SIGINFO
/*
/* Get the union of the flags for all tap listeners. */
tap_flags = union_of_tap_listener_flags();
- if(do_dissection) {
+ if (do_dissection) {
while (to_read-- && cf->wth) {
wtap_cleareof(cf->wth);
ret = wtap_read(cf->wth, &err, &err_info, &data_offset);
- if(ret == FALSE) {
+ if (ret == FALSE) {
/* read from file failed, tell the capture child to stop */
- sync_pipe_stop(capture_opts);
+ sync_pipe_stop(cap_session);
wtap_close(cf->wth);
cf->wth = NULL;
} else {
static void
report_counts(void)
{
- if (!print_packet_counts) {
+ if ((print_packet_counts == FALSE) && (really_quiet == FALSE)) {
/* Report the count only if we aren't printing a packet count
as packets arrive. */
- fprintf(stderr, "%u packet%s captured\n", packet_count,
+ fprintf(stderr, "%u packet%s captured\n", packet_count,
plurality(packet_count, "", "s"));
}
#ifdef SIGINFO
/* capture child detected any packet drops? */
void
-capture_input_drops(capture_options *capture_opts _U_, guint32 dropped)
+capture_input_drops(capture_session *cap_session _U_, guint32 dropped)
{
if (print_packet_counts) {
/* We're printing packet counts to stderr.
* do the required cleanup.
*/
void
-capture_input_closed(capture_options *capture_opts, gchar *msg)
+capture_input_closed(capture_session *cap_session, gchar *msg)
{
- capture_file *cf = (capture_file *) capture_opts->cf;
+ capture_file *cf = (capture_file *) cap_session->cf;
if (msg != NULL)
fprintf(stderr, "tshark: %s\n", msg);
report_counts();
- if(cf != NULL && cf->wth != NULL) {
+ if (cf != NULL && cf->wth != NULL) {
wtap_close(cf->wth);
- if(cf->is_tempfile) {
+ if (cf->is_tempfile) {
ws_unlink(cf->filename);
}
}
building it with Cygwin may make the problem go away). */
/* tell the capture child to stop */
- sync_pipe_stop(&global_capture_opts);
+ sync_pipe_stop(&global_capture_session);
/* don't stop our own loop already here, otherwise status messages and
* cleanup wouldn't be done properly. The child will indicate the stop of
capture_cleanup(int signum _U_)
{
/* tell the capture child to stop */
- sync_pipe_stop(&global_capture_opts);
+ sync_pipe_stop(&global_capture_session);
/* don't stop our own loop already here, otherwise status messages and
* cleanup wouldn't be done properly. The child will indicate the stop of
gint64 offset, struct wtap_pkthdr *whdr,
const guchar *pd)
{
- frame_data fdlocal;
- guint32 framenum;
- gboolean create_proto_tree = FALSE;
+ frame_data fdlocal;
+ guint32 framenum;
+ gboolean create_proto_tree = FALSE;
epan_dissect_t edt;
- gboolean passed;
+ gboolean passed;
/* The frame number of this packet is one more than the count of
frames in this packet. */
frame_data_init(&fdlocal, framenum, whdr, 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
+ run a read filter, or display filter, or we're going to process taps, set up to
do a dissection and do so. */
if (do_dissection) {
if (gbl_resolv_flags.mac_name || gbl_resolv_flags.network_name ||
/* Grab any resolved addresses */
host_name_lookup_process();
- /* If we're going to be applying a read filter, we'll need to
+ /* 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;
/* We're not going to display the protocol tree on this pass,
so it's not going to be "visible". */
- epan_dissect_init(&edt, create_proto_tree, FALSE);
+ epan_dissect_init(&edt, cf->epan, create_proto_tree, FALSE);
/* If we're running a read filter, prime the epan_dissect_t with that
filter. */
frame_data_set_before_dissect(&fdlocal, &cf->elapsed_time,
&first_ts, prev_dis, prev_cap);
- epan_dissect_run(&edt, whdr, pd, &fdlocal, NULL);
+ epan_dissect_run(&edt, whdr, frame_tvbuff_new(&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_dis_frame = fdlocal;
- prev_dis = &prev_dis_frame;
- frame_data_sequence_add(cf->frames, &fdlocal);
+ prev_cap = prev_dis = frame_data_sequence_add(cf->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 (do_dissection) {
+ g_slist_foreach(edt.pi.dependent_frames, find_and_mark_frame_depended_upon, cf->frames);
+ }
+
cf->count++;
+ } else {
+ /* if we don't add it to the frame_data_sequence, clean it up right now
+ * to avoid leaks */
+ frame_data_destroy(&fdlocal);
}
- prev_cap_frame = fdlocal;
- prev_cap = &prev_cap_frame;
-
if (do_dissection)
epan_dissect_cleanup(&edt);
static gboolean
process_packet_second_pass(capture_file *cf, frame_data *fdata,
- struct wtap_pkthdr *phdr, const guchar *pd,
+ struct wtap_pkthdr *phdr, Buffer *buf,
gboolean filtering_tap_listeners, guint tap_flags)
{
- gboolean create_proto_tree;
- column_info *cinfo;
- epan_dissect_t edt;
- gboolean passed;
+ gboolean create_proto_tree;
+ column_info *cinfo;
+ epan_dissect_t edt;
+ gboolean passed;
/* If we're not running a display filter and we're not printing any
packet information, we don't need to do a dissection. This means
/* Grab any resolved addresses */
host_name_lookup_process();
- if (cf->rfcode || verbose || filtering_tap_listeners ||
+ if (cf->dfcode || print_details || filtering_tap_listeners ||
(tap_flags & TL_REQUIRES_PROTO_TREE) || have_custom_cols(&cf->cinfo))
create_proto_tree = TRUE;
else
/* The protocol tree will be "visible", i.e., printed, only if we're
printing packet details, which is true if we're printing stuff
- ("print_packet_info" is true) and we're in verbose mode ("verbose"
- is true). */
- epan_dissect_init(&edt, create_proto_tree, print_packet_info && verbose);
+ ("print_packet_info" is true) and we're in verbose mode
+ ("packet_details" is true). */
+ epan_dissect_init(&edt, cf->epan, create_proto_tree, print_packet_info && print_details);
- /* If we're running a read filter, prime the epan_dissect_t with that
+ /* If we're running a display filter, prime the epan_dissect_t with that
filter. */
- if (cf->rfcode)
- epan_dissect_prime_dfilter(&edt, cf->rfcode);
+ if (cf->dfcode)
+ epan_dissect_prime_dfilter(&edt, cf->dfcode);
col_custom_prime_edt(&edt, &cf->cinfo);
- tap_queue_init(&edt);
-
/* We only need the columns if either
-
1) some tap needs the columns
-
or
-
2) we're printing packet info but we're *not* verbose; in verbose
- mode, we print the protocol tree, not the protocol summary. */
- if ((tap_flags & TL_REQUIRES_COLUMNS) || (print_packet_info && !verbose))
+ mode, we print the protocol tree, not the protocol summary.
+ */
+ if ((tap_flags & TL_REQUIRES_COLUMNS) || (print_packet_info && print_summary))
cinfo = &cf->cinfo;
else
cinfo = NULL;
- epan_dissect_run(&edt, phdr, pd, fdata, cinfo);
+ frame_data_set_before_dissect(fdata, &cf->elapsed_time,
+ &first_ts, prev_dis, prev_cap);
- tap_push_tapped_queue(&edt);
+ epan_dissect_run_with_taps(&edt, phdr, frame_tvbuff_new_buffer(fdata, buf), fdata, cinfo);
- /* Run the read filter if we have one. */
- if (cf->rfcode)
- passed = dfilter_apply_edt(cf->rfcode, &edt);
+ /* Run the read/display filter if we have one. */
+ if (cf->dfcode)
+ passed = dfilter_apply_edt(cf->dfcode, &edt);
}
if (passed) {
+ frame_data_set_after_dissect(fdata, &cum_bytes);
/* Process this packet. */
if (print_packet_info) {
/* We're printing packet information; print the information for
exit(2);
}
}
+ prev_dis = fdata;
}
+ prev_cap = fdata;
if (do_dissection) {
epan_dissect_cleanup(&edt);
}
- return passed;
+ return passed || fdata->flags.dependent_of_displayed;
}
static int
wtap_dumper *pdh;
guint32 framenum;
int err;
- gchar *err_info = NULL;
+ gchar *err_info = NULL;
gint64 data_offset;
- char *save_file_string = NULL;
+ char *save_file_string = NULL;
gboolean filtering_tap_listeners;
guint tap_flags;
- wtapng_section_t *shb_hdr;
+ wtapng_section_t *shb_hdr;
wtapng_iface_descriptions_t *idb_inf;
char appname[100];
+ Buffer buf;
shb_hdr = wtap_file_get_shb_info(cf->wth);
idb_inf = wtap_file_get_idb_info(cf->wth);
#ifdef PCAP_NG_DEFAULT
- if (idb_inf->number_of_interfaces > 0) {
+ if (idb_inf->number_of_interfaces > 1) {
linktype = WTAP_ENCAP_PER_PACKET;
} else {
linktype = wtap_file_encap(cf->wth);
snapshot_length = WTAP_MAX_PACKET_SIZE;
}
/* If we don't have an application name add Tshark */
- if(shb_hdr->shb_user_appl == NULL) {
+ if (shb_hdr->shb_user_appl == NULL) {
g_snprintf(appname, sizeof(appname), "TShark " VERSION "%s", wireshark_svnversion);
shb_hdr->shb_user_appl = appname;
}
- pdh = wtap_dump_open_ng(save_file, out_file_type, linktype, snapshot_length,
- FALSE /* compressed */, shb_hdr, idb_inf, &err);
+ if (linktype != WTAP_ENCAP_PER_PACKET && out_file_type == WTAP_FILE_PCAP)
+ pdh = wtap_dump_open(save_file, out_file_type, linktype,
+ snapshot_length, FALSE /* compressed */, &err);
+ else
+ pdh = wtap_dump_open_ng(save_file, out_file_type, linktype,
+ snapshot_length, FALSE /* compressed */, shb_hdr, idb_inf, &err);
g_free(idb_inf);
idb_inf = NULL;
* 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)) {
+ if ( (--max_packet_count == 0) || (max_byte_count != 0 && data_offset >= max_byte_count)) {
err = 0; /* This is not an error */
break;
}
max_packet_count = old_max_packet_count;
+ prev_dis = NULL;
+ prev_cap = NULL;
+ buffer_init(&buf, 1500);
for (framenum = 1; err == 0 && framenum <= cf->count; framenum++) {
fdata = frame_data_sequence_find(cf->frames, framenum);
if (wtap_seek_read(cf->wth, fdata->file_off, &cf->phdr,
- cf->pd, fdata->cap_len, &err, &err_info)) {
- if (process_packet_second_pass(cf, fdata,
- &cf->phdr, cf->pd,
- filtering_tap_listeners, tap_flags)) {
+ &buf, fdata->cap_len, &err, &err_info)) {
+ if (process_packet_second_pass(cf, fdata, &cf->phdr, &buf,
+ filtering_tap_listeners, tap_flags)) {
/* Either there's no read filtering or this packet passed the
filter, so, if we're writing to a capture file, write
this packet out. */
if (pdh != NULL) {
- if (!wtap_dump(pdh, wtap_phdr(cf->wth), wtap_buf_ptr(cf->wth), &err)) {
+ if (!wtap_dump(pdh, &cf->phdr, buffer_start_ptr(&cf->buf), &err)) {
/* Error writing to a capture file */
switch (err) {
* 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)) {
+ if ( (--max_packet_count == 0) || (max_byte_count != 0 && data_offset >= max_byte_count)) {
err = 0; /* This is not an error */
break;
}
}
}
}
+ buffer_free(&buf);
}
else {
framenum = 0;
* 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)) {
+ if ( (--max_packet_count == 0) || (max_byte_count != 0 && data_offset >= max_byte_count)) {
err = 0; /* This is not an error */
break;
}
const guchar *pd,
gboolean filtering_tap_listeners, guint tap_flags)
{
- frame_data fdata;
- gboolean create_proto_tree;
- column_info *cinfo;
- epan_dissect_t edt;
- gboolean passed;
+ frame_data fdata;
+ gboolean create_proto_tree;
+ column_info *cinfo;
+ epan_dissect_t edt;
+ gboolean passed;
/* Count this packet. */
cf->count++;
/* Grab any resolved addresses */
host_name_lookup_process();
- if (cf->rfcode || verbose || filtering_tap_listeners ||
+ 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
/* The protocol tree will be "visible", i.e., printed, only if we're
printing packet details, which is true if we're printing stuff
- ("print_packet_info" is true) and we're in verbose mode ("verbose"
- is true). */
- epan_dissect_init(&edt, create_proto_tree, print_packet_info && verbose);
+ ("print_packet_info" is true) and we're in verbose mode
+ ("packet_details" is true). */
+ epan_dissect_init(&edt, cf->epan, create_proto_tree, print_packet_info && print_details);
- /* If we're running a read filter, prime the epan_dissect_t with that
+ /* If we're running a filter, prime the epan_dissect_t with that
filter. */
if (cf->rfcode)
epan_dissect_prime_dfilter(&edt, cf->rfcode);
+ if (cf->dfcode)
+ epan_dissect_prime_dfilter(&edt, cf->dfcode);
col_custom_prime_edt(&edt, &cf->cinfo);
- tap_queue_init(&edt);
-
/* We only need the columns if either
-
1) some tap needs the columns
-
or
-
2) we're printing packet info but we're *not* verbose; in verbose
- mode, we print the protocol tree, not the protocol summary. */
- if ((tap_flags & TL_REQUIRES_COLUMNS) || (print_packet_info && !verbose))
+ mode, we print the protocol tree, not the protocol summary.
+ or
+ 3) there is a column mapped as an individual field */
+ if ((tap_flags & TL_REQUIRES_COLUMNS) || (print_packet_info && print_summary) || output_fields_has_cols(output_fields))
cinfo = &cf->cinfo;
else
cinfo = NULL;
frame_data_set_before_dissect(&fdata, &cf->elapsed_time,
&first_ts, prev_dis, prev_cap);
- epan_dissect_run(&edt, whdr, pd, &fdata, cinfo);
+ epan_dissect_run_with_taps(&edt, whdr, frame_tvbuff_new(&fdata, pd), &fdata, cinfo);
- tap_push_tapped_queue(&edt);
-
- /* Run the read filter if we have one. */
+ /* Run the filters if we have them. */
if (cf->rfcode)
passed = dfilter_apply_edt(cf->rfcode, &edt);
+ if (passed && cf->dfcode)
+ passed = dfilter_apply_edt(cf->dfcode, &edt);
}
if (passed) {
frame_data_set_after_dissect(&fdata, &cum_bytes);
- prev_dis_frame = fdata;
- prev_dis = &prev_dis_frame;
/* Process this packet. */
if (print_packet_info) {
exit(2);
}
}
+
+ /* this must be set after print_packet() [bug #8160] */
+ prev_dis_frame = fdata;
+ prev_dis = &prev_dis_frame;
}
prev_cap_frame = fdata;
if (do_dissection) {
epan_dissect_cleanup(&edt);
- frame_data_cleanup(&fdata);
+ frame_data_destroy(&fdata);
}
return passed;
}
switch (output_action) {
case WRITE_TEXT:
- return print_preamble(print_stream, cf ? cf->filename : NULL);
+ return print_preamble(print_stream, cf ? cf->filename : NULL, wireshark_svnversion);
case WRITE_XML:
- if (verbose)
+ if (print_details)
write_pdml_preamble(stdout, cf ? cf->filename : NULL);
else
write_psml_preamble(stdout);
static char *
get_line_buf(size_t len)
{
- static char *line_bufp = NULL;
- static size_t line_buf_len = 256;
- size_t new_line_buf_len;
+ static char *line_bufp = NULL;
+ static size_t line_buf_len = 256;
+ size_t new_line_buf_len;
for (new_line_buf_len = line_buf_len; len > new_line_buf_len;
new_line_buf_len *= 2)
;
if (line_bufp == NULL) {
line_buf_len = new_line_buf_len;
- line_bufp = g_malloc(line_buf_len + 1);
+ line_bufp = (char *)g_malloc(line_buf_len + 1);
} else {
if (new_line_buf_len > line_buf_len) {
line_buf_len = new_line_buf_len;
- line_bufp = g_realloc(line_bufp, line_buf_len + 1);
+ line_bufp = (char *)g_realloc(line_bufp, line_buf_len + 1);
}
}
return line_bufp;
static gboolean
print_columns(capture_file *cf)
{
- char *line_bufp;
- int i;
- size_t buf_offset;
- size_t column_len;
+ char *line_bufp;
+ int i;
+ size_t buf_offset;
+ size_t column_len;
line_bufp = get_line_buf(256);
buf_offset = 0;
static gboolean
print_packet(capture_file *cf, epan_dissect_t *edt)
{
- print_args_t print_args;
+ 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);
+
+ if (print_summary) {
+ /* Now print them. */
+ switch (output_action) {
+
+ case WRITE_TEXT:
+ if (!print_columns(cf))
+ return FALSE;
+ break;
- if (verbose) {
+ case WRITE_XML:
+ proto_tree_write_psml(edt, stdout);
+ return !ferror(stdout);
+ case WRITE_FIELDS: /*No non-verbose "fields" format */
+ g_assert_not_reached();
+ break;
+ }
+ }
+ }
+ if (print_details) {
/* Print the information in the protocol tree. */
switch (output_action) {
* we would otherwise have to g_free().
print_args.to_file = TRUE;
print_args.format = print_format;
- print_args.print_summary = !verbose;
+ print_args.print_summary = print_summary;
print_args.print_formfeed = FALSE;
packet_range_init(&print_args.range, &cfile);
*/
- print_args.print_hex = verbose && print_hex;
- print_args.print_dissections = verbose ? print_dissections_expanded : print_dissections_none;
+ 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, print_stream))
return FALSE;
if (!print_hex) {
- /* "print_hex_data()" will put out a leading blank line, as well
- as a trailing one; print one here, to separate the packets,
- only if "print_hex_data()" won't be called. */
if (!print_line(print_stream, 0, separator))
return FALSE;
}
printf("\n");
return !ferror(stdout);
case WRITE_FIELDS:
- proto_tree_write_fields(output_fields, edt, stdout);
+ proto_tree_write_fields(output_fields, edt, &cf->cinfo, stdout);
printf("\n");
return !ferror(stdout);
}
- } else {
- /* Just fill in the columns. */
- epan_dissect_fill_in_columns(edt, FALSE, TRUE);
-
- /* Now print them. */
- switch (output_action) {
-
- case WRITE_TEXT:
- if (!print_columns(cf))
- return FALSE;
- break;
-
- case WRITE_XML:
- proto_tree_write_psml(edt, stdout);
- return !ferror(stdout);
- case WRITE_FIELDS: /*No non-verbose "fields" format */
- g_assert_not_reached();
- break;
- }
}
if (print_hex) {
+ if (print_summary || print_details) {
+ if (!print_line(print_stream, 0, ""))
+ return FALSE;
+ }
if (!print_hex_data(print_stream, edt))
return FALSE;
- if (!print_line(print_stream, 0, ""))
+ if (!print_line(print_stream, 0, separator))
return FALSE;
}
return TRUE;
return print_finale(print_stream);
case WRITE_XML:
- if (verbose)
+ if (print_details)
write_pdml_finale(stdout);
else
write_psml_finale(stdout);
cf_status_t
cf_open(capture_file *cf, const char *fname, gboolean is_tempfile, int *err)
{
- wtap *wth;
- gchar *err_info;
- char err_msg[2048+1];
+ wtap *wth;
+ gchar *err_info;
+ char err_msg[2048+1];
wth = wtap_open_offline(fname, err, &err_info, perform_two_pass_analysis);
if (wth == NULL)
/* The open succeeded. Fill in the information for this file. */
- /* Cleanup all data structures used for dissection. */
- cleanup_dissection();
- /* Initialize all data structures used for dissection. */
- init_dissection();
+ /* Create new epan session for dissection. */
+ epan_free(cf->epan);
+ cf->epan = epan_new();
cf->wth = wth;
cf->f_datalen = 0; /* not used, but set it anyway */
filename, g_strerror(err));
}
-/*
- * Print to the standard error. This is a command-line tool, so there's
- * no need to pop up a console.
- */
-void
-vfprintf_stderr(const char *fmt, va_list ap)
-{
- vfprintf(stderr, fmt, ap);
-}
-
-void
-fprintf_stderr(const char *fmt, ...)
-{
- va_list ap;
-
- va_start(ap, fmt);
- vfprintf_stderr(fmt, ap);
- va_end(ap);
-}
-
/*
* Report an error in command-line arguments.
*/
fprintf(stderr, "\n");
va_end(ap);
}
+
+
+/*
+ * Editor modelines - http://www.wireshark.org/tools/modelines.html
+ *
+ * Local variables:
+ * c-basic-offset: 2
+ * tab-width: 8
+ * indent-tabs-mode: nil
+ * End:
+ *
+ * vi: set shiftwidth=2 tabstop=8 expandtab:
+ * :indentSize=2:tabSize=8:noTabs=true:
+ */