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,I,[I] + +Displays the flow of data between two nodes. Output is the same as ASCII format +saved from GUI. + +I specifies the flow name. It can be one of: + + any All frames + icmp ICMP + icmpv6 ICMPv6 + lbm_uim UIM + tcp TCP + +I 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,I,I[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 + * 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 +#include + +#include +#include +#include + +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 #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) {