Add Flow Graph functionality to TShark
Add flow graph functionality to tshark through -z option. Output is same as ASCII format saved from GUI. Change-Id: Iee0bfea7215858e6488b4728581be28287e9ea1a Reviewed-on: https://code.wireshark.org/review/23652 Petri-Dish: Michael Mann <mmann78@netscape.net> Tested-by: Petri Dish Buildbot <buildbot-no-reply@wireshark.org> Reviewed-by: Anders Broman <a.broman58@gmail.com>
This commit is contained in:
parent
620d54b1e3
commit
5f667694d3
|
@ -1621,6 +1621,7 @@ set(TSHARK_TAP_SRC
|
||||||
ui/cli/tap-expert.c
|
ui/cli/tap-expert.c
|
||||||
ui/cli/tap-exportobject.c
|
ui/cli/tap-exportobject.c
|
||||||
ui/cli/tap-endpoints.c
|
ui/cli/tap-endpoints.c
|
||||||
|
ui/cli/tap-flow.c
|
||||||
ui/cli/tap-follow.c
|
ui/cli/tap-follow.c
|
||||||
ui/cli/tap-funnel.c
|
ui/cli/tap-funnel.c
|
||||||
ui/cli/tap-gsm_astat.c
|
ui/cli/tap-gsm_astat.c
|
||||||
|
|
|
@ -1109,6 +1109,26 @@ on those calls that match that filter.
|
||||||
Example: B<-z "expert,note,tcp"> will only collect expert items for frames that
|
Example: B<-z "expert,note,tcp"> will only collect expert items for frames that
|
||||||
include the tcp protocol, with a severity of note or higher.
|
include the tcp protocol, with a severity of note or higher.
|
||||||
|
|
||||||
|
=item B<-z> flow,I<name>,I<mode>,[I<filter>]
|
||||||
|
|
||||||
|
Displays the flow of data between two nodes. Output is the same as ASCII format
|
||||||
|
saved from GUI.
|
||||||
|
|
||||||
|
I<name> specifies the flow name. It can be one of:
|
||||||
|
|
||||||
|
any All frames
|
||||||
|
icmp ICMP
|
||||||
|
icmpv6 ICMPv6
|
||||||
|
lbm_uim UIM
|
||||||
|
tcp TCP
|
||||||
|
|
||||||
|
I<mode> specifies the address type. It can be one of:
|
||||||
|
|
||||||
|
standard Any address
|
||||||
|
network Network address
|
||||||
|
|
||||||
|
Example: B<-z flow,tcp,network> will show data flow for all TCP frames
|
||||||
|
|
||||||
=item B<-z> follow,I<prot>,I<mode>,I<filter>[I<,range>]
|
=item B<-z> follow,I<prot>,I<mode>,I<filter>[I<,range>]
|
||||||
|
|
||||||
Displays the contents of a TCP or UDP stream between two nodes. The data
|
Displays the contents of a TCP or UDP stream between two nodes. The data
|
||||||
|
|
|
@ -50,6 +50,7 @@ since version 2.4.0:
|
||||||
* Improved NetMon .cap support with comments, event tracing, network filter,
|
* Improved NetMon .cap support with comments, event tracing, network filter,
|
||||||
network info types and some Message Analyzer exported types.
|
network info types and some Message Analyzer exported types.
|
||||||
* Personal plugins folder on Linux/Unix is now ~/.local/lib/wireshark/plugins.
|
* Personal plugins folder on Linux/Unix is now ~/.local/lib/wireshark/plugins.
|
||||||
|
* Add Flow Graph functionality to TShark using -z
|
||||||
|
|
||||||
//=== Removed Dissectors
|
//=== Removed Dissectors
|
||||||
|
|
||||||
|
|
|
@ -32,7 +32,6 @@
|
||||||
#include "column-info.h"
|
#include "column-info.h"
|
||||||
#include "tap.h"
|
#include "tap.h"
|
||||||
#include "wmem/wmem.h"
|
#include "wmem/wmem.h"
|
||||||
#include "wsutil/file_util.h"
|
|
||||||
|
|
||||||
#define NODE_OVERFLOW MAX_NUM_NODES+1
|
#define NODE_OVERFLOW MAX_NUM_NODES+1
|
||||||
|
|
||||||
|
@ -191,7 +190,8 @@ void sequence_analysis_info_free(seq_analysis_info_t *sainfo)
|
||||||
sequence_analysis_list_free(sainfo);
|
sequence_analysis_list_free(sainfo);
|
||||||
|
|
||||||
g_queue_free(sainfo->items);
|
g_queue_free(sainfo->items);
|
||||||
g_hash_table_destroy(sainfo->ht);
|
if (sainfo->ht != NULL)
|
||||||
|
g_hash_table_destroy(sainfo->ht);
|
||||||
|
|
||||||
g_free(sainfo);
|
g_free(sainfo);
|
||||||
}
|
}
|
||||||
|
@ -241,7 +241,8 @@ sequence_analysis_list_free(seq_analysis_info_t *sainfo)
|
||||||
/* free the graph data items */
|
/* free the graph data items */
|
||||||
|
|
||||||
#if GLIB_CHECK_VERSION (2, 32, 0)
|
#if GLIB_CHECK_VERSION (2, 32, 0)
|
||||||
g_queue_free_full(sainfo->items, sequence_analysis_item_free);
|
if (sainfo->items != NULL)
|
||||||
|
g_queue_free_full(sainfo->items, sequence_analysis_item_free);
|
||||||
sainfo->items = g_queue_new();
|
sainfo->items = g_queue_new();
|
||||||
#else
|
#else
|
||||||
{
|
{
|
||||||
|
@ -399,8 +400,8 @@ static void overwrite (GString *gstr, char *text_to_insert, guint32 p1, guint32
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
gboolean
|
void
|
||||||
sequence_analysis_dump_to_file(const char *pathname, seq_analysis_info_t *sainfo, unsigned int first_node)
|
sequence_analysis_dump_to_file(FILE *of, seq_analysis_info_t *sainfo, unsigned int first_node)
|
||||||
{
|
{
|
||||||
guint32 i, display_items, display_nodes;
|
guint32 i, display_items, display_nodes;
|
||||||
guint32 start_position, end_position, item_width, header_length;
|
guint32 start_position, end_position, item_width, header_length;
|
||||||
|
@ -412,18 +413,13 @@ sequence_analysis_dump_to_file(const char *pathname, seq_analysis_info_t *sainfo
|
||||||
GString *label_string, *empty_line, *separator_line, *tmp_str, *tmp_str2;
|
GString *label_string, *empty_line, *separator_line, *tmp_str, *tmp_str2;
|
||||||
const char *empty_header;
|
const char *empty_header;
|
||||||
char src_port[8], dst_port[8];
|
char src_port[8], dst_port[8];
|
||||||
GList *list;
|
GList *list = NULL;
|
||||||
char *addr_str;
|
char *addr_str;
|
||||||
|
|
||||||
FILE *of;
|
|
||||||
|
|
||||||
of = ws_fopen(pathname, "w");
|
|
||||||
if (of==NULL) {
|
|
||||||
return FALSE;
|
|
||||||
}
|
|
||||||
|
|
||||||
display_items = 0;
|
display_items = 0;
|
||||||
list = g_queue_peek_nth_link(sainfo->items, 0);
|
if (sainfo->items != NULL)
|
||||||
|
list = g_queue_peek_nth_link(sainfo->items, 0);
|
||||||
|
|
||||||
while (list)
|
while (list)
|
||||||
{
|
{
|
||||||
sai = (seq_analysis_item_t *)list->data;
|
sai = (seq_analysis_item_t *)list->data;
|
||||||
|
@ -444,8 +440,7 @@ sequence_analysis_dump_to_file(const char *pathname, seq_analysis_info_t *sainfo
|
||||||
|
|
||||||
/* if not items to display */
|
/* if not items to display */
|
||||||
if (display_items == 0) {
|
if (display_items == 0) {
|
||||||
fclose (of);
|
return;
|
||||||
return TRUE;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
label_string = g_string_new("");
|
label_string = g_string_new("");
|
||||||
|
@ -610,9 +605,6 @@ sequence_analysis_dump_to_file(const char *pathname, seq_analysis_info_t *sainfo
|
||||||
g_string_free(separator_line, TRUE);
|
g_string_free(separator_line, TRUE);
|
||||||
g_string_free(tmp_str, TRUE);
|
g_string_free(tmp_str, TRUE);
|
||||||
g_string_free(tmp_str2, TRUE);
|
g_string_free(tmp_str2, TRUE);
|
||||||
fclose (of);
|
|
||||||
return TRUE;
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
|
|
@ -38,6 +38,7 @@
|
||||||
#include "packet_info.h"
|
#include "packet_info.h"
|
||||||
#include "tap.h"
|
#include "tap.h"
|
||||||
#include "address.h"
|
#include "address.h"
|
||||||
|
#include "wsutil/file_util.h"
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
extern "C" {
|
extern "C" {
|
||||||
|
@ -202,12 +203,11 @@ WS_DLL_PUBLIC void sequence_analysis_free_nodes(seq_analysis_info_t *sainfo);
|
||||||
|
|
||||||
/** Write an ASCII version of the sequence diagram to a file.
|
/** Write an ASCII version of the sequence diagram to a file.
|
||||||
*
|
*
|
||||||
* @param pathname Pathname of the file to write.
|
* @param of File to write.
|
||||||
* @param sainfo Sequence analysis information.
|
* @param sainfo Sequence analysis information.
|
||||||
* @param first_node Start drawing at this node.
|
* @param first_node Start drawing at this node.
|
||||||
* @return TRUE on success, FALSE on failure.
|
|
||||||
*/
|
*/
|
||||||
WS_DLL_PUBLIC gboolean sequence_analysis_dump_to_file(const char *pathname, seq_analysis_info_t *sainfo, unsigned int first_node);
|
WS_DLL_PUBLIC void sequence_analysis_dump_to_file(FILE *of, seq_analysis_info_t *sainfo, unsigned int first_node);
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
}
|
}
|
||||||
|
|
|
@ -50,6 +50,7 @@ TSHARK_TAP_SRC = \
|
||||||
tap-endpoints.c \
|
tap-endpoints.c \
|
||||||
tap-expert.c \
|
tap-expert.c \
|
||||||
tap-exportobject.c \
|
tap-exportobject.c \
|
||||||
|
tap-flow.c \
|
||||||
tap-follow.c \
|
tap-follow.c \
|
||||||
tap-funnel.c \
|
tap-funnel.c \
|
||||||
tap-gsm_astat.c \
|
tap-gsm_astat.c \
|
||||||
|
|
|
@ -0,0 +1,159 @@
|
||||||
|
/* tap-flow.c
|
||||||
|
*
|
||||||
|
* Wireshark - Network traffic analyzer
|
||||||
|
* By Gerald Combs <gerald@wireshark.org>
|
||||||
|
* Copyright 1998 Gerald Combs
|
||||||
|
*
|
||||||
|
* This program is free software; you can redistribute it and/or
|
||||||
|
* modify it under the terms of the GNU General Public License
|
||||||
|
* as published by the Free Software Foundation; either version 2
|
||||||
|
* of the License, or (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/* This module provides udp and tcp follow stream capabilities to tshark.
|
||||||
|
* It is only used by tshark and not wireshark.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "config.h"
|
||||||
|
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
|
||||||
|
#include <epan/sequence_analysis.h>
|
||||||
|
#include <epan/stat_tap_ui.h>
|
||||||
|
#include <epan/tap.h>
|
||||||
|
|
||||||
|
void register_tap_listener_follow(void);
|
||||||
|
|
||||||
|
#define STR_FLOW "flow,"
|
||||||
|
#define STR_STANDARD ",standard"
|
||||||
|
#define STR_NETWORK ",network"
|
||||||
|
|
||||||
|
WS_NORETURN static void flow_exit(const char *strp)
|
||||||
|
{
|
||||||
|
fprintf(stderr, "tshark: flow - %s\n", strp);
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
flow_draw(void *arg)
|
||||||
|
{
|
||||||
|
seq_analysis_info_t* flow_info = (seq_analysis_info_t*)arg;
|
||||||
|
|
||||||
|
sequence_analysis_get_nodes(flow_info);
|
||||||
|
|
||||||
|
sequence_analysis_dump_to_file(stdout, flow_info, 0);
|
||||||
|
|
||||||
|
//clean up the data
|
||||||
|
sequence_analysis_list_free(flow_info);
|
||||||
|
sequence_analysis_info_free(flow_info);
|
||||||
|
}
|
||||||
|
|
||||||
|
static gboolean flow_arg_strncmp(const char **opt_argp, const char *strp)
|
||||||
|
{
|
||||||
|
size_t len = strlen(strp);
|
||||||
|
|
||||||
|
if (strncmp(*opt_argp, strp, len) == 0)
|
||||||
|
{
|
||||||
|
*opt_argp += len;
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
flow_arg_mode(const char **opt_argp, seq_analysis_info_t *flow_info)
|
||||||
|
{
|
||||||
|
if (flow_arg_strncmp(opt_argp, STR_STANDARD))
|
||||||
|
{
|
||||||
|
flow_info->any_addr = 1;
|
||||||
|
}
|
||||||
|
else if (flow_arg_strncmp(opt_argp, STR_NETWORK))
|
||||||
|
{
|
||||||
|
flow_info->any_addr = 0;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
flow_exit("Invalid address type.");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
flow_init(const char *opt_argp, void *userdata)
|
||||||
|
{
|
||||||
|
seq_analysis_info_t *flow_info = g_new0(seq_analysis_info_t, 1);
|
||||||
|
GString *errp;
|
||||||
|
register_analysis_t* analysis = (register_analysis_t*)userdata;
|
||||||
|
const char *filter=NULL;
|
||||||
|
|
||||||
|
opt_argp += strlen(STR_FLOW);
|
||||||
|
opt_argp += strlen(sequence_analysis_get_name(analysis));
|
||||||
|
|
||||||
|
flow_arg_mode(&opt_argp, flow_info);
|
||||||
|
if (*opt_argp == ',') {
|
||||||
|
filter = opt_argp + 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
flow_info->all_packets = TRUE;
|
||||||
|
|
||||||
|
sequence_analysis_list_free(flow_info);
|
||||||
|
|
||||||
|
errp = register_tap_listener(sequence_analysis_get_tap_listener_name(analysis), flow_info, filter, sequence_analysis_get_tap_flags(analysis),
|
||||||
|
NULL, sequence_analysis_get_packet_func(analysis), flow_draw);
|
||||||
|
|
||||||
|
if (errp != NULL)
|
||||||
|
{
|
||||||
|
sequence_analysis_list_free(flow_info);
|
||||||
|
sequence_analysis_info_free(flow_info);
|
||||||
|
g_string_free(errp, TRUE);
|
||||||
|
flow_exit("Error registering tap listener.");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static gboolean
|
||||||
|
flow_register(const void *key _U_, void *value, void *userdata _U_)
|
||||||
|
{
|
||||||
|
register_analysis_t* analysis = (register_analysis_t*)value;
|
||||||
|
stat_tap_ui flow_ui;
|
||||||
|
GString *cmd_str = g_string_new(STR_FLOW);
|
||||||
|
|
||||||
|
g_string_append(cmd_str, sequence_analysis_get_name(analysis));
|
||||||
|
|
||||||
|
flow_ui.group = REGISTER_STAT_GROUP_GENERIC;
|
||||||
|
flow_ui.title = NULL; /* construct this from the protocol info? */
|
||||||
|
flow_ui.cli_string = g_string_free(cmd_str, FALSE);
|
||||||
|
flow_ui.tap_init_cb = flow_init;
|
||||||
|
flow_ui.nparams = 0;
|
||||||
|
flow_ui.params = NULL;
|
||||||
|
register_stat_tap_ui(&flow_ui, analysis);
|
||||||
|
g_free((char*)flow_ui.cli_string);
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
register_tap_listener_flow(void)
|
||||||
|
{
|
||||||
|
sequence_analysis_table_iterate_tables(flow_register, NULL);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Editor modelines - http://www.wireshark.org/tools/modelines.html
|
||||||
|
*
|
||||||
|
* Local Variables:
|
||||||
|
* c-basic-offset: 4
|
||||||
|
* tab-width: 8
|
||||||
|
* indent-tabs-mode: nil
|
||||||
|
* End:
|
||||||
|
*
|
||||||
|
* ex: set shiftwidth=2 tabstop=8 expandtab:
|
||||||
|
* :indentSize=2:tabSize=8:noTabs=true:
|
||||||
|
*/
|
|
@ -255,6 +255,7 @@ on_save_bt_clicked (GtkWidget *button _U_,
|
||||||
graph_analysis_data_t *user_data)
|
graph_analysis_data_t *user_data)
|
||||||
{
|
{
|
||||||
char *pathname;
|
char *pathname;
|
||||||
|
FILE *outfile;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Loop until the user either selects a file or gives up.
|
* Loop until the user either selects a file or gives up.
|
||||||
|
@ -265,8 +266,10 @@ on_save_bt_clicked (GtkWidget *button _U_,
|
||||||
/* User gave up. */
|
/* User gave up. */
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
if (sequence_analysis_dump_to_file(pathname, user_data->graph_info, user_data->dlg.first_node)) {
|
outfile = ws_fopen(pathname, "w");
|
||||||
/* We succeeded. */
|
if (outfile != NULL) {
|
||||||
|
sequence_analysis_dump_to_file(outfile, user_data->graph_info, user_data->dlg.first_node);
|
||||||
|
fclose (outfile);
|
||||||
g_free(pathname);
|
g_free(pathname);
|
||||||
break;
|
break;
|
||||||
} else {
|
} else {
|
||||||
|
|
|
@ -27,6 +27,7 @@
|
||||||
#include "file.h"
|
#include "file.h"
|
||||||
#include "wsutil/nstime.h"
|
#include "wsutil/nstime.h"
|
||||||
#include "wsutil/utf8_entities.h"
|
#include "wsutil/utf8_entities.h"
|
||||||
|
#include "wsutil/file_util.h"
|
||||||
|
|
||||||
#include <ui/qt/utils/color_utils.h>
|
#include <ui/qt/utils/color_utils.h>
|
||||||
#include "progress_frame.h"
|
#include "progress_frame.h"
|
||||||
|
@ -400,7 +401,13 @@ void SequenceDialog::on_buttonBox_accepted()
|
||||||
} else if (extension.compare(jpeg_filter) == 0) {
|
} else if (extension.compare(jpeg_filter) == 0) {
|
||||||
save_ok = ui->sequencePlot->saveJpg(file_name);
|
save_ok = ui->sequencePlot->saveJpg(file_name);
|
||||||
} else if (extension.compare(ascii_filter) == 0 && !file_closed_ && info_->sainfo()) {
|
} else if (extension.compare(ascii_filter) == 0 && !file_closed_ && info_->sainfo()) {
|
||||||
save_ok = sequence_analysis_dump_to_file(file_name.toUtf8().constData(), info_->sainfo(), 0);
|
FILE *outfile = ws_fopen(file_name.toUtf8().constData(), "w");
|
||||||
|
if (outfile != NULL) {
|
||||||
|
sequence_analysis_dump_to_file(outfile, info_->sainfo(), 0);
|
||||||
|
save_ok = true;
|
||||||
|
} else {
|
||||||
|
save_ok = false;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
// else error dialog?
|
// else error dialog?
|
||||||
if (save_ok) {
|
if (save_ok) {
|
||||||
|
|
Loading…
Reference in New Issue