aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--CMakeLists.txt1
-rw-r--r--doc/tshark.pod20
-rw-r--r--docbook/release-notes.asciidoc1
-rw-r--r--epan/sequence_analysis.c30
-rw-r--r--epan/sequence_analysis.h6
-rw-r--r--ui/cli/Makefile.am1
-rw-r--r--ui/cli/tap-flow.c159
-rw-r--r--ui/gtk/graph_analysis.c7
-rw-r--r--ui/qt/sequence_dialog.cpp9
9 files changed, 209 insertions, 25 deletions
diff --git a/CMakeLists.txt b/CMakeLists.txt
index 5cac0b9129..d06049c5a2 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -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
diff --git a/doc/tshark.pod b/doc/tshark.pod
index 185409468d..67c538544e 100644
--- a/doc/tshark.pod
+++ b/doc/tshark.pod
@@ -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
diff --git a/docbook/release-notes.asciidoc b/docbook/release-notes.asciidoc
index cbf707eafd..8325aec179 100644
--- a/docbook/release-notes.asciidoc
+++ b/docbook/release-notes.asciidoc
@@ -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
diff --git a/epan/sequence_analysis.c b/epan/sequence_analysis.c
index ed52782ba0..7978637427 100644
--- a/epan/sequence_analysis.c
+++ b/epan/sequence_analysis.c
@@ -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;
-
}
/*
diff --git a/epan/sequence_analysis.h b/epan/sequence_analysis.h
index 68af7f5c68..64b0a31be3 100644
--- a/epan/sequence_analysis.h
+++ b/epan/sequence_analysis.h
@@ -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
}
diff --git a/ui/cli/Makefile.am b/ui/cli/Makefile.am
index 472be96ebe..d357a76c4d 100644
--- a/ui/cli/Makefile.am
+++ b/ui/cli/Makefile.am
@@ -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 \
diff --git a/ui/cli/tap-flow.c b/ui/cli/tap-flow.c
new file mode 100644
index 0000000000..8915df15af
--- /dev/null
+++ b/ui/cli/tap-flow.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:
+ */
diff --git a/ui/gtk/graph_analysis.c b/ui/gtk/graph_analysis.c
index a5f7d2cabb..407eb3c1ab 100644
--- a/ui/gtk/graph_analysis.c
+++ b/ui/gtk/graph_analysis.c
@@ -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 {
diff --git a/ui/qt/sequence_dialog.cpp b/ui/qt/sequence_dialog.cpp
index 9af0232787..4842c0ed93 100644
--- a/ui/qt/sequence_dialog.cpp
+++ b/ui/qt/sequence_dialog.cpp
@@ -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) {