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:
Michael Mann 2017-09-21 23:20:03 -04:00 committed by Anders Broman
parent 620d54b1e3
commit 5f667694d3
9 changed files with 209 additions and 25 deletions

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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;
} }
/* /*

View File

@ -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
} }

View File

@ -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 \

159
ui/cli/tap-flow.c Normal file
View File

@ -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:
*/

View File

@ -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 {

View File

@ -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) {