Add hardware timestamping support

pcap provides a pcap_set_tstamp_type function, which can be used to request
hardware timestamps from a supporting kernel.

This patch adds support for aforementioned function as well as two new
command line options to dumpcap, wireshark and tshark:

    --list-time-stamp-types
                             List time stamp types supported for the interface
    --time-stamp-type <type>
                             Change the interface's timestamp method

Name choice mimics those used by tcpdump(1), which already supports this
feature. However, unlike tcpdump, we provide both options unconditionally.
If Wireshark was configured without pcap_set_tstamp_type being available,
--list-time-stamp-types reports an empty list.

Change-Id: I418a4b2b84cb01949cd262aad0ad8427f5ac0652
Signed-off-by: Ahmad Fatoum <ahmad.fatoum@siemens.com>
Reviewed-on: https://code.wireshark.org/review/23113
Petri-Dish: Guy Harris <guy@alum.mit.edu>
Tested-by: Petri Dish Buildbot <buildbot-no-reply@wireshark.org>
Reviewed-by: Anders Broman <a.broman58@gmail.com>
This commit is contained in:
Ahmad Fatoum 2017-08-07 16:38:52 +02:00 committed by Anders Broman
parent 2845f6be8d
commit aca55a29f7
22 changed files with 379 additions and 102 deletions

View File

@ -412,7 +412,7 @@ install a newer version of the header file.])
AC_DEFINE(CAN_SET_CAPTURE_BUFFER_SIZE, 1,
[Define to 1 if the capture buffer size can be set.])
])
AC_CHECK_FUNCS(bpf_image pcap_set_tstamp_precision)
AC_CHECK_FUNCS(bpf_image pcap_set_tstamp_precision pcap_set_tstamp_type)
fi
AC_WIRESHARK_POP_FLAGS

View File

