*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*/
-#ifdef HAVE_CONFIG_H
-# include "config.h"
-#endif
+#include "config.h"
#include <stdlib.h>
#include <stdio.h>
# include <sys/stat.h>
#endif
-#ifdef HAVE_GETOPT_H
-#include <getopt.h>
-#else
+#ifndef HAVE_GETOPT
#include "wsutil/wsgetopt.h"
#endif
#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 "util.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-pcap-util.h"
#ifdef _WIN32
#include "capture-wpcap.h"
-#include "capture_errs.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>
static guint32 cum_bytes;
static nstime_t first_ts;
-static nstime_t prev_dis_ts;
-static nstime_t prev_cap_ts;
+static frame_data *prev_dis;
+static frame_data prev_dis_frame;
+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 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,
- const struct wtap_pkthdr *whdr, union wtap_pseudo_header *pseudo_header,
- 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, " filesize:NUM - switch to next file after NUM KB\n");
fprintf(output, " files:NUM - ringbuffer: replace after NUM files\n");
#endif /* HAVE_LIBPCAP */
-
+#ifdef HAVE_PCAP_REMOTE
+ fprintf(output, "RPCAP options:\n");
+ fprintf(output, " -A <user>:<password> use RPCAP password authentication\n");
+#endif
/*fprintf(output, "\n");*/
fprintf(output, "Input file:\n");
fprintf(output, " -r <infile> set the filename to read from (no pipes or stdin!)\n");
fprintf(output, "\n");
fprintf(output, "Processing:\n");
- fprintf(output, " -R <read filter> packet filter in Wireshark display filter syntax\n");
+ fprintf(output, " -2 perform a two-pass analysis\n");
+ fprintf(output, " -R <read filter> packet Read filter in Wireshark display filter syntax\n");
+ fprintf(output, " -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, " \"Decode As\", see the man page for details\n");
fprintf(output, " Example: tcp.port==8888,http\n");
+ fprintf(output, " -H <hosts file> read a list of entries from a hosts file, which will\n");
+ fprintf(output, " then be written to a capture file. (Implies -W n)\n");
/*fprintf(output, "\n");*/
fprintf(output, "Output:\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, " -F <output file type> set the output file type, default is pcapng\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, " -O <protocols> Only show packet details of these protocols, comma\n");
fprintf(output, " separated\n");
- fprintf(output, " -S display 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, " -z <statistics> various statistics, 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 decodes dump \"layer type\"/\"decode as\" associations and exit\n");
+ fprintf(output, " -G heuristic-decodes dump heuristic dissector tables\n");
fprintf(output, "\n");
fprintf(output, "Preference reports:\n");
fprintf(output, " -G defaultprefs dump default preferences and exit\n");
fprintf(output, " -G currentprefs dump current preferences and exit\n");
fprintf(output, "\n");
-
}
/*
display_dissector_table_names(const char *table_name, const char *ui_name,
gpointer output)
{
- fprintf((FILE *)output, "\t%s (%s)\n", table_name, ui_name);
+ if ((prev_display_dissector_name == NULL) ||
+ (strcmp(prev_display_dissector_name, table_name) != 0)) {
+ fprintf((FILE *)output, "\t%s (%s)\n", table_name, ui_name);
+ prev_display_dissector_name = table_name;
+ }
}
/*
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);
g_assert(proto_filter_name != NULL);
g_assert(proto_ui_name != NULL);
- fprintf((FILE *)output, "\t%s (%s)\n",
- proto_filter_name,
- proto_ui_name);
+ if ((prev_display_dissector_name == NULL) ||
+ (strcmp(prev_display_dissector_name, proto_filter_name) != 0)) {
+ fprintf((FILE *)output, "\t%s (%s)\n",
+ proto_filter_name,
+ proto_ui_name);
+ prev_display_dissector_name = proto_filter_name;
+ }
}
}
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);
}
}
+/*
+ * Allow dissector key names to be sorted alphabetically
+ */
+
+static gint
+compare_dissector_key_name(gconstpointer dissector_a, gconstpointer dissector_b)
+{
+ return strcmp((const char*)dissector_a, (const char*)dissector_b);
+}
+
/*
* Print all layer type names supported.
* We send the output to the stream described by the handle output.
fprint_all_layer_types(FILE *output)
{
- dissector_all_tables_foreach_table(display_dissector_table_names, (gpointer)output);
+ prev_display_dissector_name = NULL;
+ dissector_all_tables_foreach_table(display_dissector_table_names, (gpointer)output, (GCompareFunc)compare_dissector_key_name);
}
/*
fprint_all_protocols_for_layer_types(FILE *output, gchar *table_name)
{
+ prev_display_dissector_name = NULL;
dissector_table_foreach_handle(table_name,
display_dissector_names,
(gpointer)output);
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_STRING:
case FT_STRINGZ:
- case FT_EBCDIC:
/* The selector for this table is a string. */
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:
case FT_STRINGZ:
- case FT_EBCDIC:
/* The selector for this table is a string. */
dissector_change_string(table_name, selector_str, dissector_matching);
break;
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 gdp_open_errno, gdp_read_errno;
int dp_open_errno, dp_read_errno;
int err;
- int exit_status = 0;
+ volatile int exit_status = 0;
#ifdef HAVE_LIBPCAP
gboolean list_link_layer_types = FALSE;
gboolean start_capture = FALSE;
int status;
GList *if_list;
gchar *err_str;
- guint i;
- interface_options interface_opts;
#else
gboolean capture_option_specified = FALSE;
#endif
gboolean quiet = FALSE;
#ifdef PCAP_NG_DEFAULT
- int out_file_type = WTAP_FILE_PCAPNG;
+ volatile int out_file_type = WTAP_FILE_PCAPNG;
#else
- int out_file_type = WTAP_FILE_PCAP;
+ volatile int out_file_type = WTAP_FILE_PCAP;
#endif
- gboolean out_file_name_res = FALSE;
- gchar *cf_name = NULL, *rfilter = NULL;
+ 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;
+#ifdef HAVE_PCAP_REMOTE
+#define OPTSTRING_A "A:"
+#else
+#define OPTSTRING_A ""
+#endif
#ifdef HAVE_LIBPCAP
#if defined(_WIN32) || defined(HAVE_PCAP_CREATE)
#define OPTSTRING_B "B:"
#define OPTSTRING_I ""
#endif
-#define OPTSTRING "a:b:" OPTSTRING_B "c:C:d:De:E:f:F:G:hH:i:" OPTSTRING_I "K:lLnN:o:O:pPqr:R:s:St: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
#endif /* _WIN32 */
/*
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);
#endif
register_all_tap_listeners();
- /* Now register the preferences for any non-dissector modules.
- We must do that before we read the preferences as well. */
- prefs_register_modules();
-
/* If invoked with the "-G" flag, we dump out information based on
the argument to the "-G" flag; if no argument is specified,
for backwards compatibility we dump out a glossary of display
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)
proto_registrar_dump_values();
+ else if (strcmp(argv[2], "ftypes") == 0)
+ proto_registrar_dump_ftypes();
else if (strcmp(argv[2], "decodes") == 0)
dissector_dump_decodes();
+ else if (strcmp(argv[2], "heuristic-decodes") == 0)
+ dissector_dump_heur_decodes();
else if (strcmp(argv[2], "defaultprefs") == 0)
write_prefs(NULL);
else if (strcmp(argv[2], "plugins") == 0)
pf_path = NULL;
}
- /* Set the name resolution code's flags from the preferences. */
- gbl_resolv_flags = prefs_p->name_resolve;
-
/* Read the disabled protocols file. */
read_disabled_protos_list(&gdp_path, &gdp_open_errno, &gdp_read_errno,
&dp_path, &dp_open_errno, &dp_read_errno);
/* Now get our args */
while ((opt = getopt(argc, argv, optstring)) != -1) {
switch (opt) {
+ case '2': /* Perform two pass analysis */
+ perform_two_pass_analysis = 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 'p': /* Don't capture in promiscuous mode */
+#ifdef HAVE_PCAP_REMOTE
+ case 'A': /* Authentication */
+#endif
#ifdef HAVE_PCAP_CREATE
case 'I': /* Capture in monitor mode, if available */
#endif
#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:
+ case DONT_HAVE_PCAP:
cmdarg_err("%s", err_str);
g_free(err_str);
break;
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;
arg_error = TRUE;
#endif
break;
- case 'P': /* Perform two pass analysis */
- perform_two_pass_analysis = TRUE;
- break;
case 'n': /* No name resolution */
- gbl_resolv_flags = RESOLV_NONE;
+ gbl_resolv_flags.mac_name = FALSE;
+ gbl_resolv_flags.network_name = FALSE;
+ gbl_resolv_flags.transport_name = FALSE;
+ gbl_resolv_flags.concurrent_dns = FALSE;
break;
case 'N': /* Select what types of addresses/port #s to resolve */
- if (gbl_resolv_flags == RESOLV_ALL)
- gbl_resolv_flags = RESOLV_NONE;
badopt = string_to_name_resolve(optarg, &gbl_resolv_flags);
if (badopt != '\0') {
cmdarg_err("-N specifies unknown resolving option '%c';",
break;
}
break;
- case 'O': /* Only output these protocols */
- output_only = g_strdup(optarg);
- break;
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 'S': /* show packets in real time */
- print_packet_info = TRUE;
+ case 'P':
+ /* already processed; just ignore it now */
+ break;
+ case 'S': /* Set the line Separator to be printed between packets */
+ separator = strdup(optarg);
break;
case 't': /* Time stamp type */
if (strcmp(optarg, "r") == 0)
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;
- break;
}
+ case 'O': /* Only output these protocols */
+ /* 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) {
/*
}
/* Process the packets in the file */
+ TRY {
#ifdef HAVE_LIBPCAP
- err = load_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);
+ err = load_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 = load_cap_file(&cfile, NULL, out_file_type, out_file_name_res, 0, 0);
+ err = load_cap_file(&cfile, NULL, out_file_type, out_file_name_res, 0, 0);
#endif
+ }
+ CATCH(OutOfMemoryError) {
+ fprintf(stderr,
+ "Out Of Memory!\n"
+ "\n"
+ "Sorry, but TShark has to terminate now!\n"
+ "\n"
+ "Some infos / workarounds can be found at:\n"
+ "http://wiki.wireshark.org/KnownBugs/OutOfMemory\n");
+ err = ENOMEM;
+ }
+ ENDTRY;
if (err != 0) {
/* We still dump out the results of taps, etc., as we might have
read some packets; however, we exit with an error status. */
}
} 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
-
-#ifdef _WIN32
- if (!has_wpcap) {
- char *detailed_err;
-
- cmdarg_err("WinPcap couldn't be found.");
- detailed_err = cant_load_winpcap_err("TShark");
- cmdarg_err_cont("%s", detailed_err);
- g_free(detailed_err);
- return 2;
- }
-#endif
-
- /* trim the interface name and exit if that failed */
- if (!capture_opts_trim_iface(&global_capture_opts,
- (prefs_p->capture_device) ? 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
- GStaticMutex callback_running;
+ GMutex *callback_running;
#endif
} pipe_input_t;
static gint
pipe_timer_cb(gpointer data)
{
- HANDLE handle;
- DWORD avail = 0;
- gboolean result, result1;
- 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_static_mutex_lock (&pipe_input_p->callback_running);
+ g_mutex_lock (pipe_input_p->callback_running);
/* try to read data from the pipe only 5 times, to avoid blocking */
while(iterations < 5) {
result = PeekNamedPipe(handle, NULL, 0, NULL, &avail, NULL);
/* Get the child process exit status */
- result1 = GetExitCodeProcess((HANDLE)*(pipe_input_p->child_process),
- &childstatus);
+ GetExitCodeProcess((HANDLE)*(pipe_input_p->child_process),
+ &childstatus);
/* If the Peek returned an error, or there are bytes to be read
or the childwatcher thread has terminated then call the normal
if (!pipe_input_p->input_cb(pipe_input_p->source, pipe_input_p->user_data)) {
g_log(NULL, G_LOG_LEVEL_DEBUG, "pipe_timer_cb: input pipe closed, iterations: %u", iterations);
/* pipe closed, return false so that the timer is stopped */
- g_static_mutex_unlock (&pipe_input_p->callback_running);
+ g_mutex_unlock (pipe_input_p->callback_running);
return FALSE;
}
}
/*g_log(NULL, G_LOG_LEVEL_DEBUG, "pipe_timer_cb: finished with iterations: %u, new timer", iterations);*/
- g_static_mutex_unlock (&pipe_input_p->callback_running);
+ g_mutex_unlock (pipe_input_p->callback_running);
/* we didn't stopped the timer, so let it run */
return TRUE;
pipe_input.input_cb = input_cb;
#ifdef _WIN32
- g_static_mutex_init(&pipe_input.callback_running);
+#if GLIB_CHECK_VERSION(2,31,0)
+ pipe_input.callback_running = g_malloc(sizeof(GMutex));
+ g_mutex_init(pipe_input.callback_running);
+#else
+ pipe_input.callback_running = g_mutex_new();
+#endif
/* Tricky to use pipes in win9x, as no concept of wait. NT can
do this but that doesn't cover all win32 platforms. GTK can do
this but doesn't seem to work over processes. Attempt to do
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. */
the capture child to finish; it will report that it finished,
or will exit abnormally, so we'll stop reading from the sync
pipe, pick up the exit status, and quit. */
+ memset(&action, 0, sizeof(action));
action.sa_handler = capture_cleanup;
action.sa_flags = SA_RESTART;
sigemptyset(&action.sa_mask);
#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;
loop_running = TRUE;
- while (loop_running)
+ TRY
{
+ while (loop_running)
+ {
#ifdef USE_TSHARK_SELECT
- ret = select(pipe_input.source+1, &readfds, NULL, NULL, NULL);
+ ret = select(pipe_input.source+1, &readfds, NULL, NULL, NULL);
- if (ret == -1)
- {
- perror("select()");
- return TRUE;
- } else if (ret == 1) {
+ if (ret == -1)
+ {
+ perror("select()");
+ return TRUE;
+ } else if (ret == 1) {
#endif
- /* Call the real handler */
- if (!pipe_input.input_cb(pipe_input.source, pipe_input.user_data)) {
- g_log(NULL, G_LOG_LEVEL_DEBUG, "input pipe closed");
- return FALSE;
- }
+ /* Call the real handler */
+ if (!pipe_input.input_cb(pipe_input.source, pipe_input.user_data)) {
+ g_log(NULL, G_LOG_LEVEL_DEBUG, "input pipe closed");
+ return FALSE;
+ }
#ifdef USE_TSHARK_SELECT
- }
+ }
#endif
+ }
}
-
+ CATCH(OutOfMemoryError) {
+ fprintf(stderr,
+ "Out Of Memory!\n"
+ "\n"
+ "Sorry, but TShark has to terminate now!\n"
+ "\n"
+ "Some infos / workarounds can be found at:\n"
+ "http://wiki.wireshark.org/KnownBugs/OutOfMemory\n");
+ exit(1);
+ }
+ ENDTRY;
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 {
ret = process_packet(cf, data_offset, wtap_phdr(cf->wth),
- wtap_pseudoheader(cf->wth), wtap_buf_ptr(cf->wth),
+ wtap_buf_ptr(cf->wth),
filtering_tap_listeners, tap_flags);
}
if (ret != FALSE) {
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 *) cap_session->cf;
+
if (msg != NULL)
fprintf(stderr, "tshark: %s\n", msg);
report_counts();
- 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)->user_saved == FALSE) {
- ws_unlink(((capture_file *) capture_opts->cf)->filename);
+ if (cf != NULL && cf->wth != NULL) {
+ wtap_close(cf->wth);
+ if (cf->is_tempfile) {
+ ws_unlink(cf->filename);
}
}
#ifdef USE_BROKEN_G_MAIN_LOOP
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
static gboolean
process_packet_first_pass(capture_file *cf,
- gint64 offset, const struct wtap_pkthdr *whdr,
- union wtap_pseudo_header *pseudo_header, const guchar *pd)
+ gint64 offset, struct wtap_pkthdr *whdr,
+ const guchar *pd)
{
- frame_data fdlocal;
- guint32 framenum;
+ 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)
+ if (gbl_resolv_flags.mac_name || gbl_resolv_flags.network_name ||
+ gbl_resolv_flags.transport_name || gbl_resolv_flags.concurrent_dns)
/* Grab any resolved addresses */
- host_name_lookup_process(NULL);
+ host_name_lookup_process();
- /* 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, FALSE, FALSE);
+ /* 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, cf->epan, create_proto_tree, FALSE);
/* If we're running a read filter, prime the epan_dissect_t with that
filter. */
epan_dissect_prime_dfilter(&edt, cf->rfcode);
frame_data_set_before_dissect(&fdlocal, &cf->elapsed_time,
- &first_ts, &prev_dis_ts, &prev_cap_ts);
+ &first_ts, prev_dis, prev_cap);
- epan_dissect_run(&edt, pseudo_header, 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_ts);
- frame_data_sequence_add(cf->frames, &fdlocal);
+ frame_data_set_after_dissect(&fdlocal, &cum_bytes);
+ 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);
}
if (do_dissection)
static gboolean
process_packet_second_pass(capture_file *cf, frame_data *fdata,
- union wtap_pseudo_header *pseudo_header, 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
run a read filter, or we're going to process taps, set up to
do a dissection and do so. */
if (do_dissection) {
- if (gbl_resolv_flags)
+ if (gbl_resolv_flags.mac_name || gbl_resolv_flags.network_name ||
+ gbl_resolv_flags.transport_name || gbl_resolv_flags.concurrent_dns)
/* Grab any resolved addresses */
- host_name_lookup_process(NULL);
+ 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, pseudo_header, 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
gint linktype;
int snapshot_length;
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_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
- linktype = WTAP_ENCAP_PER_PACKET;
+ if (idb_inf->number_of_interfaces > 1) {
+ linktype = WTAP_ENCAP_PER_PACKET;
+ } else {
+ linktype = wtap_file_encap(cf->wth);
+ }
#else
linktype = wtap_file_encap(cf->wth);
#endif
/* Snapshot length of input file not known. */
snapshot_length = WTAP_MAX_PACKET_SIZE;
}
- pdh = wtap_dump_open(save_file, out_file_type, linktype, snapshot_length,
- FALSE /* compressed */, &err);
+ /* If we don't have an application name add Tshark */
+ if (shb_hdr->shb_user_appl == NULL) {
+ g_snprintf(appname, sizeof(appname), "TShark " VERSION "%s", wireshark_svnversion);
+ shb_hdr->shb_user_appl = appname;
+ }
+
+ 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;
if (pdh == NULL) {
/* We couldn't set up to write to the capture file. */
case WTAP_ERR_UNSUPPORTED_ENCAP:
case WTAP_ERR_ENCAP_PER_PACKET_UNSUPPORTED:
- cmdarg_err("The capture file being read can't be written in "
- "the format \"%s\".", wtap_encap_short_string(linktype));
+ cmdarg_err("The capture file being read can't be written as a "
+ "\"%s\" file.", wtap_file_type_short_string(out_file_type));
break;
case WTAP_ERR_CANT_OPEN:
tap_flags = union_of_tap_listener_flags();
if (perform_two_pass_analysis) {
- guint32 framenum;
frame_data *fdata;
int old_max_packet_count = max_packet_count;
while (wtap_read(cf->wth, &err, &err_info, &data_offset)) {
if (process_packet_first_pass(cf, data_offset, wtap_phdr(cf->wth),
- wtap_pseudoheader(cf->wth), wtap_buf_ptr(cf->wth))) {
+ wtap_buf_ptr(cf->wth))) {
/* Stop reading if we have the maximum number of packets;
* When the -c option has not been used, max_packet_count
* 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->pseudo_header,
- cf->pd, fdata->cap_len, &err, &err_info)) {
- if (process_packet_second_pass(cf, fdata,
- &cf->pseudo_header, cf->pd,
- filtering_tap_listeners, tap_flags)) {
+ if (wtap_seek_read(cf->wth, fdata->file_off, &cf->phdr,
+ &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_pseudoheader(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 */
- show_capture_file_io_error(save_file, err, FALSE);
+ switch (err) {
+
+ case WTAP_ERR_UNSUPPORTED_ENCAP:
+ /*
+ * This is a problem with the particular frame we're writing;
+ * note that, and give the frame number.
+ *
+ * XXX - framenum is not necessarily the frame number in
+ * the input file if there was a read filter.
+ */
+ fprintf(stderr,
+ "Frame %u of \"%s\" has a network type that can't be saved in a \"%s\" file.\n",
+ framenum, cf->filename,
+ wtap_file_type_short_string(out_file_type));
+ break;
+
+ default:
+ show_capture_file_io_error(save_file, err, FALSE);
+ break;
+ }
wtap_dump_close(pdh, &err);
+ g_free(shb_hdr);
exit(2);
}
}
* 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;
while (wtap_read(cf->wth, &err, &err_info, &data_offset)) {
+ framenum++;
+
if (process_packet(cf, data_offset, wtap_phdr(cf->wth),
- wtap_pseudoheader(cf->wth), wtap_buf_ptr(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. */
if (pdh != NULL) {
- if (!wtap_dump(pdh, wtap_phdr(cf->wth),
- wtap_pseudoheader(cf->wth), wtap_buf_ptr(cf->wth),
- &err)) {
+ if (!wtap_dump(pdh, wtap_phdr(cf->wth), wtap_buf_ptr(cf->wth), &err)) {
/* Error writing to a capture file */
- show_capture_file_io_error(save_file, err, FALSE);
+ switch (err) {
+
+ case WTAP_ERR_UNSUPPORTED_ENCAP:
+ /*
+ * This is a problem with the particular frame we're writing;
+ * note that, and give the frame number.
+ */
+ fprintf(stderr,
+ "Frame %u of \"%s\" has a network type that can't be saved in a \"%s\" file.\n",
+ framenum, cf->filename,
+ wtap_file_type_short_string(out_file_type));
+ break;
+
+ default:
+ show_capture_file_io_error(save_file, err, FALSE);
+ break;
+ }
wtap_dump_close(pdh, &err);
+ g_free(shb_hdr);
exit(2);
}
}
* 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;
}
#endif
switch (err) {
+ case WTAP_ERR_UNSUPPORTED:
+ cmdarg_err("The file \"%s\" contains record data that TShark doesn't support.\n(%s)",
+ cf->filename, err_info);
+ g_free(err_info);
+ break;
+
case WTAP_ERR_UNSUPPORTED_ENCAP:
cmdarg_err("The file \"%s\" has a packet with a network type that TShark doesn't support.\n(%s)",
cf->filename, err_info);
cf->filename);
break;
- case WTAP_ERR_BAD_RECORD:
+ case WTAP_ERR_BAD_FILE:
cmdarg_err("The file \"%s\" appears to be damaged or corrupt.\n(%s)",
cf->filename, err_info);
g_free(err_info);
cf->wth = NULL;
g_free(save_file_string);
+ g_free(shb_hdr);
return err;
}
static gboolean
-process_packet(capture_file *cf, gint64 offset, const struct wtap_pkthdr *whdr,
- union wtap_pseudo_header *pseudo_header, const guchar *pd,
+process_packet(capture_file *cf, gint64 offset, struct wtap_pkthdr *whdr,
+ 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++;
run a read filter, or we're going to process taps, set up to
do a dissection and do so. */
if (do_dissection) {
- if (print_packet_info && gbl_resolv_flags)
+ if (print_packet_info && (gbl_resolv_flags.mac_name || gbl_resolv_flags.network_name ||
+ gbl_resolv_flags.transport_name || gbl_resolv_flags.concurrent_dns))
/* Grab any resolved addresses */
- host_name_lookup_process(NULL);
+ 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_ts, &prev_cap_ts);
+ &first_ts, prev_dis, prev_cap);
- epan_dissect_run(&edt, pseudo_header, 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_ts);
+ frame_data_set_after_dissect(&fdata, &cum_bytes);
/* 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;
+ prev_cap = &prev_cap_frame;
+
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)
- write_pdml_preamble(stdout, cf->filename);
+ if (print_details)
+ write_pdml_preamble(stdout, cf ? cf->filename : NULL);
else
write_psml_preamble(stdout);
return !ferror(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) {
- if (verbose) {
+ 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_details) {
/* Print the information in the protocol tree. */
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 = !verbose;
- print_args.print_hex = verbose && print_hex;
+ print_args.print_summary = print_summary;
print_args.print_formfeed = FALSE;
- print_args.print_dissections = verbose ? print_dissections_expanded : print_dissections_none;
-
- /* init the packet range */
- packet_range_init(&print_args.range);
+ 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, 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, ""))
+ if (!print_line(print_stream, 0, separator))
return FALSE;
}
break;
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 */
/* Indicate whether it's a permanent or temporary file. */
cf->is_tempfile = is_tempfile;
- /* If it's a temporary capture buffer file, mark it as not saved. */
- cf->user_saved = !is_tempfile;
+ /* No user changes yet. */
+ cf->unsaved_changes = FALSE;
cf->cd_t = wtap_file_type(cf->wth);
cf->count = 0;
cf->has_snap = TRUE;
nstime_set_zero(&cf->elapsed_time);
nstime_set_unset(&first_ts);
- nstime_set_unset(&prev_dis_ts);
- nstime_set_unset(&prev_cap_ts);
+ prev_dis = NULL;
+ prev_cap = NULL;
cf->state = FILE_READ_IN_PROGRESS;
errmsg = "The file \"%s\" is a \"special file\" or socket or other non-regular file.";
break;
+ case WTAP_ERR_RANDOM_OPEN_PIPE:
+ /* Seen only when opening a capture file for reading. */
+ errmsg = "The file \"%s\" is a pipe or FIFO; TShark can't read pipe or FIFO files in two-pass mode.";
+ break;
+
case WTAP_ERR_FILE_UNKNOWN_FORMAT:
/* Seen only when opening a capture file for reading. */
errmsg = "The file \"%s\" isn't a capture file in a format TShark understands.";
case WTAP_ERR_CANT_WRITE_TO_PIPE:
/* Seen only when opening a capture file for writing. */
g_snprintf(errmsg_errno, sizeof(errmsg_errno),
- "The file \"%%s\" is a pipe, and %s capture files can't be "
- "written to a pipe.", wtap_file_type_string(file_type));
+ "The file \"%%s\" is a pipe, and \"%s\" capture files can't be "
+ "written to a pipe.", wtap_file_type_short_string(file_type));
errmsg = errmsg_errno;
break;
break;
case WTAP_ERR_UNSUPPORTED_ENCAP:
- if (for_writing)
- errmsg = "TShark can't save this capture in that format.";
- else {
+ if (for_writing) {
+ g_snprintf(errmsg_errno, sizeof(errmsg_errno),
+ "TShark can't save this capture as a \"%s\" file.",
+ wtap_file_type_short_string(file_type));
+ } else {
g_snprintf(errmsg_errno, sizeof(errmsg_errno),
"The file \"%%s\" is a capture for a network type that TShark doesn't support.\n"
"(%s)", err_info);
g_free(err_info);
- errmsg = errmsg_errno;
}
+ errmsg = errmsg_errno;
break;
case WTAP_ERR_ENCAP_PER_PACKET_UNSUPPORTED:
- if (for_writing)
- errmsg = "TShark can't save this capture in that format.";
- else
+ if (for_writing) {
+ g_snprintf(errmsg_errno, sizeof(errmsg_errno),
+ "TShark can't save this capture as a \"%s\" file.",
+ wtap_file_type_short_string(file_type));
+ errmsg = errmsg_errno;
+ } else
errmsg = "The file \"%s\" is a capture for a network type that TShark doesn't support.";
break;
- case WTAP_ERR_BAD_RECORD:
+ case WTAP_ERR_BAD_FILE:
/* Seen only when opening a capture file for reading. */
g_snprintf(errmsg_errno, sizeof(errmsg_errno),
"The file \"%%s\" appears to be damaged or corrupt.\n"
errmsg = "A full header couldn't be written to the file \"%s\".";
break;
+ case WTAP_ERR_COMPRESSION_NOT_SUPPORTED:
+ errmsg = "This file type cannot be written as a compressed file.";
+ break;
+
case WTAP_ERR_DECOMPRESS:
/* Seen only when opening a capture file for reading. */
g_snprintf(errmsg_errno, sizeof(errmsg_errno),
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:
+ */