You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
wireshark/tshark.c

4655 lines
177 KiB

/* tshark.c
*
* Text-mode variant of Wireshark, along the lines of tcpdump and snoop,
* by Gilbert Ramirez <gram@alumni.rice.edu> and Guy Harris <guy@alum.mit.edu>.
*
* Wireshark - Network traffic analyzer
* By Gerald Combs <gerald@wireshark.org>
* Copyright 1998 Gerald Combs
*
* SPDX-License-Identifier: GPL-2.0-or-later
*/
#include <config.h>
Refactor our logging and extend the wslog API Experience has shown that: 1. The current logging methods are not very reliable or practical. A logging bitmask makes little sense as the user-facing interface (who would want debug but not crtical messages for example?); it's computer-friendly and user-unfriendly. More importantly the console log level preference is initialized too late in the startup process to be used for the logging subsystem and that fact raises a number of annoying and hard-to-fix usability issues. 2. Coding around G_MESSAGES_DEBUG to comply with our log level mask and not clobber the user's settings or not create unexpected log misses is unworkable and generally follows the principle of most surprise. The fact that G_MESSAGES_DEBUG="all" can leak to other programs using GLib is also annoying. 3. The non-structured GLib logging API is very opinionated and lacks configurability beyond replacing the log handler. 4. Windows GUI has some special code to attach to a console, but it would be nice to abstract away the rest under a single interface. 5. Using this logger seems to be noticeably faster. Deprecate the console log level preference and extend our API to implement a log handler in wsutil/wslog.h to provide easy-to-use, flexible and dependable logging during all execution phases. Log levels have a hierarchy, from most verbose to least verbose (debug to error). When a given level is set everything above that is also enabled. The log level can be set with an environment variable or a command line option (parsed as soon as possible but still later than the environment). The default log level is "message". Dissector logging is not included because it is not clear what log domain they should use. An explosion to thousands of domains is not desirable and putting everything in a single domain is probably too coarse and noisy. For now I think it makes sense to let them do their own thing using g_log_default_handler() and continue using the G_MESSAGES_DEBUG mechanism with specific domains for each individual dissector. In the future a mechanism may be added to selectively enable these domains at runtime while trying to avoid the problems introduced by G_MESSAGES_DEBUG.
2 years ago
#define WS_LOG_DOMAIN LOG_DOMAIN_MAIN
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <locale.h>
#include <limits.h>
#include <wsutil/ws_getopt.h>
#include <errno.h>
#ifdef _WIN32
# include <winsock2.h>
#endif
#ifndef _WIN32
#include <signal.h>
#endif
#include <glib.h>
#include <epan/exceptions.h>
#include <epan/epan.h>
#include <ws_exit_codes.h>
#include <wsutil/clopts_common.h>
#include <wsutil/cmdarg_err.h>
#include <ui/urls.h>
#include <wsutil/filesystem.h>
#include <wsutil/file_util.h>
#include <wsutil/socket.h>
#include <wsutil/privileges.h>
#include <wsutil/report_message.h>
#include <wsutil/please_report_bug.h>
#include <wsutil/wslog.h>
#include <wsutil/ws_assert.h>
#include <wsutil/strtoi.h>
#include <cli_main.h>
#include <wsutil/version_info.h>
#include <wiretap/wtap_opttypes.h>
#include "globals.h"
#include <epan/timestamp.h>
#include <epan/packet.h>
#ifdef HAVE_LUA
#include <epan/wslua/init_wslua.h>
#endif
#include "frame_tvbuff.h"
#include <epan/disabled_protos.h>
#include <epan/prefs.h>
#include <epan/column.h>
#include <epan/decode_as.h>
#include <epan/print.h>
#include <epan/addr_resolv.h>
#ifdef HAVE_LIBPCAP
#include "ui/capture_ui_utils.h"
#endif
#include "ui/taps.h"
#include "ui/util.h"
#include "ui/ws_ui_util.h"
#include "ui/decode_as_utils.h"
#include "wsutil/filter_files.h"
#include "ui/cli/tshark-tap.h"
#include "ui/cli/tap-exportobject.h"
#include "ui/tap_export_pdu.h"
#include "ui/dissect_opts.h"
#include "ui/ssl_key_export.h"
#include "ui/failure_message.h"
#if defined(HAVE_LIBSMI)
#include "epan/oids.h"
#endif
#include "epan/maxmind_db.h"
#include <epan/epan_dissect.h>
#include <epan/tap.h>
#include <epan/stat_tap_ui.h>
#include <epan/conversation_table.h>
#include <epan/srt_table.h>
#include <epan/rtd_table.h>
#include <epan/ex-opt.h>
#include <epan/exported_pdu.h>
#include <epan/secrets.h>
#include "capture_opts.h"
#include "capture/capture-pcap-util.h"
#ifdef HAVE_LIBPCAP
#include "capture/capture_ifinfo.h"
#ifdef _WIN32
#include "capture/capture-wpcap.h"
#endif /* _WIN32 */
#include <capture/capture_session.h>
#include <capture/capture_sync.h>
#include <ui/capture_info.h>
#endif /* HAVE_LIBPCAP */
#include <epan/funnel.h>
#include <wsutil/str_util.h>
#include <wsutil/utf8_entities.h>
#include <wsutil/json_dumper.h>
Refactor our logging and extend the wslog API Experience has shown that: 1. The current logging methods are not very reliable or practical. A logging bitmask makes little sense as the user-facing interface (who would want debug but not crtical messages for example?); it's computer-friendly and user-unfriendly. More importantly the console log level preference is initialized too late in the startup process to be used for the logging subsystem and that fact raises a number of annoying and hard-to-fix usability issues. 2. Coding around G_MESSAGES_DEBUG to comply with our log level mask and not clobber the user's settings or not create unexpected log misses is unworkable and generally follows the principle of most surprise. The fact that G_MESSAGES_DEBUG="all" can leak to other programs using GLib is also annoying. 3. The non-structured GLib logging API is very opinionated and lacks configurability beyond replacing the log handler. 4. Windows GUI has some special code to attach to a console, but it would be nice to abstract away the rest under a single interface. 5. Using this logger seems to be noticeably faster. Deprecate the console log level preference and extend our API to implement a log handler in wsutil/wslog.h to provide easy-to-use, flexible and dependable logging during all execution phases. Log levels have a hierarchy, from most verbose to least verbose (debug to error). When a given level is set everything above that is also enabled. The log level can be set with an environment variable or a command line option (parsed as soon as possible but still later than the environment). The default log level is "message". Dissector logging is not included because it is not clear what log domain they should use. An explosion to thousands of domains is not desirable and putting everything in a single domain is probably too coarse and noisy. For now I think it makes sense to let them do their own thing using g_log_default_handler() and continue using the G_MESSAGES_DEBUG mechanism with specific domains for each individual dissector. In the future a mechanism may be added to selectively enable these domains at runtime while trying to avoid the problems introduced by G_MESSAGES_DEBUG.
2 years ago
#include <wsutil/wslog.h>
#ifdef _WIN32
#include <wsutil/win32-utils.h>
#endif
#include "extcap.h"
#ifdef HAVE_PLUGINS
#include <wsutil/codecs.h>
#include <wsutil/plugins.h>
#endif
/* Additional exit codes */
#define INVALID_EXPORT 2
#define INVALID_TAP 2
#define INVALID_CAPTURE 2
#define LONGOPT_EXPORT_OBJECTS LONGOPT_BASE_APPLICATION+1
#define LONGOPT_COLOR LONGOPT_BASE_APPLICATION+2
#define LONGOPT_NO_DUPLICATE_KEYS LONGOPT_BASE_APPLICATION+3
#define LONGOPT_ELASTIC_MAPPING_FILTER LONGOPT_BASE_APPLICATION+4
#define LONGOPT_EXPORT_TLS_SESSION_KEYS LONGOPT_BASE_APPLICATION+5
#define LONGOPT_CAPTURE_COMMENT LONGOPT_BASE_APPLICATION+6
#define LONGOPT_HEXDUMP LONGOPT_BASE_APPLICATION+7
#define LONGOPT_SELECTED_FRAME LONGOPT_BASE_APPLICATION+8
capture_file cfile;
static guint32 cum_bytes;
static frame_data ref_frame;
static frame_data prev_dis_frame;
static frame_data prev_cap_frame;
static gboolean perform_two_pass_analysis;
static guint32 epan_auto_reset_count = 0;
static gboolean epan_auto_reset = FALSE;
static guint32 selected_frame_number = 0;
/*
* The way the packet decode is to be written.
*/
typedef enum {
WRITE_NONE, /* dummy initial state */
WRITE_TEXT, /* summary or detail text */
WRITE_XML, /* PDML or PSML */
WRITE_FIELDS, /* User defined list of fields */
WRITE_JSON, /* JSON */
WRITE_JSON_RAW, /* JSON only raw hex */
WRITE_EK /* JSON bulk insert to Elasticsearch */
/* Add CSV and the like here */
} output_action_e;
static output_action_e output_action;
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 gboolean print_summary; /* 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/ascii information */
static gboolean line_buffered;
static gboolean quiet = FALSE;
static gboolean really_quiet = FALSE;
static gchar* delimiter_char = " ";
static gboolean dissect_color = FALSE;
static guint hexdump_source_option = HEXDUMP_SOURCE_MULTI; /* Default - Enable legacy multi-source mode */
static guint hexdump_ascii_option = HEXDUMP_ASCII_INCLUDE; /* Default - Enable legacy undelimited ASCII dump */
static print_format_e print_format = PR_FMT_TEXT;
static print_stream_t *print_stream = NULL;
static char *output_file_name;
static output_fields_t* output_fields = NULL;
static wmem_map_t *protocolfilter = NULL;
Add --no-duplicate-keys tshark option. Adds the --no-duplicate-keys option to tshark. If -T json is specified, this option can be specified in order to transform the duplicate keys produced by -T json into single keys with as value a json array of all separate values. Specifying --no-duplicate-keys changes the function which groups node children that is passed to write_json_proto_tree. Instead of a function that puts each node in a separate group (proto_node_group_children_by_unique) a function is passed that groups children that have the same json key together (proto_node_group_children_by_json_key). This will lead to some groups having multiple values. Groups with multiple values are written to the output as a json array. This includes normal json keys but also keys with the "_raw" and "_tree" suffix. If --no-duplicate-keys is specified with an option other than "-T json" or "-T jsonraw" or without -T an error is shown and tshark will exit. "Export Packet Dissections -> As JSON" in the GUI is hardcoded to use the duplicated keys format. Fixes one regression in the output where a filtered json key (-j) with both a value and children would not have the "_tree" suffix added to the json key containing the children. Includes a little code cleanup (removes one instance of code duplication and simplifies a while loop). Fixes a memory leak (I thought this fix was already included in the previous refactor patch but something must have gone wrong when updating the patch so I'm including it again in this patch). Bug: 12958 Change-Id: I401f8fc877b5c590686567c3c44cdb832e9e7dfe Reviewed-on: https://code.wireshark.org/review/22166 Petri-Dish: Jaap Keuter <jaap.keuter@xs4all.nl> Tested-by: Petri Dish Buildbot <buildbot-no-reply@wireshark.org> Reviewed-by: Anders Broman <a.broman58@gmail.com>
6 years ago
static gboolean no_duplicate_keys = FALSE;
static proto_node_children_grouper_func node_children_grouper = proto_node_group_children_by_unique;
static json_dumper jdumper;
/* The line separator used between packets, changeable via the -S option */
static const char *separator = "";
/* Per-file comments to be added to the output file. */
static GPtrArray *capture_comments = NULL;
static gboolean prefs_loaded = FALSE;
#ifdef HAVE_LIBPCAP
/*
* TRUE if we're to print packet counts to keep track of captured packets.
*/
static gboolean print_packet_counts;
static capture_options global_capture_opts;
static capture_session global_capture_session;
static info_data_t global_info_data;
#ifdef SIGINFO
static gboolean infodelay; /* if TRUE, don't print capture info in SIGINFO handler */
static gboolean infoprint; /* if TRUE, print capture info after clearing infodelay */
#endif /* SIGINFO */
static gboolean capture(void);
static gboolean capture_input_new_file(capture_session *cap_session,
gchar *new_file);
static void capture_input_new_packets(capture_session *cap_session,
int to_read);
static void capture_input_drops(capture_session *cap_session, guint32 dropped,
const char* interface_name);
static void capture_input_error(capture_session *cap_session,
char *error_msg, char *secondary_error_msg);
static void capture_input_cfilter_error(capture_session *cap_session,
guint i, const char *error_message);
static void capture_input_closed(capture_session *cap_session, gchar *msg);
static void report_counts(void);
#ifdef _WIN32
static BOOL WINAPI capture_cleanup(DWORD);
#else /* _WIN32 */
static void capture_cleanup(int);
#ifdef SIGINFO
static void report_counts_siginfo(int);
#endif /* SIGINFO */
#endif /* _WIN32 */
#endif /* HAVE_LIBPCAP */
static void reset_epan_mem(capture_file *cf, epan_dissect_t *edt, gboolean tree, gboolean visual);
typedef enum {
PROCESS_FILE_SUCCEEDED,
PROCESS_FILE_NO_FILE_PROCESSED,
PROCESS_FILE_ERROR,
PROCESS_FILE_INTERRUPTED
} process_file_status_t;
static process_file_status_t process_cap_file(capture_file *, char *, int, gboolean, int, gint64, int);
static gboolean process_packet_single_pass(capture_file *cf,
epan_dissect_t *edt, gint64 offset, wtap_rec *rec, Buffer *buf,
guint tap_flags);
static void show_print_file_io_error(void);
static gboolean write_preamble(capture_file *cf);
static gboolean print_packet(capture_file *cf, epan_dissect_t *edt);
static gboolean write_finale(void);
static void tshark_cmdarg_err(const char *msg_format, va_list ap);
static void tshark_cmdarg_err_cont(const char *msg_format, va_list ap);
static GHashTable *output_only_tables = NULL;
wiretap: more work on file type/subtypes. Provide a wiretap routine to get an array of all savable file type/subtypes, sorted with pcap and pcapng at the top, followed by the other types, sorted either by the name or the description. Use that routine to list options for the -F flag for various commands Rename wtap_get_savable_file_types_subtypes() to wtap_get_savable_file_types_subtypes_for_file(), to indicate that it provides an array of all file type/subtypes in which a given file can be saved. Have it sort all types, other than the default type/subtype and, if there is one, the "other" type (both of which are put at the top), by the name or the description. Don't allow wtap_register_file_type_subtypes() to override any existing registrations; have them always register a new type. In that routine, if there are any emply slots in the table, due to an entry being unregistered, use it rather than allocating a new slot. Don't allow unregistration of built-in types. Rename the "dump open table" to the "file type/subtype table", as it has entries for all types/subtypes, even if we can't write them. Initialize that table in a routine that pre-allocates the GArray before filling it with built-in types/subtypes, so it doesn't keep getting reallocated. Get rid of wtap_num_file_types_subtypes - it's just a copy of the size of the GArray. Don't have wtap_file_type_subtype_description() crash if handed an file type/subtype that isn't a valid array index - just return NULL, as we do with wtap_file_type_subtype_name(). In wtap_name_to_file_type_subtype(), don't use WTAP_FILE_TYPE_SUBTYPE_ names for the backwards-compatibility names - map those names to the current names, and then look them up. This reduces the number of uses of hardwired WTAP_FILE_TYPE_SUBTYPE_ values. Clean up the type of wtap_module_count - it has no need to be a gulong. Have built-in wiretap file handlers register names to be used for their file type/subtypes, rather than building the table in init.lua. Add a new Lua C function get_wtap_filetypes() to construct the wtap_filetypes table, based on the registered names, and use it in init.lua. Add a #define WSLUA_INTERNAL_FUNCTION to register functions intended only for internal use in init.lua, so they can be made available from Lua without being documented. Get rid of WTAP_NUM_FILE_TYPES_SUBTYPES - most code has no need to use it, as it can just request arrays of types, and the space of type/subtype codes can be sparse due to registration in any case, so code has to be careful using it. wtap_get_num_file_types_subtypes() is no longer used, so remove it. It returns the number of elements in the file type/subtype array, which is not necessarily the name of known file type/subtypes, as there may have been some deregistered types, and those types do *not* get removed from the array, they just get cleared so that they're available for future allocation (we don't want the indices of any registered types to changes if another type is deregistered, as those indicates are the type/subtype values, so we can't shrink the array). Clean up white space and remove some comments that shouldn't have been added.
2 years ago
static void
list_capture_types(void)
{
GArray *writable_type_subtypes;
fprintf(stderr, "tshark: The available capture file types for the \"-F\" flag are:\n");
writable_type_subtypes = wtap_get_writable_file_types_subtypes(FT_SORT_BY_NAME);
for (guint i = 0; i < writable_type_subtypes->len; i++) {
int ft = g_array_index(writable_type_subtypes, int, i);
fprintf(stderr, " %s - %s\n", wtap_file_type_subtype_name(ft),
wtap_file_type_subtype_description(ft));
}
g_array_free(writable_type_subtypes, TRUE);
wiretap: more work on file type/subtypes. Provide a wiretap routine to get an array of all savable file type/subtypes, sorted with pcap and pcapng at the top, followed by the other types, sorted either by the name or the description. Use that routine to list options for the -F flag for various commands Rename wtap_get_savable_file_types_subtypes() to wtap_get_savable_file_types_subtypes_for_file(), to indicate that it provides an array of all file type/subtypes in which a given file can be saved. Have it sort all types, other than the default type/subtype and, if there is one, the "other" type (both of which are put at the top), by the name or the description. Don't allow wtap_register_file_type_subtypes() to override any existing registrations; have them always register a new type. In that routine, if there are any emply slots in the table, due to an entry being unregistered, use it rather than allocating a new slot. Don't allow unregistration of built-in types. Rename the "dump open table" to the "file type/subtype table", as it has entries for all types/subtypes, even if we can't write them. Initialize that table in a routine that pre-allocates the GArray before filling it with built-in types/subtypes, so it doesn't keep getting reallocated. Get rid of wtap_num_file_types_subtypes - it's just a copy of the size of the GArray. Don't have wtap_file_type_subtype_description() crash if handed an file type/subtype that isn't a valid array index - just return NULL, as we do with wtap_file_type_subtype_name(). In wtap_name_to_file_type_subtype(), don't use WTAP_FILE_TYPE_SUBTYPE_ names for the backwards-compatibility names - map those names to the current names, and then look them up. This reduces the number of uses of hardwired WTAP_FILE_TYPE_SUBTYPE_ values. Clean up the type of wtap_module_count - it has no need to be a gulong. Have built-in wiretap file handlers register names to be used for their file type/subtypes, rather than building the table in init.lua. Add a new Lua C function get_wtap_filetypes() to construct the wtap_filetypes table, based on the registered names, and use it in init.lua. Add a #define WSLUA_INTERNAL_FUNCTION to register functions intended only for internal use in init.lua, so they can be made available from Lua without being documented. Get rid of WTAP_NUM_FILE_TYPES_SUBTYPES - most code has no need to use it, as it can just request arrays of types, and the space of type/subtype codes can be sparse due to registration in any case, so code has to be careful using it. wtap_get_num_file_types_subtypes() is no longer used, so remove it. It returns the number of elements in the file type/subtype array, which is not necessarily the name of known file type/subtypes, as there may have been some deregistered types, and those types do *not* get removed from the array, they just get cleared so that they're available for future allocation (we don't want the indices of any registered types to changes if another type is deregistered, as those indicates are the type/subtype values, so we can't shrink the array). Clean up white space and remove some comments that shouldn't have been added.
2 years ago
}
struct string_elem {
const char *sstr; /* The short string */
const char *lstr; /* The long string */
};
static gint
string_compare(gconstpointer a, gconstpointer b)
{
return strcmp(((const struct string_elem *)a)->sstr,
((const struct string_elem *)b)->sstr);
}
static void
string_elem_print(gpointer data)
{
fprintf(stderr, " %s - %s\n",
((struct string_elem *)data)->sstr,
((struct string_elem *)data)->lstr);
}
static void
list_read_capture_types(void)
{
guint i;
size_t num_file_types;
struct string_elem *captypes;
GSList *list = NULL;
const char *magic = "Magic-value-based";
const char *heuristic = "Heuristics-based";
/* How many readable file types are there? */
num_file_types = 0;
for (i = 0; open_routines[i].name != NULL; i++)
num_file_types++;
captypes = g_new(struct string_elem, num_file_types);
fprintf(stderr, "tshark: The available read file types for the \"-X read_format:\" option are:\n");
for (i = 0; i < num_file_types && open_routines[i].name != NULL; i++) {
captypes[i].sstr = open_routines[i].name;
captypes[i].lstr = (open_routines[i].type == OPEN_INFO_MAGIC) ? magic : heuristic;
list = g_slist_insert_sorted(list, &captypes[i], string_compare);
}
g_slist_free_full(list, string_elem_print);
g_free(captypes);
}
static void
list_export_pdu_taps(void)
{
fprintf(stderr, "tshark: The available export tap names and the encapsulation types they produce for the \"-U tap_name\" option are:\n");
for (GSList *export_pdu_tap_name_list = get_export_pdu_tap_list();
export_pdu_tap_name_list != NULL;
export_pdu_tap_name_list = g_slist_next(export_pdu_tap_name_list)) {
fprintf(stderr, " %s - %s\n", (const char*)(export_pdu_tap_name_list->data), wtap_encap_description(export_pdu_tap_get_encap((const char*)export_pdu_tap_name_list->data)));
}
}
static void
print_usage(FILE *output)
{
fprintf(output, "\n");
fprintf(output, "Usage: tshark [options] ...\n");
fprintf(output, "\n");
#ifdef HAVE_LIBPCAP
fprintf(output, "Capture interface:\n");
fprintf(output, " -i <interface>, --interface <interface>\n");
fprintf(output, " name or idx of interface (def: first non-loopback)\n");
fprintf(output, " -f <capture filter> packet filter in libpcap filter syntax\n");
fprintf(output, " -s <snaplen>, --snapshot-length <snaplen>\n");
#ifdef HAVE_PCAP_CREATE
fprintf(output, " packet snapshot length (def: appropriate maximum)\n");
#else
fprintf(output, " packet snapshot length (def: %u)\n", WTAP_MAX_PACKET_SIZE_STANDARD);
#endif
fprintf(output, " -p, --no-promiscuous-mode\n");
fprintf(output, " don't capture in promiscuous mode\n");
#ifdef HAVE_PCAP_CREATE
fprintf(output, " -I, --monitor-mode capture in monitor mode, if available\n");
#endif
#ifdef CAN_SET_CAPTURE_BUFFER_SIZE
fprintf(output, " -B <buffer size>, --buffer-size <buffer size>\n");
fprintf(output, " size of kernel buffer (def: %dMB)\n", DEFAULT_CAPTURE_BUFFER_SIZE);
#endif
fprintf(output, " -y <link type>, --linktype <link type>\n");
fprintf(output, " link layer type (def: first appropriate)\n");
fprintf(output, " --time-stamp-type <type> timestamp method for interface\n");
fprintf(output, " -D, --list-interfaces print list of interfaces and exit\n");
fprintf(output, " -L, --list-data-link-types\n");
fprintf(output, " print list of link-layer types of iface and exit\n");
fprintf(output, " --list-time-stamp-types print list of timestamp types for iface and exit\n");
fprintf(output, "\n");
fprintf(output, "Capture stop conditions:\n");
fprintf(output, " -c <packet count> stop after n packets (def: infinite)\n");
fprintf(output, " -a <autostop cond.> ..., --autostop <autostop cond.> ...\n");
fprintf(output, " duration:NUM - stop after NUM seconds\n");
fprintf(output, " filesize:NUM - stop this file after NUM KB\n");
fprintf(output, " files:NUM - stop after NUM files\n");
fprintf(output, " packets:NUM - stop after NUM packets\n");
/*fprintf(output, "\n");*/
fprintf(output, "Capture output:\n");
fprintf(output, " -b <ringbuffer opt.> ..., --ring-buffer <ringbuffer opt.>\n");
fprintf(output, " duration:NUM - switch to next file after NUM secs\n");
fprintf(output, " filesize:NUM - switch to next file after NUM KB\n");
fprintf(output, " files:NUM - ringbuffer: replace after NUM files\n");
fprintf(output, " packets:NUM - switch to next file after NUM packets\n");
fprintf(output, " interval:NUM - switch to next file when the time is\n");
fprintf(output, " an exact multiple of NUM secs\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>, --read-file <infile>\n");
fprintf(output, " set the filename to read from (or '-' for stdin)\n");
fprintf(output, "\n");
fprintf(output, "Processing:\n");
fprintf(output, " -2 perform a two-pass analysis\n");
fprintf(output, " -M <packet count> perform session auto reset\n");
fprintf(output, " -R <read filter>, --read-filter <read filter>\n");
fprintf(output, " packet Read filter in Wireshark display filter syntax\n");
fprintf(output, " (requires -2)\n");
fprintf(output, " -Y <display filter>, --display-filter <display filter>\n");
fprintf(output, " packet displaY filter in Wireshark display filter\n");
fprintf(output, " syntax\n");
fprintf(output, " -n disable all name resolutions (def: \"mNd\" enabled, or\n");
fprintf(output, " as set in preferences)\n");
fprintf(output, " -N <name resolve flags> enable specific name resolution(s): \"mnNtdv\"\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, " --enable-protocol <proto_name>\n");
fprintf(output, " enable dissection of proto_name\n");
fprintf(output, " --disable-protocol <proto_name>\n");
fprintf(output, " disable dissection of proto_name\n");
fprintf(output, " --enable-heuristic <short_name>\n");
fprintf(output, " enable dissection of heuristic protocol\n");
fprintf(output, " --disable-heuristic <short_name>\n");
fprintf(output, " disable dissection of heuristic protocol\n");
/*fprintf(output, "\n");*/
fprintf(output, "Output:\n");
fprintf(output, " -w <outfile|-> write packets to a pcapng-format file named \"outfile\"\n");
fprintf(output, " (or '-' for stdout)\n");
fprintf(output, " --capture-comment <comment>\n");
fprintf(output, " add a capture file comment, if supported\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 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, " -P, --print 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, " --hexdump <hexoption> add hexdump, set options for data source and ASCII dump\n");
fprintf(output, " all dump all data sources (-x default)\n");
fprintf(output, " frames dump only frame data source\n");
fprintf(output, " ascii include ASCII dump text (-x default)\n");
fprintf(output, " delimit delimit ASCII dump text with '|' characters\n");
fprintf(output, " noascii exclude ASCII dump text\n");
fprintf(output, " help display help for --hexdump and exit\n");
fprintf(output, " -T pdml|ps|psml|json|jsonraw|ek|tabs|text|fields|?\n");
fprintf(output, " format of text output (def: text)\n");
fprintf(output, " -j <protocolfilter> protocols layers filter if -T ek|pdml|json selected\n");
fprintf(output, " (e.g. \"ip ip.flags text\", filter does not expand child\n");
fprintf(output, " nodes, unless child is specified also in the filter)\n");
fprintf(output, " -J <protocolfilter> top level protocol filter if -T ek|pdml|json selected\n");
fprintf(output, " (e.g. \"http tcp\", filter which expands all child nodes)\n");
fprintf(output, " -e <field> field to print if -Tfields selected (e.g. tcp.port,\n");
fprintf(output, " _ws.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, " bom=y|n print a UTF-8 BOM\n");
fprintf(output, " header=y|n switch headers on and off\n");
fprintf(output, " separator=/t|/s|<char> select tab, space, printable character as separator\n");
fprintf(output, " occurrence=f|l|a print first, last or all occurrences of each field\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 a|ad|adoy|d|dd|e|r|u|ud|udoy\n");
fprintf(output, " 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, " -U tap_name PDUs export mode, see the man page for details\n");
fprintf(output, " -z <statistics> various statistics, see the man page for details\n");
fprintf(output, " --export-objects <protocol>,<destdir>\n");
fprintf(output, " save exported objects for a protocol to a directory\n");
fprintf(output, " named \"destdir\"\n");
fprintf(output, " --export-tls-session-keys <keyfile>\n");
fprintf(output, " export TLS Session Keys to a file named \"keyfile\"\n");
fprintf(output, " --color color output text similarly to the Wireshark GUI,\n");
fprintf(output, " requires a terminal with 24-bit color support\n");
fprintf(output, " Also supplies color attributes to pdml and psml formats\n");
fprintf(output, " (Note that attributes are nonstandard)\n");
fprintf(output, " --no-duplicate-keys If -T json is specified, merge duplicate keys in an object\n");
fprintf(output, " into a single key with as value a json array containing all\n");
fprintf(output, " values\n");
fprintf(output, " --elastic-mapping-filter <protocols> If -G elastic-mapping is specified, put only the\n");
fprintf(output, " specified protocols within the mapping file\n");
fprintf(output, " --temp-dir <directory> write temporary files to this directory\n");
fprintf(output, " (default: %s)\n", g_get_tmp_dir());
fprintf(output, "\n");
ws_log_print_usage(output);
fprintf(output, "\n");
fprintf(output, "Miscellaneous:\n");
fprintf(output, " -h, --help display this help and exit\n");
fprintf(output, " -v, --version display version info and exit\n");
fprintf(output, " -o <name>:<value> ... override preference setting\n");
fprintf(output, " -K <keytab> keytab file to use for kerberos decryption\n");
fprintf(output, " -G [report] dump one of several available reports and exit\n");
fprintf(output, " default report=\"fields\"\n");
fprintf(output, " use \"-G help\" for more help\n");
#ifdef __linux__
fprintf(output, "\n");
fprintf(output, "Dumpcap can benefit from an enabled BPF JIT compiler if available.\n");
fprintf(output, "You might want to enable it by executing:\n");
fprintf(output, " \"echo 1 > /proc/sys/net/core/bpf_jit_enable\"\n");
fprintf(output, "Note that this can make your system less secure!\n");
#endif
}
static void
glossary_option_help(void)
{
FILE *output;
output = stdout;
fprintf(output, "%s\n", get_appname_and_version());
fprintf(output, "\n");
fprintf(output, "Usage: tshark -G [report]\n");
fprintf(output, "\n");
fprintf(output, "Glossary table reports:\n");
fprintf(output, " -G column-formats dump column format codes and exit\n");
fprintf(output, " -G decodes dump \"layer type\"/\"decode as\" associations and exit\n");
fprintf(output, " -G dissector-tables dump dissector table names, types, and properties\n");
fprintf(output, " -G elastic-mapping dump ElasticSearch mapping file\n");
fprintf(output, " -G fieldcount dump count of header fields and exit\n");
fprintf(output, " -G fields dump fields glossary and exit\n");
fprintf(output, " -G ftypes dump field type basic and descriptive names\n");
fprintf(output, " -G heuristic-decodes dump heuristic dissector tables\n");
fprintf(output, " -G plugins dump installed plugins 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, "\n");
fprintf(output, "Preference reports:\n");
fprintf(output, " -G currentprefs dump current preferences and exit\n");
fprintf(output, " -G defaultprefs dump default preferences and exit\n");
fprintf(output, " -G folders dump about:folders\n");
fprintf(output, "\n");
}
static void
hexdump_option_help(FILE *output)
{
fprintf(output, "%s\n", get_appname_and_version());
fprintf(output, "\n");
fprintf(output, "tshark: Valid --hexdump <hexoption> values include:\n");
fprintf(output, "\n");
fprintf(output, "Data source options:\n");
fprintf(output, " all add hexdump, dump all data sources (-x default)\n");
fprintf(output, " frames add hexdump, dump only frame data source\n");
fprintf(output, "\n");
fprintf(output, "ASCII options:\n");
fprintf(output, " ascii add hexdump, include ASCII dump text (-x default)\n");
fprintf(output, " delimit add hexdump, delimit ASCII dump text with '|' characters\n");
fprintf(output, " noascii add hexdump, exclude ASCII dump text\n");
fprintf(output, "\n");
fprintf(output, "Miscellaneous:\n");
fprintf(output, " help display this help and exit\n");
fprintf(output, "\n");
fprintf(output, "Example:\n");
fprintf(output, "\n");
fprintf(output, " $ tshark ... --hexdump frames --hexdump delimit ...\n");
fprintf(output, "\n");
}
static void
protocolfilter_add_opt(const char* arg, pf_flags filter_flags)
{
void* value;
gchar **newfilter = NULL;
for (newfilter = wmem_strsplit(wmem_epan_scope(), arg, " ", -1); *newfilter; newfilter++) {
if (strcmp(*newfilter, "") == 0) {
/* Don't treat the empty string as an intended field abbreviation
* to output, consecutive spaces on the command line probably
* aren't intentional.
*/
continue;
}
if (!protocolfilter) {
protocolfilter = wmem_map_new(wmem_epan_scope(), wmem_str_hash, g_str_equal);
}
if (wmem_map_lookup_extended(protocolfilter, *newfilter, NULL, &value)) {
if (GPOINTER_TO_UINT(value) != (guint)filter_flags) {
cmdarg_err("%s was already specified with different filter flags. Overwriting previous protocol filter.", *newfilter);
}
}
wmem_map_insert(protocolfilter, *newfilter, GINT_TO_POINTER(filter_flags));
}
}
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();
fprintf(stderr, "Running as user \"%s\" and group \"%s\".",
cur_user, cur_group);
g_free(cur_user);
g_free(cur_group);
if (running_with_special_privs()) {
fprintf(stderr, " This could be dangerous.");
}
fprintf(stderr, "\n");
}