@ -228,11 +228,10 @@ capture_get_if_capabilities(const gchar *ifname, gboolean monitor_mode,
char **err_str, void (*update_cb)(void))
{
if_capabilities_t *caps;
GList *linktype_list = NULL;
GList *linktype_list = NULL, *timestamp_list = NULL;
int err, i;
gchar *data, *primary_msg, *secondary_msg;
gchar **raw_list, **lt_parts;
data_link_info_t *data_link_info;
gchar **raw_list;
g_log(LOG_DOMAIN_CAPTURE, G_LOG_LEVEL_MESSAGE, "Capture Interface Capabilities ...");
@ -309,11 +308,12 @@ capture_get_if_capabilities(const gchar *ifname, gboolean monitor_mode,
}
/*
* The rest are link-layer types.
* The following are link-layer types.
*/
for (i = 1; raw_list[i] != NULL; i++) {
for (i = 1; raw_list[i] != NULL && *raw_list[i] != '\0'; i++) {
data_link_info_t *data_link_info;
/* ...and what if the interface name has a tab in it, Mr. Clever Programmer? */
lt_parts = g_strsplit(raw_list[i], "\t", 3);
char **lt_parts = g_strsplit(raw_list[i], "\t", 3);
if (lt_parts[0] == NULL || lt_parts[1] == NULL || lt_parts[2] == NULL) {
g_strfreev(lt_parts);
continue;
@ -330,6 +330,25 @@ capture_get_if_capabilities(const gchar *ifname, gboolean monitor_mode,
linktype_list = g_list_append(linktype_list, data_link_info);
}
if (raw_list[i]) { /* Oh, timestamp types! */
for (i++; raw_list[i] != NULL && *raw_list[i] != '\0'; i++) {
timestamp_info_t *timestamp_info;
char **tt_parts = g_strsplit(raw_list[i], "\t", 2);
if (tt_parts[0] == NULL || tt_parts[1] == NULL) {
g_strfreev(tt_parts);
continue;
}
timestamp_info = g_new(timestamp_info_t,1);
timestamp_info->name = g_strdup(tt_parts[0]);
timestamp_info->description = g_strdup(tt_parts[1]);
g_strfreev(tt_parts);
timestamp_list = g_list_append(timestamp_list, timestamp_info);
}
}
g_strfreev(raw_list);
/* Check to see if we built a list */
@ -340,7 +359,11 @@ capture_get_if_capabilities(const gchar *ifname, gboolean monitor_mode,
g_free(caps);
return NULL;
}
caps->data_link_types = linktype_list;
/* Might be NULL. Not all systems report timestamp types */
caps->timestamp_types = timestamp_list;
return caps;
}

View File

@ -412,6 +412,10 @@ sync_pipe_start(capture_options *capture_opts, capture_session *cap_session, inf
argv = sync_pipe_add_arg(argv, &argc, ssampling);
}
#endif
if (interface_opts.timestamp_type) {
argv = sync_pipe_add_arg(argv, &argc, "--time-stamp-type");
argv = sync_pipe_add_arg(argv, &argc, interface_opts.timestamp_type);
}
}
/* dumpcap should be running in capture child mode (hidden feature) */
@ -1302,6 +1306,7 @@ sync_if_capabilities_open(const gchar *ifname, gboolean monitor_mode, const gcha
argv = sync_pipe_add_arg(argv, &argc, "-i");
argv = sync_pipe_add_arg(argv, &argc, ifname);
argv = sync_pipe_add_arg(argv, &argc, "-L");
argv = sync_pipe_add_arg(argv, &argc, "--list-time-stamp-types");
if (monitor_mode)
argv = sync_pipe_add_arg(argv, &argc, "-I");
if (auth) {

View File

@ -90,6 +90,7 @@ capture_opts_init(capture_options *capture_opts)
capture_opts->default_options.sampling_method = CAPTURE_SAMP_NONE;
capture_opts->default_options.sampling_param = 0;
#endif
capture_opts->default_options.timestamp_type = NULL;
capture_opts->saving_to_file = FALSE;
capture_opts->save_file = NULL;
capture_opts->group_read_access = FALSE;
@ -193,6 +194,7 @@ capture_opts_log(const char *log_domain, GLogLevelFlags log_level, capture_optio
g_log(log_domain, log_level, "Sampling meth.[%02d] : %d", i, interface_opts.sampling_method);
g_log(log_domain, log_level, "Sampling param.[%02d] : %d", i, interface_opts.sampling_param);
#endif
g_log(log_domain, log_level, "Timestamp type [%02d] : %s", i, interface_opts.timestamp_type);
}
g_log(log_domain, log_level, "Interface name[df] : %s", capture_opts->default_options.name ? capture_opts->default_options.name : "(unspecified)");
g_log(log_domain, log_level, "Interface Descr[df] : %s", capture_opts->default_options.descr ? capture_opts->default_options.descr : "(unspecified)");
@ -233,6 +235,7 @@ capture_opts_log(const char *log_domain, GLogLevelFlags log_level, capture_optio
g_log(log_domain, log_level, "Sampling meth. [df] : %d", capture_opts->default_options.sampling_method);
g_log(log_domain, log_level, "Sampling param.[df] : %d", capture_opts->default_options.sampling_param);
#endif
g_log(log_domain, log_level, "Timestamp type [df] : %s", capture_opts->default_options.timestamp_type ? capture_opts->default_options.timestamp_type : "(unspecified)");
g_log(log_domain, log_level, "SavingToFile : %u", capture_opts->saving_to_file);
g_log(log_domain, log_level, "SaveFile : %s", (capture_opts->save_file) ? capture_opts->save_file : "");
g_log(log_domain, log_level, "GroupReadAccess : %u", capture_opts->group_read_access);
@ -732,6 +735,7 @@ capture_opts_add_iface_opt(capture_options *capture_opts, const char *optarg_str
interface_opts.sampling_method = capture_opts->default_options.sampling_method;
interface_opts.sampling_param = capture_opts->default_options.sampling_param;
#endif
interface_opts.timestamp_type = capture_opts->default_options.timestamp_type;
g_array_append_val(capture_opts->ifaces, interface_opts);
@ -800,6 +804,18 @@ capture_opts_add_opt(capture_options *capture_opts, int opt, const char *optarg_
case 'H': /* Hide capture info dialog box */
capture_opts->show_info = FALSE;
break;
case LONGOPT_SET_TSTAMP_TYPE: /* Set capture time stamp type */
if (capture_opts->ifaces->len > 0) {
interface_options interface_opts;
interface_opts = g_array_index(capture_opts->ifaces, interface_options, capture_opts->ifaces->len - 1);
capture_opts->ifaces = g_array_remove_index(capture_opts->ifaces, capture_opts->ifaces->len - 1);
interface_opts.timestamp_type = g_strdup(optarg_str_p);
g_array_append_val(capture_opts->ifaces, interface_opts);
} else {
capture_opts->default_options.timestamp_type = g_strdup(optarg_str_p);
}
break;
case 'i': /* Use interface x */
status = capture_opts_add_iface_opt(capture_opts, optarg_str_p);
if (status != 0) {
@ -939,26 +955,40 @@ capture_opts_add_opt(capture_options *capture_opts, int opt, const char *optarg_
}
void
capture_opts_print_if_capabilities(if_capabilities_t *caps, char *name,
gboolean monitor_mode)
capture_opts_print_if_capabilities(if_capabilities_t *caps, char *name, int queries)
{
GList *lt_entry;
data_link_info_t *data_link_info;
GList *lt_entry, *ts_entry;
if (caps->can_set_rfmon)
printf("Data link types of interface %s when %sin monitor mode (use option -y to set):\n",
name, monitor_mode ? "" : "not ");
else
printf("Data link types of interface %s (use option -y to set):\n", name);
for (lt_entry = caps->data_link_types; lt_entry != NULL;
lt_entry = g_list_next(lt_entry)) {
data_link_info = (data_link_info_t *)lt_entry->data;
printf(" %s", data_link_info->name);
if (data_link_info->description != NULL)
printf(" (%s)", data_link_info->description);
if (queries & CAPS_QUERY_LINK_TYPES) {
if (caps->can_set_rfmon)
printf("Data link types of interface %s when %sin monitor mode (use option -y to set):\n",
name, queries & CAPS_MONITOR_MODE ? "" : "not ");
else
printf(" (not supported)");
printf("\n");
printf("Data link types of interface %s (use option -y to set):\n", name);
for (lt_entry = caps->data_link_types; lt_entry != NULL;
lt_entry = g_list_next(lt_entry)) {
data_link_info_t *data_link_info = (data_link_info_t *)lt_entry->data;
printf(" %s", data_link_info->name);
if (data_link_info->description != NULL)
printf(" (%s)", data_link_info->description);
else
printf(" (not supported)");
printf("\n");
}
}
if (queries & CAPS_QUERY_TIMESTAMP_TYPES) {
printf("Timestamp types of the interface (use option --time-stamp-type to set):\n");
for (ts_entry = caps->timestamp_types; ts_entry != NULL;
ts_entry = g_list_next(ts_entry)) {
timestamp_info_t *timestamp = (timestamp_info_t *)ts_entry->data;
printf(" %s", timestamp->name);
if (timestamp->description != NULL)
printf(" (%s)", timestamp->description);
else
printf(" (none)");
printf("\n");
}
}
}

View File

@ -60,7 +60,9 @@ extern "C" {
* In short: we must not use 1 here, which is another reason to use
* values outside the range of ASCII graphic characters.
*/
#define LONGOPT_NUM_CAP_COMMENT 128
#define LONGOPT_NUM_CAP_COMMENT 128
#define LONGOPT_LIST_TSTAMP_TYPES 129
#define LONGOPT_SET_TSTAMP_TYPE 130
/*
* Options for capturing common to all capturing programs.
@ -89,17 +91,20 @@ extern "C" {
#endif
#define LONGOPT_CAPTURE_COMMON \
{"capture-comment", required_argument, NULL, LONGOPT_NUM_CAP_COMMENT}, \
{"autostop", required_argument, NULL, 'a'}, \
{"ring-buffer", required_argument, NULL, 'b'}, \
{"capture-comment", required_argument, NULL, LONGOPT_NUM_CAP_COMMENT}, \
{"autostop", required_argument, NULL, 'a'}, \
{"ring-buffer", required_argument, NULL, 'b'}, \
LONGOPT_BUFFER_SIZE \
{"list-interfaces", no_argument, NULL, 'D'}, \
{"interface", required_argument, NULL, 'i'}, \
{"list-interfaces", no_argument, NULL, 'D'}, \
{"interface", required_argument, NULL, 'i'}, \
LONGOPT_MONITOR_MODE \
{"list-data-link-types", no_argument, NULL, 'L'}, \
{"no-promiscuous-mode", no_argument, NULL, 'p'}, \
{"snapshot-length", required_argument, NULL, 's'}, \
{"linktype", required_argument, NULL, 'y'}, \
{"list-data-link-types", no_argument, NULL, 'L'}, \
{"no-promiscuous-mode", no_argument, NULL, 'p'}, \
{"snapshot-length", required_argument, NULL, 's'}, \
{"linktype", required_argument, NULL, 'y'}, \
{"list-time-stamp-types", no_argument, NULL, LONGOPT_LIST_TSTAMP_TYPES}, \
{"time-stamp-type", required_argument, NULL, LONGOPT_SET_TSTAMP_TYPE},
#define OPTSTRING_CAPTURE_COMMON \
"a:" OPTSTRING_A "b:" OPTSTRING_B "c:Df:i:" OPTSTRING_I "Lps:y:"
@ -248,6 +253,9 @@ typedef struct interface_options_tag {
capture_sampling sampling_method;
int sampling_param;
#endif
gchar *timestamp_type; /* requested timestamp as string */
int timestamp_type_id; /* Timestamp type to pass to pcap_set_tstamp_type.
only valid if timestamp_type != NULL */
} interface_options;
/** Capture options coming from user interface */
@ -342,10 +350,15 @@ capture_opts_add_opt(capture_options *capture_opts, int opt, const char *optarg,
extern void
capture_opts_log(const char *log_domain, GLogLevelFlags log_level, capture_options *capture_opts);
enum caps_query {
CAPS_MONITOR_MODE = 0x1,
CAPS_QUERY_LINK_TYPES = 0x2,
CAPS_QUERY_TIMESTAMP_TYPES = 0x4
};
/* print interface capabilities, including link layer types */
extern void
capture_opts_print_if_capabilities(if_capabilities_t *caps, char *name,
gboolean monitor_mode);
capture_opts_print_if_capabilities(if_capabilities_t *caps, char *name, int queries);
/* print list of interfaces */
extern void

View File

@ -668,11 +668,24 @@ free_linktype_cb(gpointer data, gpointer user_data _U_)
g_free(linktype_info);
}
static void
free_timestamp_cb(gpointer data, gpointer user_data _U_)
{
/* timestamp_info_t's contents are immutable and in static memory,
* so we only need to free the struct itself
*/
g_free(data);
}
void
free_if_capabilities(if_capabilities_t *caps)
{
g_list_foreach(caps->data_link_types, free_linktype_cb, NULL);
g_list_free(caps->data_link_types);
g_list_foreach(caps->timestamp_types, free_timestamp_cb, NULL);
g_list_free(caps->timestamp_types);
g_free(caps);
}
@ -861,10 +874,7 @@ create_data_link_info(int dlt)
else
data_link_info->name = g_strdup_printf("DLT %d", dlt);
text = pcap_datalink_val_to_description(dlt);
if (text != NULL)
data_link_info->description = g_strdup(text);
else
data_link_info->description = NULL;
data_link_info->description = g_strdup(text);
return data_link_info;
}
@ -960,6 +970,34 @@ get_data_link_types(pcap_t *pch, interface_options *interface_opts,
return data_link_types;
}
/* Get supported timestamp types for a libpcap device. */
static GList*
get_pcap_timestamp_types(pcap_t *pch _U_, char **err_str _U_)
{
GList *list = NULL;
#ifdef HAVE_PCAP_SET_TSTAMP_TYPE
int *types;
int ntypes = pcap_list_tstamp_types(pch, &types);
if (err_str)
*err_str = ntypes < 0 ? pcap_geterr(pch) : NULL;
if (ntypes <= 0)
return NULL;
while (ntypes--) {
timestamp_info_t *info = (timestamp_info_t *)g_malloc(sizeof *info);
info->name = pcap_tstamp_type_val_to_name(types[ntypes]);
info->description = pcap_tstamp_type_val_to_description(types[ntypes]);
list = g_list_prepend(list, info);
}
pcap_free_tstamp_types(types);
#endif
return list;
}
#ifdef HAVE_PCAP_CREATE
#ifdef HAVE_BONDING
static gboolean
@ -1079,6 +1117,8 @@ get_if_capabilities_pcap_create(interface_options *interface_opts,
return NULL;
}
caps->timestamp_types = get_pcap_timestamp_types(pch, NULL);
pcap_close(pch);
if (err_str != NULL)
@ -1088,7 +1128,7 @@ get_if_capabilities_pcap_create(interface_options *interface_opts,
pcap_t *
open_capture_device_pcap_create(capture_options *capture_opts
#ifdef HAVE_PCAP_SET_TSTAMP_PRECISION
#if defined(HAVE_PCAP_SET_TSTAMP_PRECISION) || defined (HAVE_PCAP_SET_TSTAMP_TYPE)
,
#else
_U_,
@ -1141,6 +1181,18 @@ open_capture_device_pcap_create(capture_options *capture_opts
request_high_resolution_timestamp(pcap_h);
#endif /* HAVE_PCAP_SET_TSTAMP_PRECISION */
#ifdef HAVE_PCAP_SET_TSTAMP_TYPE
if (interface_opts->timestamp_type) {
err = pcap_set_tstamp_type(pcap_h, interface_opts->timestamp_type_id);
if (err == PCAP_ERROR) {
g_strlcpy(*open_err_str, pcap_geterr(pcap_h),
sizeof *open_err_str);
pcap_close(pcap_h);
return NULL;
}
}
#endif /* HAVE_PCAP_SET_TSTAMP_PRECISION */
g_log(LOG_DOMAIN_CAPTURE_CHILD, G_LOG_LEVEL_DEBUG,
"buffersize %d.", interface_opts->buffer_size);
if (interface_opts->buffer_size != 0)
@ -1195,6 +1247,8 @@ get_if_capabilities_pcap_open_live(interface_options *interface_opts,
return NULL;
}
caps->timestamp_types = get_pcap_timestamp_types(pch, NULL);
pcap_close(pch);
if (err_str != NULL)
@ -1295,8 +1349,8 @@ get_if_capabilities(interface_options *interface_opts, char **err_str)
caps->data_link_types = NULL;
deflt = get_pcap_datalink(pch, interface_opts->name);
data_link_info = create_data_link_info(deflt);
caps->data_link_types = g_list_append(caps->data_link_types,
data_link_info);
caps->data_link_types = g_list_append(caps->data_link_types, data_link_info);
caps->timestamp_types = get_pcap_timestamp_types(pch, NULL);
pcap_close(pch);
if (err_str != NULL)

View File

@ -99,6 +99,7 @@ void free_interface_list(GList *if_list);
typedef struct {
gboolean can_set_rfmon; /* TRUE if can be put into monitor mode */
GList *data_link_types; /* GList of data_link_info_t's */
GList *timestamp_types; /* GList of timestamp_info_t's */
} if_capabilities_t;
/*
@ -110,6 +111,14 @@ typedef struct {
char *description; /* descriptive name from wiretap e.g. "Ethernet", NULL if unknown */
} data_link_info_t;
/*
* Information about timestamp types.
*/
typedef struct {
const char *name; /* e.g. "adapter_unsynced" */
const char *description; /* description from libpcap e.g. "Adapter, not synced with system time" */
} timestamp_info_t;
/**
* Fetch the linktype list for the specified interface from a child process.
*/

View File

@ -85,6 +85,7 @@ if( PCAP_FOUND )
check_function_exists( "bpf_image" HAVE_BPF_IMAGE )
check_function_exists( "pcap_setsampling" HAVE_PCAP_SETSAMPLING )
check_function_exists( "pcap_set_tstamp_precision" HAVE_PCAP_SET_TSTAMP_PRECISION )
check_function_exists( "pcap_set_tstamp_type" HAVE_PCAP_SET_TSTAMP_TYPE )
# Remote pcap checks
check_function_exists( "pcap_open" HAVE_PCAP_OPEN )
if( HAVE_PCAP_OPEN )

View File

@ -278,6 +278,9 @@
/* Define to 1 if you have the `pcap_set_tstamp_precision' function. */
#cmakedefine HAVE_PCAP_SET_TSTAMP_PRECISION 1
/* Define to 1 if you have the `pcap_set_tstamp_type' function. */
#cmakedefine HAVE_PCAP_SET_TSTAMP_TYPE 1
/* Define to 1 if you have the popcount function. */
#cmakedefine HAVE_POPCOUNT 1

View File

@ -32,6 +32,8 @@ S<[ B<-v> ]>
S<[ B<-w> E<lt>outfileE<gt> ]>
S<[ B<-y> E<lt>capture link typeE<gt> ]>
S<[ B<--capture-comment> E<lt>commentE<gt> ]>
S<[ B<--list-time-stamp-types> ]>
S<[ B<--time-stamp-type> E<lt>typeE<gt> ]>
=head1 DESCRIPTION
@ -254,7 +256,8 @@ link types can be used for the B<-y> option.
=item -M
When used with B<-D>, B<-L> or B<-S>, print machine-readable output.
When used with B<-D>, B<-L>, B<-S> or B<--list-time-stamp-types> print
machine-readable output.
The machine-readable output is intended to be read by B<Wireshark> and
B<TShark>; its format is subject to change from release to release.
@ -352,6 +355,15 @@ This option is only available if we output the captured packets to a
single file in pcap-ng format. Only one capture comment may be set per
output file.
=item --list-time-stamp-types
List time stamp types supported for the interface. If no time stamp type can be
set, no time stamp types are listed.
=item --time-stamp-type E<lt>typeE<gt>
Change the interface's timestamp method.
=back
=head1 CAPTURE FILTER SYNTAX

View File

@ -54,6 +54,8 @@ S<[ B<-Y> E<lt>displaY filterE<gt> ]>
S<[ B<-M> E<lt>auto session resetE<gt> ]>
S<[ B<-z> E<lt>statisticsE<gt> ]>
S<[ B<--capture-comment> E<lt>commentE<gt> ]>
S<[ B<--list-time-stamp-types> ]>
S<[ B<--time-stamp-type> E<lt>typeE<gt> ]>
S<[ B<--color> ]>
S<[ B<--no-duplicate-keys> ]>
S<[ B<--export-objects> E<lt>protocolE<gt>,E<lt>destdirE<gt> ]>
@ -1622,6 +1624,15 @@ Add a capture comment to the output file.
This option is only available if a new output file in pcapng format is
created. Only one capture comment may be set per output file.
=item --list-time-stamp-types
List time stamp types supported for the interface. If no time stamp type can be
set, no time stamp types are listed.
=item --time-stamp-type E<lt>typeE<gt>
Change the interface's timestamp method.
=item --color
Enable coloring of packets according to standard Wireshark color filters. This

View File

@ -53,6 +53,8 @@ S<[ B<--enable-protocol> E<lt>proto_nameE<gt> ]>
S<[ B<--disable-protocol> E<lt>proto_nameE<gt> ]>
S<[ B<--enable-heuristic> E<lt>short_nameE<gt> ]>
S<[ B<--disable-heuristic> E<lt>short_nameE<gt> ]>
S<[ B<--list-time-stamp-types> ]>
S<[ B<--time-stamp-type> E<lt>typeE<gt> ]>
S<[ E<lt>infileE<gt> ]>
=head1 DESCRIPTION
@ -987,6 +989,15 @@ Enable dissection of heuristic protocol.
Disable dissection of heuristic protocol.
=item --list-time-stamp-types
List time stamp types supported for the interface. If no time stamp type can be
set, no time stamp types are listed.
=item --time-stamp-type E<lt>typeE<gt>
Change the interface's timestamp method.
=back
=head1 INTERFACE

View File

@ -41,6 +41,7 @@ since version 2.4.0:
* File load time in Status Bar is now disabled by default and can be enabled in
Preferences -> Appearance -> Layout -> Show file load time.
* Support for G.729 codec in the RTP Player (via the bcg729 library).
* Support for hardware-timestamping of packets
//=== Removed Dissectors

View File

@ -42,8 +42,10 @@ Capture interface:
-I capture in monitor mode, if available
-B <buffer size> size of kernel buffer (def: 2MB)
-y <link type> link layer type (def: first appropriate)
--time-stamp-type <type> timestamp method for interface
-D print list of interfaces and exit
-L print list of link-layer types of iface and exit
--list-time-stamp-types print list of timestamp types for iface and exit
Capture stop conditions:
-c <packet count> stop after n packets (def: infinite)
@ -185,8 +187,10 @@ Capture interface:
-I capture in monitor mode, if available
-B <buffer size> size of kernel buffer in MiB (def: 2MiB)
-y <link type> link layer type (def: first appropriate)
--time-stamp-type <type> timestamp method for interface
-D print list of interfaces and exit
-L print list of link-layer types of iface and exit
--list-time-stamp-types print list of timestamp types for iface and exit
-d print generated BPF code for capture filter
-k set channel on wifi interface <freq>,[<type>]
-S print statistics for each interface once per second

View File

@ -56,8 +56,10 @@ Capture interface:
-I capture in monitor mode, if available
-B <buffer size> size of kernel buffer (def: 2MB)
-y <link type> link layer type (def: first appropriate)
--time-stamp-type <type> timestamp method for interface
-D print list of interfaces and exit
-L print list of link-layer types of iface and exit
--list-time-stamp-types print list of timestamp types for iface and exit
Capture stop conditions:
-c <packet count> stop after n packets (def: infinite)
@ -273,6 +275,10 @@ updated automatically as packets arrive during a capture ( as specified by the
List the data link types supported by the interface and exit.
--list-time-stamp-types::
List timestamp types configurable for the iface and exit
-m <font>::
This option sets the name of the font used for most text displayed by Wireshark.
@ -420,10 +426,16 @@ This option sets the name of the file to be used to save captured packets.
-y <capture link type>::
If a capture is started from the command line with -k, set the data
link type to use while capturing packets. The values reported by -L
If a capture is started from the command line with `-k`, set the data
link type to use while capturing packets. The values reported by `-L`
are the values that can be used.
--time-stamp-type <type>::
If a capture is started from the command line with `-k`, set the data
link type to use while capturing packets. The values reported by
`--list-time-stamp-types` are the values that can be used.
-X <eXtension option>::
Specify an option to be passed to a TShark module. The eXtension option is in

View File

@ -493,8 +493,10 @@ print_usage(FILE *output)
fprintf(output, " -B <buffer size> size of kernel buffer in MiB (def: %dMiB)\n", DEFAULT_CAPTURE_BUFFER_SIZE);
#endif
fprintf(output, " -y <link type> link layer type (def: first appropriate)\n");
fprintf(output, " --time-stamp-type <type> timestamp method for interface\n");
fprintf(output, " -D print list of interfaces and exit\n");
fprintf(output, " -L 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");
#ifdef HAVE_BPF_IMAGE
fprintf(output, " -d print generated BPF code for capture filter\n");
#endif
@ -906,10 +908,9 @@ print_machine_readable_interfaces(GList *if_list)
* you MUST update capture_ifinfo.c:capture_get_if_capabilities() accordingly!
*/
static void
print_machine_readable_if_capabilities(if_capabilities_t *caps)
print_machine_readable_if_capabilities(if_capabilities_t *caps, int queries)
{
GList *lt_entry;
data_link_info_t *data_link_info;
GList *lt_entry, *ts_entry;
const gchar *desc_str;
if (capture_child) {
@ -917,19 +918,33 @@ print_machine_readable_if_capabilities(if_capabilities_t *caps)
pipe_write_block(2, SP_SUCCESS, NULL);
}
if (caps->can_set_rfmon)
printf("1\n");
else
printf("0\n");
for (lt_entry = caps->data_link_types; lt_entry != NULL;
lt_entry = g_list_next(lt_entry)) {
data_link_info = (data_link_info_t *)lt_entry->data;
if (data_link_info->description != NULL)
desc_str = data_link_info->description;
else
desc_str = "(not supported)";
printf("%d\t%s\t%s\n", data_link_info->dlt, data_link_info->name,
desc_str);
if (queries & CAPS_QUERY_LINK_TYPES) {
if (caps->can_set_rfmon)
printf("1\n");
else
printf("0\n");
for (lt_entry = caps->data_link_types; lt_entry != NULL;
lt_entry = g_list_next(lt_entry)) {
data_link_info_t *data_link_info = (data_link_info_t *)lt_entry->data;
if (data_link_info->description != NULL)
desc_str = data_link_info->description;
else
desc_str = "(not supported)";
printf("%d\t%s\t%s\n", data_link_info->dlt, data_link_info->name,
desc_str);
}
}
printf("\n");
if (queries & CAPS_QUERY_TIMESTAMP_TYPES) {
for (ts_entry = caps->timestamp_types; ts_entry != NULL;
ts_entry = g_list_next(ts_entry)) {
timestamp_info_t *timestamp = (timestamp_info_t *)ts_entry->data;
if (timestamp->description != NULL)
desc_str = timestamp->description;
else
desc_str = "(none)";
printf("%s\t%s\n", timestamp->name, desc_str);
}
}
}
@ -3888,7 +3903,7 @@ main(int argc, char *argv[])
struct pcap_stat stats;
GLogLevelFlags log_flags;
gboolean list_interfaces = FALSE;
gboolean list_link_layer_types = FALSE;
int caps_queries = 0;
#ifdef HAVE_BPF_IMAGE
gboolean print_bpf_code = FALSE;
#endif
@ -4241,6 +4256,7 @@ main(int argc, char *argv[])
case 'f': /* capture filter */
case 'g': /* enable group read access on file(s) */
case 'i': /* Use interface x */
case LONGOPT_SET_TSTAMP_TYPE: /* Set capture timestamp type */
case 'n': /* Use pcapng format */
case 'p': /* Don't capture in promiscuous mode */
case 'P': /* Use pcap format */
@ -4306,11 +4322,14 @@ main(int argc, char *argv[])
}
break;
case 'L': /* Print list of link-layer types and exit */
if (!list_link_layer_types) {
list_link_layer_types = TRUE;
if (!(caps_queries & CAPS_QUERY_LINK_TYPES)) {
caps_queries |= CAPS_QUERY_LINK_TYPES;
run_once_args++;
}
break;
case LONGOPT_LIST_TSTAMP_TYPES:
caps_queries |= CAPS_QUERY_TIMESTAMP_TYPES;
break;
#ifdef HAVE_BPF_IMAGE
case 'd': /* Print BPF code for capture filter and exit */
if (!print_bpf_code) {
@ -4387,9 +4406,9 @@ main(int argc, char *argv[])
if (run_once_args > 1) {
#ifdef HAVE_BPF_IMAGE
cmdarg_err("Only one of -D, -L, -d, -k, or -S may be supplied.");
cmdarg_err("Only one of -D, -L, -d, -k or -S may be supplied.");
#else
cmdarg_err("Only one of -D, -L, -k, or -S may be supplied.");
cmdarg_err("Only one of -D, -L, -k or -S may be supplied.");
#endif
exit_main(1);
} else if (run_once_args == 1) {
@ -4452,7 +4471,7 @@ main(int argc, char *argv[])
int err;
gchar *err_str;
if_list = capture_interface_list(&err, &err_str,NULL);
if_list = capture_interface_list(&err, &err_str, NULL);
if (if_list == NULL) {
if (err == 0) {
/*
@ -4512,13 +4531,14 @@ main(int argc, char *argv[])
exit_main(status);
}
if (list_link_layer_types) {
/* Get the list of link-layer types for the capture device. */
if (caps_queries) {
/* Get the list of link-layer and/or timestamp types for the capture device. */
if_capabilities_t *caps;
gchar *err_str;
guint ii;
for (ii = 0; ii < global_capture_opts.ifaces->len; ii++) {
int if_caps_queries = caps_queries;
interface_options interface_opts;
interface_opts = g_array_index(global_capture_opts.ifaces, interface_options, ii);
@ -4531,22 +4551,40 @@ main(int argc, char *argv[])
g_free(err_str);
exit_main(2);
}
if (caps->data_link_types == NULL) {
if ((if_caps_queries & CAPS_QUERY_LINK_TYPES) && caps->data_link_types == NULL) {
cmdarg_err("The capture device \"%s\" has no data link types.", interface_opts.name);
exit_main(2);
}
} /* No timestamp types is no big deal. So we will just ignore it */
if (interface_opts.monitor_mode)
if_caps_queries |= CAPS_MONITOR_MODE;
if (machine_readable) /* tab-separated values to stdout */
/* XXX: We need to change the format and adopt consumers */
print_machine_readable_if_capabilities(caps);
/* XXX: We need to change the format and adapt consumers */
print_machine_readable_if_capabilities(caps, if_caps_queries);
else
/* XXX: We might want to print also the interface name */
capture_opts_print_if_capabilities(caps, interface_opts.name,
interface_opts.monitor_mode);
capture_opts_print_if_capabilities(caps, interface_opts.name, if_caps_queries);
free_if_capabilities(caps);
}
exit_main(0);
}
#ifdef HAVE_PCAP_SET_TSTAMP_TYPE
for (j = 0; j < global_capture_opts.ifaces->len; j++) {
interface_options *interface_opts;
interface_opts = &g_array_index(global_capture_opts.ifaces, interface_options, j);
if (interface_opts->timestamp_type) {
interface_opts->timestamp_type_id = pcap_tstamp_type_name_to_val(interface_opts->timestamp_type);
if (interface_opts->timestamp_type_id < 0) {
cmdarg_err("Invalid argument to option: --time-stamp-type=%s", interface_opts->timestamp_type);
exit_main(1);
}
}
}
#endif
/* We're supposed to do a capture, or print the BPF code for a filter. */
/* Let the user know what interfaces were chosen. */

View File

@ -383,6 +383,7 @@ static gboolean cb_dlt(extcap_callback_info_t cb_info)
*/
caps = (if_capabilities_t *) g_malloc(sizeof * caps);
caps->can_set_rfmon = FALSE;
caps->timestamp_types = NULL;
while (dlts)
{

View File

@ -148,6 +148,7 @@
#define INVALID_CAPABILITY 2
#define INVALID_TAP 2
#define INVALID_DATA_LINK 2
#define INVALID_TIMESTAMP_TYPE 2
#define INVALID_CAPTURE 2
#define INIT_FAILED 2
@ -353,8 +354,10 @@ print_usage(FILE *output)
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, " --time-stamp-type <type> timestamp method for interface\n");
fprintf(output, " -D print list of interfaces and exit\n");
fprintf(output, " -L 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");
@ -686,7 +689,7 @@ main(int argc, char *argv[])
volatile gboolean success;
volatile int exit_status = EXIT_SUCCESS;
#ifdef HAVE_LIBPCAP
gboolean list_link_layer_types = FALSE;
int caps_queries = 0;
gboolean start_capture = FALSE;
GList *if_list;
gchar *err_str;
@ -1082,6 +1085,7 @@ main(int argc, char *argv[])
case 'f': /* capture filter */
case 'g': /* enable group read access on file(s) */
case 'i': /* Use interface x */
case LONGOPT_SET_TSTAMP_TYPE: /* Set capture timestamp type */
case 'p': /* Don't capture in promiscuous mode */
#ifdef HAVE_PCAP_REMOTE
case 'A': /* Authentication */
@ -1226,7 +1230,15 @@ main(int argc, char *argv[])
break;
case 'L': /* Print list of link-layer types and exit */
#ifdef HAVE_LIBPCAP
list_link_layer_types = TRUE;
caps_queries |= CAPS_QUERY_LINK_TYPES;
#else
capture_option_specified = TRUE;
arg_error = TRUE;
#endif
break;
case LONGOPT_LIST_TSTAMP_TYPES: /* List possible timestamp types */
#ifdef HAVE_LIBPCAP
caps_queries |= CAPS_QUERY_TIMESTAMP_TYPES;
#else
capture_option_specified = TRUE;
arg_error = TRUE;
@ -1601,12 +1613,13 @@ main(int argc, char *argv[])
}
#ifdef HAVE_LIBPCAP
if (list_link_layer_types) {
/* We're supposed to list the link-layer types for an interface;
if (caps_queries) {
/* We're supposed to list the link-layer/timestamp types for an interface;
did the user also specify a capture file to be read? */
if (cf_name) {
/* Yes - that's bogus. */
cmdarg_err("You can't specify -L and a capture file to be read.");
cmdarg_err("You can't specify %s and a capture file to be read.",
caps_queries & CAPS_QUERY_LINK_TYPES ? "-L" : "--list-time-stamp-types");
exit_status = INVALID_OPTION;
goto clean_exit;
}
@ -2079,7 +2092,7 @@ main(int argc, char *argv[])
}
/* if requested, list the link layer types and exit */
if (list_link_layer_types) {
if (caps_queries) {
guint i;
/* Get the list of link-layer types for the capture devices. */
@ -2087,6 +2100,7 @@ main(int argc, char *argv[])
interface_options interface_opts;
if_capabilities_t *caps;
char *auth_str = NULL;
int if_caps_queries = caps_queries;
interface_opts = g_array_index(global_capture_opts.ifaces, interface_options, i);
#ifdef HAVE_PCAP_REMOTE
@ -2102,12 +2116,19 @@ main(int argc, char *argv[])
exit_status = INVALID_CAPABILITY;
goto clean_exit;
}
if (caps->data_link_types == NULL) {
if ((if_caps_queries & CAPS_QUERY_LINK_TYPES) && caps->data_link_types == NULL) {
cmdarg_err("The capture device \"%s\" has no data link types.", interface_opts.name);
exit_status = INVALID_DATA_LINK;
goto clean_exit;
}
capture_opts_print_if_capabilities(caps, interface_opts.name, interface_opts.monitor_mode);
if ((if_caps_queries & CAPS_QUERY_TIMESTAMP_TYPES) && caps->timestamp_types == NULL) {
cmdarg_err("The capture device \"%s\" has no timestamp types.", interface_opts.name);
exit_status = INVALID_TIMESTAMP_TYPE;
goto clean_exit;
}
if (interface_opts.monitor_mode)
if_caps_queries |= CAPS_MONITOR_MODE;
capture_opts_print_if_capabilities(caps, interface_opts.name, if_caps_queries);
free_if_capabilities(caps);
}
exit_status = EXIT_SUCCESS;

View File

@ -109,8 +109,10 @@ commandline_print_usage(gboolean for_help_option) {
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, " --time-stamp-type <type> timestamp method for interface\n");
fprintf(output, " -D print list of interfaces and exit\n");
fprintf(output, " -L 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");
@ -352,6 +354,7 @@ void commandline_other_options(int argc, char *argv[], gboolean opt_reset)
{
int opt;
gboolean arg_error = FALSE;
const char *list_option_supplied = NULL;
#ifdef HAVE_LIBPCAP
int status;
#else
@ -405,6 +408,7 @@ void commandline_other_options(int argc, char *argv[], gboolean opt_reset)
#ifdef HAVE_LIBPCAP
global_commandline_info.start_capture = FALSE;
global_commandline_info.list_link_layer_types = FALSE;
global_commandline_info.list_timestamp_types = FALSE;
global_commandline_info.quit_after_cap = getenv("WIRESHARK_QUIT_AFTER_CAPTURE") ? TRUE : FALSE;
#endif
global_commandline_info.full_screen = FALSE;
@ -420,6 +424,7 @@ void commandline_other_options(int argc, char *argv[], gboolean opt_reset)
case 'H': /* Hide capture info dialog box */
case 'p': /* Don't capture in promiscuous mode */
case 'i': /* Use interface x */
case LONGOPT_SET_TSTAMP_TYPE: /* Set capture timestamp type */
#ifdef HAVE_PCAP_CREATE
case 'I': /* Capture in monitor mode, if available */
#endif
@ -469,6 +474,16 @@ void commandline_other_options(int argc, char *argv[], gboolean opt_reset)
case 'L': /* Print list of link-layer types and exit */
#ifdef HAVE_LIBPCAP
global_commandline_info.list_link_layer_types = TRUE;
list_option_supplied = "-L";
#else
capture_option_specified = TRUE;
arg_error = TRUE;
#endif
break;
case LONGOPT_LIST_TSTAMP_TYPES:
#ifdef HAVE_LIBPCAP
global_commandline_info.list_timestamp_types = TRUE;
list_option_supplied = "--list-time-stamp-types";
#else
capture_option_specified = TRUE;
arg_error = TRUE;
@ -631,18 +646,18 @@ void commandline_other_options(int argc, char *argv[], gboolean opt_reset)
}
#ifdef HAVE_LIBPCAP
if (global_commandline_info.start_capture && global_commandline_info.list_link_layer_types) {
if (global_commandline_info.start_capture && list_option_supplied) {
/* Specifying *both* is bogus. */
cmdarg_err("You can't specify both -L and a live capture.");
cmdarg_err("You can't specify both %s and a live capture.", list_option_supplied);
exit(1);
}
if (global_commandline_info.list_link_layer_types) {
if (list_option_supplied) {
/* We're supposed to list the link-layer types for an interface;
did the user also specify a capture file to be read? */
if (global_commandline_info.cf_name) {
/* Yes - that's bogus. */
cmdarg_err("You can't specify -L and a capture file to be read.");
cmdarg_err("You can't specify %s and a capture file to be read.", list_option_supplied);
exit(1);
}
/* No - did they specify a ring buffer option? */

View File

@ -37,6 +37,7 @@ typedef struct commandline_param_info
{
#ifdef HAVE_LIBPCAP
gboolean list_link_layer_types;
gboolean list_timestamp_types;
gboolean start_capture;
gboolean quit_after_cap;
#endif

View File

@ -1996,6 +1996,7 @@ main(int argc, char *argv[])
#endif
#endif
#endif
int caps_queries = 0;
gint pl_size = 280, tv_size = 95, bv_size = 75;
gchar *rc_file;
dfilter_t *rfcode = NULL;
@ -2294,8 +2295,13 @@ main(int argc, char *argv[])
fill_in_local_interfaces(main_window_update);
if (global_commandline_info.start_capture || global_commandline_info.list_link_layer_types) {
/* We're supposed to do a live capture or get a list of link-layer
if (global_commandline_info.list_link_layer_types)
caps_queries |= CAPS_QUERY_LINK_TYPES;
if (global_commandline_info.list_timestamp_types)
caps_queries |= CAPS_QUERY_TIMESTAMP_TYPES;
if (global_commandline_info.start_capture || caps_queries) {
/* We're supposed to do a live capture or get a list of link-layer/timestamp
types for a live capture device; if the user didn't specify an
interface to use, pick a default. */
ret = capture_opts_default_iface_if_necessary(&global_capture_opts,
@ -2305,13 +2311,13 @@ main(int argc, char *argv[])
}
}
if (global_commandline_info.list_link_layer_types) {
if (caps_queries) {
/* Get the list of link-layer types for the capture devices. */
if_capabilities_t *caps;
guint i;
interface_t device;
for (i = 0; i < global_capture_opts.all_ifaces->len; i++) {
int if_caps_queries = caps_queries;
device = g_array_index(global_capture_opts.all_ifaces, interface_t, i);
if (device.selected) {
gchar* auth_str = NULL;
@ -2342,10 +2348,10 @@ main(int argc, char *argv[])
create_console();
#endif /* _WIN32 */
#if defined(HAVE_PCAP_CREATE)
capture_opts_print_if_capabilities(caps, device.name, device.monitor_mode_supported);
#else
capture_opts_print_if_capabilities(caps, device.name, FALSE);
if (device.monitor_mode_supported)
if_caps_queries |= CAPS_MONITOR_MODE;
#endif
capture_opts_print_if_capabilities(caps, device.name, if_caps_queries);
#ifdef _WIN32
destroy_console();
#endif /* _WIN32 */

View File

@ -366,6 +366,7 @@ int main(int argc, char *qt_argv[])
GString *runtime_info_str = NULL;
QString dfilter, read_filter;
int caps_queries = 0;
/* Start time in microseconds*/
guint64 start_time = g_get_monotonic_time();
#ifdef DEBUG_STARTUP_TIME
@ -714,8 +715,13 @@ int main(int argc, char *qt_argv[])
fill_in_local_interfaces(main_window_update);
if (global_commandline_info.start_capture || global_commandline_info.list_link_layer_types) {
/* We're supposed to do a live capture or get a list of link-layer
if (global_commandline_info.list_link_layer_types)
caps_queries |= CAPS_QUERY_LINK_TYPES;
if (global_commandline_info.list_timestamp_types)
caps_queries |= CAPS_QUERY_TIMESTAMP_TYPES;
if (global_commandline_info.start_capture || caps_queries) {
/* We're supposed to do a live capture or get a list of link-layer/timestamp
types for a live capture device; if the user didn't specify an
interface to use, pick a default. */
ret_val = capture_opts_default_iface_if_necessary(&global_capture_opts,
@ -725,13 +731,13 @@ int main(int argc, char *qt_argv[])
}
}
if (global_commandline_info.list_link_layer_types) {
if (caps_queries) {
/* Get the list of link-layer types for the capture devices. */
if_capabilities_t *caps;
guint i;
interface_t device;
for (i = 0; i < global_capture_opts.all_ifaces->len; i++) {
int if_caps_queries = caps_queries;
device = g_array_index(global_capture_opts.all_ifaces, interface_t, i);
if (device.selected) {
#if defined(HAVE_PCAP_CREATE)
@ -754,10 +760,10 @@ int main(int argc, char *qt_argv[])
create_console();
#endif /* _WIN32 */
#if defined(HAVE_PCAP_CREATE)
capture_opts_print_if_capabilities(caps, device.name, device.monitor_mode_supported);
#else
capture_opts_print_if_capabilities(caps, device.name, FALSE);
if (device.monitor_mode_supported)
if_caps_queries |= CAPS_MONITOR_MODE;
#endif
capture_opts_print_if_capabilities(caps, device.name, if_caps_queries);
#ifdef _WIN32
destroy_console();
#endif /* _WIN32 */