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-exportobject.c
ui/cli/tap-endpoints.c
ui/cli/tap-flow.c
ui/cli/tap-follow.c
ui/cli/tap-funnel.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
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>]
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,
network info types and some Message Analyzer exported types.
* Personal plugins folder on Linux/Unix is now ~/.local/lib/wireshark/plugins.
* Add Flow Graph functionality to TShark using -z
//=== Removed Dissectors

View File

@ -32,7 +32,6 @@
#include "column-info.h"
#include "tap.h"
#include "wmem/wmem.h"
#include "wsutil/file_util.h"
#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);
g_queue_free(sainfo->items);
g_hash_table_destroy(sainfo->ht);
if (sainfo->ht != NULL)
g_hash_table_destroy(sainfo->ht);
g_free(sainfo);
}
@ -241,7 +241,8 @@ sequence_analysis_list_free(seq_analysis_info_t *sainfo)
/* free the graph data items */
#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();
#else
{
@ -399,8 +400,8 @@ static void overwrite (GString *gstr, char *text_to_insert, guint32 p1, guint32
}
gboolean
sequence_analysis_dump_to_file(const char *pathname, seq_analysis_info_t *sainfo, unsigned int first_node)
void
sequence_analysis_dump_to_file(FILE *of, seq_analysis_info_t *sainfo, unsigned int first_node)
{
guint32 i, display_items, display_nodes;
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;
const char *empty_header;
char src_port[8], dst_port[8];
GList *list;
GList *list = NULL;
char *addr_str;
FILE *of;
of = ws_fopen(pathname, "w");
if (of==NULL) {
return FALSE;
}
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)
{
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 (display_items == 0) {
fclose (of);
return TRUE;
return;
}
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(tmp_str, TRUE);
g_string_free(tmp_str2, TRUE);
fclose (of);
return TRUE;
}
/*

View File

@ -38,6 +38,7 @@
#include "packet_info.h"
#include "tap.h"
#include "address.h"
#include "wsutil/file_util.h"
#ifdef __cplusplus
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.
*
* @param pathname Pathname of the file to write.
* @param of File to write.
* @param sainfo Sequence analysis information.
* @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
}

View File

@ -50,6 +50,7 @@ TSHARK_TAP_SRC = \
tap-endpoints.c \
tap-expert.c \
tap-exportobject.c \
tap-flow.c \
tap-follow.c \
tap-funnel.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)
{
char *pathname;
FILE *outfile;
/*
* 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. */
break;
}
if (sequence_analysis_dump_to_file(pathname, user_data->graph_info, user_data->dlg.first_node)) {
/* We succeeded. */
outfile = ws_fopen(pathname, "w");
if (outfile != NULL) {
sequence_analysis_dump_to_file(outfile, user_data->graph_info, user_data->dlg.first_node);
fclose (outfile);
g_free(pathname);
break;
} else {

View File

@ -27,6 +27,7 @@
#include "file.h"
#include "wsutil/nstime.h"
#include "wsutil/utf8_entities.h"
#include "wsutil/file_util.h"
#include <ui/qt/utils/color_utils.h>
#include "progress_frame.h"
@ -400,7 +401,13 @@ void SequenceDialog::on_buttonBox_accepted()
} else if (extension.compare(jpeg_filter) == 0) {
save_ok = ui->sequencePlot->saveJpg(file_name);
} 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?
if (save_ok) {