/* tshark.c
+ *
+ * Text-mode variant of Wireshark, along the lines of tcpdump and snoop,
+ * by Gilbert Ramirez <gram@alumni.rice.edu> and Guy Harris <guy@alum.mit.edu>.
*
* $Id$
*
* By Gerald Combs <gerald@wireshark.org>
* Copyright 1998 Gerald Combs
*
- * Text-mode variant, by Gilbert Ramirez <gram@alumni.rice.edu>
- * and Guy Harris <guy@alum.mit.edu>.
- *
* 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
#include <glib.h>
#include <epan/epan.h>
#include <epan/filesystem.h>
-#include <epan/privileges.h>
-#include <wiretap/file_util.h>
+#include <wsutil/privileges.h>
#include "globals.h"
#include <epan/timestamp.h>
#include "clopts_common.h"
#include "cmdarg_err.h"
#include "version_info.h"
-#include <epan/conversation.h>
#include <epan/plugins.h>
#include "register.h"
#include <epan/epan_dissect.h>
#endif /* _WIN32 */
#include "capture_sync.h"
#endif /* HAVE_LIBPCAP */
-#include "epan/emem.h"
#include "log.h"
#include <epan/funnel.h>
static gboolean print_packet_counts;
-static capture_options capture_opts;
+static capture_options global_capture_opts;
#ifdef SIGINFO
static gboolean infodelay; /* if TRUE, don't print capture info in SIGINFO handler */
static int load_cap_file(capture_file *, char *, int, int, gint64);
static gboolean process_packet(capture_file *cf, gint64 offset,
const struct wtap_pkthdr *whdr, union wtap_pseudo_header *pseudo_header,
- const guchar *pd);
+ 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);
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);
capture_file cfile;
+/*
+ * Mark a particular frame.
+ * Copied from file.c
+ */
+void
+cf_mark_frame(capture_file *cf, frame_data *frame)
+{
+ if (! frame->flags.marked) {
+ frame->flags.marked = TRUE;
+ if (cf->count > cf->marked_count)
+ cf->marked_count++;
+ }
+}
+
+/*
+ * Unmark a particular frame.
+ * Copied from file.c
+ */
+void
+cf_unmark_frame(capture_file *cf, frame_data *frame)
+{
+ if (frame->flags.marked) {
+ frame->flags.marked = FALSE;
+ if (cf->marked_count > 0)
+ cf->marked_count--;
+ }
+}
+
static void list_capture_types(void) {
int i;
/*fprintf(output, "\n");*/
fprintf(output, "Output:\n");
- fprintf(output, " -w <outfile|-> set the output filename (or '-' for stdout)\n");
+ fprintf(output, " -w <outfile|-> write packets to a pcap-format file named \"outfile\"\n");
+ fprintf(output, " (or to the standard output for \"-\")\n");
+ fprintf(output, " -C <config profile> start with specified configuration profile\n");
fprintf(output, " -F <output file type> set the output file type, default is libpcap\n");
fprintf(output, " an empty \"-F\" option will list the file types\n");
fprintf(output, " -V add output of packet tree (Packet Details)\n");
fprintf(output, " -h display this help and exit\n");
fprintf(output, " -v display version info and exit\n");
fprintf(output, " -o <name>:<value> ... override preference setting\n");
+ fprintf(output, " -K <keytab> keytab file to use for kerberos decryption\n");
}
/*
ftenum_t dissector_table_selector_type;
struct protocol_name_search user_protocol_name;
-/* The following code will allocate and copy the command-line options in a string pointed by decoded_param */
+ /* The following code will allocate and copy the command-line options in a string pointed by decoded_param */
g_assert(cl_param);
- decoded_param = g_malloc( sizeof(gchar) * (strlen(cl_param) + 1) ); /* Allocate enough space to have a working copy of the command-line parameter */
+ decoded_param = g_strdup(cl_param);
g_assert(decoded_param);
- strcpy(decoded_param, cl_param);
/* The lines below will parse this string (modifying it) to extract all
}
static void
-log_func_ignore (const gchar *log_domain _U_, GLogLevelFlags log_level _U_,
- const gchar *message _U_, gpointer user_data _U_)
+tshark_log_handler (const gchar *log_domain, GLogLevelFlags log_level,
+ const gchar *message, gpointer user_data)
{
+ /* 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
+ message anyway.
+
+ The default console_log_level preference value is such that only
+ ERROR, CRITICAL and WARNING level messages are processed;
+ MESSAGE, INFO and DEBUG level messages are ignored.
+
+ XXX: Aug 07, 2009: Prior tshark g_log code was hardwired to process 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) {
+ return;
+ }
+
+ g_log_default_handler(log_domain, log_level, message, user_data);
+
}
static char *
GLogLevelFlags log_flags;
int optind_initial;
-#define OPTSTRING_INIT "a:b:c:d:De:E:f:F:G:hi:lLnN:o:pqr:R:s:St:T:vVw:xX:y:z:"
+#define OPTSTRING_INIT "a:b:c:C:d:De:E:f:F:G:hi:K:lLnN:o:pqr:R:s:St:T:vVw:xX:y:z:"
#ifdef HAVE_LIBPCAP
#ifdef _WIN32
#define OPTSTRING_WIN32 "B:"
/*
* Attempt to get the pathname of the executable file.
*/
- init_progfile_dir_error = init_progfile_dir(argv[0]);
+ init_progfile_dir_error = init_progfile_dir(argv[0], main);
if (init_progfile_dir_error != NULL) {
fprintf(stderr, "tshark: Can't get pathname of tshark program: %s.\n",
init_progfile_dir_error);
while ((opt = getopt(argc, argv, optstring)) != -1) {
switch (opt) {
+ case 'C': /* Configuration Profile */
+ if (profile_exists (optarg)) {
+ set_profile_name (optarg);
+ } else {
+ cmdarg_err("Configuration Profile \"%s\" does not exist", optarg);
+ exit(1);
+ }
+ break;
case 'X':
ex_opt_add(optarg);
break;
optind = optind_initial;
opterr = 1;
- /* nothing more than the standard GLib handler, but without a warning */
+
+
+/** Send All g_log messages to our own handler **/
+
log_flags =
+ G_LOG_LEVEL_ERROR|
+ G_LOG_LEVEL_CRITICAL|
G_LOG_LEVEL_WARNING|
G_LOG_LEVEL_MESSAGE|
G_LOG_LEVEL_INFO|
- G_LOG_LEVEL_DEBUG;
+ G_LOG_LEVEL_DEBUG|
+ G_LOG_FLAG_FATAL|G_LOG_FLAG_RECURSION;
g_log_set_handler(NULL,
log_flags,
- log_func_ignore, NULL /* user_data */);
+ tshark_log_handler, NULL /* user_data */);
+ g_log_set_handler(LOG_DOMAIN_MAIN,
+ log_flags,
+ tshark_log_handler, NULL /* user_data */);
+
+#ifdef HAVE_LIBPCAP
g_log_set_handler(LOG_DOMAIN_CAPTURE,
log_flags,
- log_func_ignore, NULL /* user_data */);
+ tshark_log_handler, NULL /* user_data */);
+ g_log_set_handler(LOG_DOMAIN_CAPTURE_CHILD,
+ log_flags,
+ tshark_log_handler, NULL /* user_data */);
+#endif
initialize_funnel_ops();
#ifdef HAVE_LIBPCAP
- capture_opts_init(&capture_opts, NULL /* cfile */);
+ capture_opts_init(&global_capture_opts, &cfile);
#endif
timestamp_set_type(TS_RELATIVE);
dissectors, and we must do it before we read the preferences, in
case any dissectors register preferences. */
epan_init(register_all_protocols, register_all_protocol_handoffs, NULL, NULL,
- failure_message, open_failure_message, read_failure_message);
+ failure_message, open_failure_message, read_failure_message,
+ write_failure_message);
/* Register all tap listeners; we do this before we parse the arguments,
as the "-z" argument can specify a registered tap. */
If none of our build or other processes uses "-G" with no arguments,
we can just process it with the other arguments. */
if (argc >= 2 && strcmp(argv[1], "-G") == 0) {
+ proto_initialize_all_prefixes();
+
if (argc == 2)
proto_registrar_dump_fields(1);
else {
case 'B': /* Buffer size */
#endif /* _WIN32 */
#ifdef HAVE_LIBPCAP
- status = capture_opts_add_opt(&capture_opts, opt, optarg, &start_capture);
+ status = capture_opts_add_opt(&global_capture_opts, opt, optarg, &start_capture);
if(status != 0) {
exit(status);
}
arg_error = TRUE;
#endif
break;
+ case 'C':
+ /* Configuration profile settings were already processed just ignore them this time*/
+ break;
case 'd': /* Decode as rule */
if (!add_decode_as(optarg))
exit(1);
break;
+#if defined(HAVE_HEIMDAL_KERBEROS) || defined(HAVE_MIT_KERBEROS)
+ case 'K': /* Kerberos keytab file */
+ read_keytab_file(optarg);
+ break;
+#endif
case 'D': /* Print a list of capture devices and exit */
#ifdef HAVE_LIBPCAP
status = capture_opts_list_interfaces(FALSE);
case 'L': /* Print list of link-layer types and exit */
#ifdef HAVE_LIBPCAP
list_link_layer_types = TRUE;
- break;
#else
capture_option_specified = TRUE;
arg_error = TRUE;
rfilter = get_args_as_string(argc, argv, optind);
} else {
#ifdef HAVE_LIBPCAP
- if (capture_opts.has_cfilter) {
+ if (global_capture_opts.has_cfilter) {
cmdarg_err("Capture filters were specified both with \"-f\""
" and with additional command-line arguments");
exit(1);
}
- capture_opts.has_cfilter = TRUE;
- capture_opts.cfilter = get_args_as_string(argc, argv, optind);
+ global_capture_opts.has_cfilter = TRUE;
+ global_capture_opts.cfilter = get_args_as_string(argc, argv, optind);
#else
capture_option_specified = TRUE;
#endif
}
#ifdef HAVE_LIBPCAP
- if (!capture_opts.saving_to_file) {
+ if (!global_capture_opts.saving_to_file) {
/* We're not saving the capture to a file; if "-q" wasn't specified,
we should print packet information */
if (!quiet)
output, reject the request. At best, we could redirect that
to the standard error; we *can't* write both to the standard
output and have either of them be useful. */
- if (strcmp(capture_opts.save_file, "-") == 0 && print_packet_info) {
+ if (strcmp(global_capture_opts.save_file, "-") == 0 && print_packet_info) {
cmdarg_err("You can't write both raw packet data and dissected packets"
" to the standard output.");
exit(1);
support in capture files we read). */
#ifdef HAVE_LIBPCAP
if (cf_name != NULL) {
- if (capture_opts.has_cfilter) {
+ if (global_capture_opts.has_cfilter) {
cmdarg_err("Only read filters, not capture filters, "
"can be specified when reading a capture file.");
exit(1);
exit(1);
}
/* No - did they specify a ring buffer option? */
- if (capture_opts.multi_files_on) {
+ if (global_capture_opts.multi_files_on) {
cmdarg_err("Ring buffer requested, but a capture isn't being done.");
exit(1);
}
* "-r" was specified, so we're reading a capture file.
* Capture options don't apply here.
*/
- if (capture_opts.multi_files_on) {
+ if (global_capture_opts.multi_files_on) {
cmdarg_err("Multiple capture files requested, but "
"a capture isn't being done.");
exit(1);
}
- if (capture_opts.has_file_duration) {
+ if (global_capture_opts.has_file_duration) {
cmdarg_err("Switching capture files after a time interval was specified, but "
"a capture isn't being done.");
exit(1);
}
- if (capture_opts.has_ring_num_files) {
+ if (global_capture_opts.has_ring_num_files) {
cmdarg_err("A ring buffer of capture files was specified, but "
"a capture isn't being done.");
exit(1);
}
- if (capture_opts.has_autostop_files) {
+ if (global_capture_opts.has_autostop_files) {
cmdarg_err("A maximum number of capture files was specified, but "
"a capture isn't being done.");
exit(1);
* and byte count as well as a write file. Other autostop options remain valid
* only for a write file.
*/
- if (capture_opts.has_autostop_duration) {
+ if (global_capture_opts.has_autostop_duration) {
cmdarg_err("A maximum capture time was specified, but "
"a capture isn't being done.");
exit(1);
/*
* "-r" wasn't specified, so we're doing a live capture.
*/
- if (capture_opts.saving_to_file) {
+ if (global_capture_opts.saving_to_file) {
/* They specified a "-w" flag, so we'll be saving to a capture file. */
/* When capturing, we only support writing libpcap format. */
cmdarg_err("Live captures can only be saved in libpcap format.");
exit(1);
}
- if (capture_opts.multi_files_on) {
+ if (global_capture_opts.multi_files_on) {
/* Multiple-file mode doesn't work under certain conditions:
a) it doesn't work if you're writing to the standard output;
b) it doesn't work if you're writing to a pipe;
*/
- if (strcmp(capture_opts.save_file, "-") == 0) {
+ if (strcmp(global_capture_opts.save_file, "-") == 0) {
cmdarg_err("Multiple capture files requested, but "
"the capture is being written to the standard output.");
exit(1);
}
- if (capture_opts.output_to_pipe) {
+ if (global_capture_opts.output_to_pipe) {
cmdarg_err("Multiple capture files requested, but "
"the capture file is a pipe.");
exit(1);
}
- if (!capture_opts.has_autostop_filesize &&
- !capture_opts.has_file_duration) {
+ if (!global_capture_opts.has_autostop_filesize &&
+ !global_capture_opts.has_file_duration) {
cmdarg_err("Multiple capture files requested, but "
"no maximum capture file size or duration was specified.");
exit(1);
/* 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
we're saving to a file. */
- if (capture_opts.has_autostop_filesize) {
+ if (global_capture_opts.has_autostop_filesize) {
cmdarg_err("Maximum capture file size specified, but "
"capture isn't being saved to a file.");
exit(1);
}
- if (capture_opts.multi_files_on) {
+ if (global_capture_opts.multi_files_on) {
cmdarg_err("Multiple capture files requested, but "
"the capture isn't being saved to a file.");
exit(1);
for (i = 0; i < cfile.cinfo.num_cols; i++) {
cfile.cinfo.col_fmt[i] = get_column_format(i);
cfile.cinfo.col_title[i] = g_strdup(get_column_title(i));
+ if (cfile.cinfo.col_fmt[i] == COL_CUSTOM) {
+ cfile.cinfo.col_custom_field[i] = g_strdup(get_column_custom_field(i));
+ if(!dfilter_compile(cfile.cinfo.col_custom_field[i], &cfile.cinfo.col_custom_dfilter[i])) {
+ /* XXX: Should we issue a warning? */
+ g_free(cfile.cinfo.col_custom_field[i]);
+ cfile.cinfo.col_custom_field[i] = NULL;
+ cfile.cinfo.col_custom_dfilter[i] = NULL;
+ }
+ } else {
+ cfile.cinfo.col_custom_field[i] = NULL;
+ cfile.cinfo.col_custom_dfilter[i] = NULL;
+ }
cfile.cinfo.fmt_matx[i] = (gboolean *) g_malloc0(sizeof(gboolean) *
NUM_COL_FMTS);
get_column_format_matches(cfile.cinfo.fmt_matx[i], cfile.cinfo.col_fmt[i]);
else
cfile.cinfo.col_buf[i] = (gchar *) g_malloc(sizeof(gchar) * COL_MAX_LEN);
cfile.cinfo.col_fence[i] = 0;
- cfile.cinfo.col_expr[i] = (gchar *) g_malloc(sizeof(gchar) * COL_MAX_LEN);
- cfile.cinfo.col_expr_val[i] = (gchar *) g_malloc(sizeof(gchar) * COL_MAX_LEN);
+ cfile.cinfo.col_expr.col_expr[i] = (gchar *) g_malloc(sizeof(gchar) * COL_MAX_LEN);
+ cfile.cinfo.col_expr.col_expr_val[i] = (gchar *) g_malloc(sizeof(gchar) * COL_MAX_LEN);
}
for (i = 0; i < cfile.cinfo.num_cols; i++) {
}
#ifdef HAVE_LIBPCAP
- capture_opts_trim_snaplen(&capture_opts, MIN_PACKET_SIZE);
- capture_opts_trim_ring_num_files(&capture_opts);
+ capture_opts_trim_snaplen(&global_capture_opts, MIN_PACKET_SIZE);
+ capture_opts_trim_ring_num_files(&global_capture_opts);
#endif
if (rfilter != NULL) {
/* Process the packets in the file */
#ifdef HAVE_LIBPCAP
- err = load_cap_file(&cfile, capture_opts.save_file, out_file_type,
- capture_opts.has_autostop_packets ? capture_opts.autostop_packets : 0,
- capture_opts.has_autostop_filesize ? capture_opts.autostop_filesize : 0);
+ err = load_cap_file(&cfile, global_capture_opts.save_file, out_file_type,
+ 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 = load_cap_file(&cfile, NULL, out_file_type, 0, 0);
#endif
#endif
/* trim the interface name and exit if that failed */
- if (!capture_opts_trim_iface(&capture_opts,
+ if (!capture_opts_trim_iface(&global_capture_opts,
(prefs->capture_device) ? get_if_name(prefs->capture_device) : NULL)) {
exit(2);
}
/* if requested, list the link layer types and exit */
if (list_link_layer_types) {
- status = capture_opts_list_link_layer_types(&capture_opts, FALSE);
+ status = capture_opts_list_link_layer_types(&global_capture_opts, FALSE);
exit(status);
}
#endif /* SIGINFO */
#endif /* _WIN32 */
- capture_opts.state = CAPTURE_PREPARING;
+ global_capture_opts.state = CAPTURE_PREPARING;
/* Let the user know what interface was chosen. */
- capture_opts.iface_descr = get_interface_descriptive_name(capture_opts.iface);
- fprintf(stderr, "Capturing on %s\n", capture_opts.iface_descr);
+ global_capture_opts.iface_descr = get_interface_descriptive_name(global_capture_opts.iface);
+ fprintf(stderr, "Capturing on %s\n", global_capture_opts.iface_descr);
- ret = sync_pipe_start(&capture_opts);
+ ret = sync_pipe_start(&global_capture_opts);
if (!ret)
return FALSE;
{
}
-/* XXX - move the call to simple_dialog() out of capture_sync.c */
-#include "simple_dialog.h"
-
-/* capture_sync.c want's to tell us an error */
-gpointer simple_dialog(ESD_TYPE_E type _U_, gint btn_mask _U_,
- const gchar *msg_format, ...)
-{
- va_list ap;
-
- /* XXX - do we need to display buttons and alike? */
- va_start(ap, msg_format);
- fprintf(stderr, "tshark: ");
- vfprintf(stderr, msg_format, ap);
- fprintf(stderr, "\n");
- va_end(ap);
-
- return NULL;
-}
-
-
/* capture child detected an error */
void
capture_input_error_message(capture_options *capture_opts _U_, char *error_msg, char *secondary_error_msg)
g_assert(capture_opts->state == CAPTURE_PREPARING || capture_opts->state == CAPTURE_RUNNING);
- capture_opts->cf = &cfile;
-
/* free the old filename */
- if(capture_opts->save_file != NULL) {
+ 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_opts->cf != NULL && ((capture_file *) capture_opts->cf)->wth != NULL) {
- wtap_close(((capture_file *) capture_opts->cf)->wth);
- }
+ if ( ((capture_file *) capture_opts->cf)->wth != NULL) {
+ wtap_close(((capture_file *) capture_opts->cf)->wth);
+ }
+ ((capture_file *) capture_opts->cf)->state = FILE_CLOSED;
}
+
g_free(capture_opts->save_file);
is_tempfile = FALSE;
} else {
g_free(capture_opts->save_file);
capture_opts->save_file = NULL;
return FALSE;
- break;
}
}
gchar *err_info;
gint64 data_offset;
capture_file *cf = capture_opts->cf;
-
+ gboolean filtering_tap_listeners;
+ guint tap_flags;
#ifdef SIGINFO
/*
infodelay = TRUE;
#endif /* SIGINFO */
+ /* Do we have any tap listeners with filters? */
+ filtering_tap_listeners = have_filtering_tap_listeners();
+
+ /* Get the union of the flags for all tap listeners. */
+ tap_flags = union_of_tap_listener_flags();
+
if(do_dissection) {
while (to_read-- && cf->wth) {
ret = wtap_read(cf->wth, &err, &err_info, &data_offset);
cf->wth = NULL;
} else {
ret = process_packet(cf, data_offset, wtap_phdr(cf->wth),
- wtap_pseudoheader(cf->wth), wtap_buf_ptr(cf->wth));
+ wtap_pseudoheader(cf->wth), wtap_buf_ptr(cf->wth),
+ filtering_tap_listeners, tap_flags);
}
if (ret != FALSE) {
/* packet sucessfully read and gone through the "Read Filter" */
/* capture child detected any packet drops? */
void
-capture_input_drops(capture_options *capture_opts _U_, int dropped)
+capture_input_drops(capture_options *capture_opts _U_, guint32 dropped)
{
- if (print_packet_counts) {
- /* We're printing packet counts to stderr.
- Send a newline so that we move to the line after the packet count. */
- fprintf(stderr, "\n");
- }
-
- if(dropped != 0) {
- /* We're printing packet counts to stderr.
- Send a newline so that we move to the line after the packet count. */
- fprintf(stderr, "%u packet%s dropped\n", dropped, plurality(dropped, "", "s"));
- }
+ if (print_packet_counts) {
+ /* We're printing packet counts to stderr.
+ Send a newline so that we move to the line after the packet count. */
+ fprintf(stderr, "\n");
+ }
+
+ if (dropped != 0) {
+ /* We're printing packet counts to stderr.
+ Send a newline so that we move to the line after the packet count. */
+ fprintf(stderr, "%u packet%s dropped\n", dropped, plurality(dropped, "", "s"));
+ }
}
building it with Cygwin may make the problem go away). */
/* tell the capture child to stop */
- sync_pipe_stop(&capture_opts);
+ sync_pipe_stop(&global_capture_opts);
/* 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(&capture_opts);
+ sync_pipe_stop(&global_capture_opts);
}
#endif /* _WIN32 */
#endif /* HAVE_LIBPCAP */
gchar *err_info;
gint64 data_offset;
char *save_file_string = NULL;
+ gboolean filtering_tap_listeners;
+ guint tap_flags;
linktype = wtap_file_encap(cf->wth);
if (save_file != NULL) {
}
pdh = NULL;
}
+
+ /* Do we have any tap listeners with filters? */
+ filtering_tap_listeners = have_filtering_tap_listeners();
+
+ /* Get the union of the flags for all tap listeners. */
+ tap_flags = union_of_tap_listener_flags();
+
while (wtap_read(cf->wth, &err, &err_info, &data_offset)) {
if (process_packet(cf, data_offset, wtap_phdr(cf->wth),
- wtap_pseudoheader(cf->wth), wtap_buf_ptr(cf->wth))) {
+ wtap_pseudoheader(cf->wth), wtap_buf_ptr(cf->wth),
+ 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. */
}
}
/* Stop reading if we have the maximum number of packets;
- * note that a zero max_packet_count will never be matched
- * (unless we roll over the packet number?)
+ * 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 == cf->count || (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;
}
case WTAP_ERR_UNSUPPORTED_ENCAP:
cmdarg_err("\"%s\" has a packet with a network type that TShark doesn't support.\n(%s)",
cf->filename, err_info);
+ g_free(err_info);
break;
case WTAP_ERR_CANT_READ:
case WTAP_ERR_BAD_RECORD:
cmdarg_err("\"%s\" appears to be damaged or corrupt.\n(%s)",
cf->filename, err_info);
+ g_free(err_info);
break;
default:
wtap_close(cf->wth);
cf->wth = NULL;
- if (save_file_string != NULL)
- g_free(save_file_string);
+ g_free(save_file_string);
return err;
}
cf->elapsed_time = fdata->rel_ts;
}
+ /* If we don't have the time stamp of the previous displayed packet,
+ it's because this is the first packet that's being displayed. Save the time
+ stamp of this packet as the time stamp of the previous displayed
+ packet. */
+ if (nstime_is_unset(&prev_dis_ts))
+ prev_dis_ts = fdata->abs_ts;
+
/* Get the time elapsed between the previous displayed packet and
this packet. */
- if (nstime_is_unset(&prev_dis_ts))
- nstime_set_zero(&fdata->del_dis_ts);
- else
- nstime_delta(&fdata->del_dis_ts, &fdata->abs_ts, &prev_dis_ts);
+ nstime_delta(&fdata->del_dis_ts, &fdata->abs_ts, &prev_dis_ts);
/* Get the time elapsed between the previous captured packet and
this packet. */
static gboolean
process_packet(capture_file *cf, gint64 offset, const struct wtap_pkthdr *whdr,
- union wtap_pseudo_header *pseudo_header, const guchar *pd)
+ union wtap_pseudo_header *pseudo_header, 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;
}
passed = TRUE;
- if (cf->rfcode || verbose || num_tap_filters!=0)
+ if (cf->rfcode || verbose || filtering_tap_listeners ||
+ (tap_flags & TL_REQUIRES_PROTO_TREE) || have_custom_cols(&cf->cinfo))
create_proto_tree = TRUE;
else
create_proto_tree = FALSE;
if (cf->rfcode)
epan_dissect_prime_dfilter(edt, cf->rfcode);
+ col_custom_prime_edt(edt, &cf->cinfo);
+
tap_queue_init(edt);
- /* We only need the columns if we're printing packet info but we're
- *not* verbose; in verbose mode, we print the protocol tree, not
- the protocol summary. */
- epan_dissect_run(edt, pseudo_header, pd, &fdata,
- (print_packet_info && !verbose) ? &cf->cinfo : NULL);
+ /* 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))
+ cinfo = &cf->cinfo;
+ else
+ cinfo = NULL;
+ epan_dissect_run(edt, pseudo_header, pd, &fdata, cinfo);
tap_push_tapped_queue(edt);
case WRITE_TEXT:
return print_preamble(print_stream, cf ? cf->filename : NULL);
- break;
case WRITE_XML:
if (verbose)
* the same time, sort of like an "Update list of packets
* in real time" capture in Wireshark.)
*/
- if (capture_opts.iface != NULL)
+ if (global_capture_opts.iface != NULL)
continue;
#endif
column_len = strlen(cf->cinfo.col_data[i]);
}
} else {
/* Just fill in the columns. */
- epan_dissect_fill_in_columns(edt);
+ epan_dissect_fill_in_columns(edt, TRUE);
/* Now print them. */
switch (output_action) {
case WRITE_TEXT:
return print_finale(print_stream);
- break;
case WRITE_XML:
if (verbose)
nstime_set_unset(&prev_dis_ts);
nstime_set_unset(&prev_cap_ts);
+ cf->state = FILE_READ_IN_PROGRESS;
+
return CF_OK;
fail:
filename, strerror(err));
}
+/*
+ * Write errors are reported with an console message in TShark.
+ */
+static void
+write_failure_message(const char *filename, int err)
+{
+ cmdarg_err("An error occurred while writing to the file \"%s\": %s.",
+ filename, strerror(err));
+}
+
/*
* Report an error in command-line arguments.
*/
va_list ap;
va_start(ap, fmt);
- fprintf(stderr, "tshark: ");
- vfprintf(stderr, fmt, ap);
- fprintf(stderr, "\n");
+ failure_message(fmt, ap);
va_end(ap);
}
fprintf(stderr, "\n");
va_end(ap);
}
-
-