*
* 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 <epan/column.h>
#include "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 "capture-pcap-util.h"
#ifdef _WIN32
#include "capture-wpcap.h"
-#include "capture_errs.h"
#include <wsutil/unicode-utils.h>
#endif /* _WIN32 */
#include "capture_sync.h"
#endif /* HAVE_LIBPCAP */
#include "log.h"
#include <epan/funnel.h>
+#include "capture_opts.h"
/*
* This is the template for the decode as option; it is shared between the
static 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;
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, " -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, " -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, " -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, " -G fields3 dump glossary in format 3 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");
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;
+ }
}
/*
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;
+ }
}
}
}
}
+/*
+ * 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);
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 "2a:A:b:" OPTSTRING_B "c:C:d:De:E:f:F:G:hH:i:" OPTSTRING_I "K:lLnN:o:O:pPqr:R:s:S:t:T:u:vVw:W:xX:y:z:"
+#define OPTSTRING "2a:" OPTSTRING_A "b:" OPTSTRING_B "c:C:d:De:E:f:F:G:hH:i:" OPTSTRING_I "K:lLnN:o:O:pPqr:R:s:S:t:T:u:vVw:W:xX:y:z:"
static const char optstring[] = OPTSTRING;
#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_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);
case 'f': /* capture filter */
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
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;
#endif
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';",
g_string_free(comp_info_str, TRUE);
g_string_free(runtime_info_str, TRUE);
return 0;
- break;
}
case 'O': /* Only output these protocols */
output_only = g_strdup(optarg);
(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)) {
+ ((prefs_p->capture_device) && (*prefs_p->capture_device != '\0')) ? get_if_name(prefs_p->capture_device) : NULL)) {
return 2;
}
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);
void
capture_input_closed(capture_options *capture_opts, gchar *msg)
{
+ capture_file *cf = (capture_file *) capture_opts->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
{
frame_data fdlocal;
guint32 framenum;
+ gboolean create_proto_tree = FALSE;
epan_dissect_t edt;
gboolean passed;
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);
+ if (cf->rfcode)
+ create_proto_tree = TRUE;
+
/* 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);
+ epan_dissect_init(&edt, 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);
}
if (passed) {
- frame_data_set_after_dissect(&fdlocal, &cum_bytes, &prev_dis_ts);
+ frame_data_set_after_dissect(&fdlocal, &cum_bytes);
+ prev_dis_frame = fdlocal;
+ prev_dis = &prev_dis_frame;
frame_data_sequence_add(cf->frames, &fdlocal);
cf->count++;
}
+ prev_cap_frame = fdlocal;
+ prev_cap = &prev_cap_frame;
+
if (do_dissection)
epan_dissect_cleanup(&edt);
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);
gint linktype;
int snapshot_length;
wtap_dumper *pdh;
+ guint32 framenum;
int err;
gchar *err_info = NULL;
gint64 data_offset;
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];
+ 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 > 0) {
+ 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;
+ }
+
+ 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;
wtap_pseudoheader(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.
+ *
+ * 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);
}
}
}
}
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),
filtering_tap_listeners, tap_flags)) {
wtap_pseudoheader(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);
}
}
#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;
}
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);
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);
}
if (passed) {
- frame_data_set_after_dissect(&fdata, &cum_bytes, &prev_dis_ts);
+ frame_data_set_after_dissect(&fdata, &cum_bytes);
+ prev_dis_frame = fdata;
+ prev_dis = &prev_dis_frame;
/* Process this packet. */
if (print_packet_info) {
}
}
+ prev_cap_frame = fdata;
+ prev_cap = &prev_cap_frame;
+
if (do_dissection) {
epan_dissect_cleanup(&edt);
frame_data_cleanup(&fdata);
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_formfeed = FALSE;
- print_args.print_dissections = verbose ? print_dissections_expanded : print_dissections_none;
-
- /* init the packet range */
packet_range_init(&print_args.range);
+ */
+ print_args.print_hex = verbose && print_hex;
+ print_args.print_dissections = verbose ? print_dissections_expanded : print_dissections_none;
if (!proto_tree_print(&print_args, edt, print_stream))
return FALSE;
/* 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),