From c41bab1f667cfe51b09b80869497a2db68abecce Mon Sep 17 00:00:00 2001 From: Jakub Zawadzki Date: Sat, 16 Sep 2017 16:52:23 +0200 Subject: Move most of sequence analysis code from ui/ to epan/ Create registration system to allow creation of analysis items to be localized to the dissector. For now only frame (all) and TCP are supported. VOIP functionality will be covered in a separate patch. Change-Id: I5b05ef6d5afff8d0b162b03a0f451ab810602e81 Reviewed-on: https://code.wireshark.org/review/23571 Reviewed-by: Michael Mann --- epan/sequence_analysis.c | 275 +++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 275 insertions(+) create mode 100644 epan/sequence_analysis.c (limited to 'epan/sequence_analysis.c') diff --git a/epan/sequence_analysis.c b/epan/sequence_analysis.c new file mode 100644 index 0000000000..7d8f03064f --- /dev/null +++ b/epan/sequence_analysis.c @@ -0,0 +1,275 @@ +/* sequence-analysis.c + * Flow sequence analysis + * + * Some code from from gtk/flow_graph.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. + */ + +#include "config.h" + +#include "sequence_analysis.h" + +#include "addr_resolv.h" +#include "proto.h" +#include "tap.h" +#include "wmem/wmem.h" + +#define NODE_OVERFLOW MAX_NUM_NODES+1 + +struct register_analysis { + const char* name; /* Name (used for lookup) */ + const char* ui_name; /* Name used for UI */ + int proto_id; /* protocol id (0-indexed) */ + const char* tap_listen_str; /* string used in register_tap_listener (NULL to use protocol name) */ + guint tap_flags; + tap_packet_cb analysis_func; /* function to be called for new incoming packets for sequence analysis */ +}; + +static wmem_tree_t *registered_seq_analysis = NULL; + +void +register_seq_analysis(const char* name, const char* ui_name, const int proto_id, const char* tap_listener, guint tap_flags, tap_packet_cb tap_func) +{ + register_analysis_t* analysis; + + DISSECTOR_ASSERT(tap_func); + + analysis = wmem_new0(wmem_epan_scope(), register_analysis_t); + + analysis->name = name; + analysis->ui_name = ui_name; + analysis->proto_id = proto_id; + if (tap_listener != NULL) + analysis->tap_listen_str = tap_listener; + else + analysis->tap_listen_str = proto_get_protocol_filter_name(proto_id); + analysis->tap_flags = tap_flags; + analysis->analysis_func = tap_func; + + if (registered_seq_analysis == NULL) + registered_seq_analysis = wmem_tree_new(wmem_epan_scope()); + + wmem_tree_insert_string(registered_seq_analysis, name, analysis, 0); +} + +const char* sequence_analysis_get_name(register_analysis_t* analysis) +{ + return analysis->name; +} + +const char* sequence_analysis_get_ui_name(register_analysis_t* analysis) +{ + return analysis->ui_name; +} + +const char* sequence_analysis_get_tap_listener_name(register_analysis_t* analysis) +{ + return analysis->tap_listen_str; +} + +tap_packet_cb sequence_analysis_get_packet_func(register_analysis_t* analysis) +{ + return analysis->analysis_func; +} + +guint sequence_analysis_get_tap_flags(register_analysis_t* analysis) +{ + return analysis->tap_flags; +} + + +register_analysis_t* sequence_analysis_find_by_name(const char* name) +{ + return (register_analysis_t*)wmem_tree_lookup_string(registered_seq_analysis, name, 0); +} + +void sequence_analysis_table_iterate_tables(wmem_foreach_func func, gpointer user_data) +{ + wmem_tree_foreach(registered_seq_analysis, func, user_data); +} + +seq_analysis_info_t * +sequence_analysis_info_new(void) +{ + seq_analysis_info_t *sainfo = g_new0(seq_analysis_info_t, 1); + + /* SEQ_ANALYSIS_DEBUG("adding new item"); */ + sainfo->items = g_queue_new(); + sainfo->ht= g_hash_table_new(g_int_hash, g_int_equal); + return sainfo; +} + +void sequence_analysis_info_free(seq_analysis_info_t *sainfo) +{ + if (!sainfo) return; + + /* SEQ_ANALYSIS_DEBUG("%d items", g_queue_get_length(sainfo->items)); */ + sequence_analysis_list_free(sainfo); + + g_queue_free(sainfo->items); + g_hash_table_destroy(sainfo->ht); + + g_free(sainfo); +} + +static void sequence_analysis_item_free(gpointer data) +{ + seq_analysis_item_t *seq_item = (seq_analysis_item_t *)data; + g_free(seq_item->frame_label); + g_free(seq_item->time_str); + g_free(seq_item->comment); + g_free(seq_item->protocol); + free_address(&seq_item->src_addr); + free_address(&seq_item->dst_addr); + g_free(data); +} + + +/* compare two list entries by packet no */ +static gint +sequence_analysis_sort_compare(gconstpointer a, gconstpointer b, gpointer user_data _U_) +{ + const seq_analysis_item_t *entry_a = (const seq_analysis_item_t *)a; + const seq_analysis_item_t *entry_b = (const seq_analysis_item_t *)b; + + if(entry_a->frame_number < entry_b->frame_number) + return -1; + + if(entry_a->frame_number > entry_b->frame_number) + return 1; + + return 0; +} + + +void +sequence_analysis_list_sort(seq_analysis_info_t *sainfo) +{ + if (!sainfo) return; + g_queue_sort(sainfo->items, sequence_analysis_sort_compare, NULL); +} + +void +sequence_analysis_list_free(seq_analysis_info_t *sainfo) +{ + if (!sainfo) return; + /* SEQ_ANALYSIS_DEBUG("%d items", g_queue_get_length(sainfo->items)); */ + + /* free the graph data items */ + +#if GLIB_CHECK_VERSION (2, 32, 0) + g_queue_free_full(sainfo->items, sequence_analysis_item_free); + sainfo->items = g_queue_new(); +#else + { + GList *list = g_queue_peek_nth_link(sainfo->items, 0); + while (list) + { + sequence_analysis_item_free(list->data); + list = g_list_next(list); + } + g_queue_clear(sainfo->items); + } +#endif + + if (NULL != sainfo->ht) { + g_hash_table_remove_all(sainfo->ht); + } + sainfo->nconv = 0; + + sequence_analysis_free_nodes(sainfo); +} + +/* Return the index array if the node is in the array. Return -1 if there is room in the array + * and Return -2 if the array is full + */ +/****************************************************************************/ +static guint add_or_get_node(seq_analysis_info_t *sainfo, address *node) { + guint i; + + if (node->type == AT_NONE) return NODE_OVERFLOW; + + for (i=0; inum_nodes ; i++) { + if ( cmp_address(&(sainfo->nodes[i]), node) == 0 ) return i; /* it is in the array */ + } + + if (i >= MAX_NUM_NODES) { + return NODE_OVERFLOW; + } else { + sainfo->num_nodes++; + copy_address(&(sainfo->nodes[i]), node); + return i; + } +} + +struct sainfo_counter { + seq_analysis_info_t *sainfo; + int num_items; +}; + +static void sequence_analysis_get_nodes_item_proc(gpointer data, gpointer user_data) +{ + seq_analysis_item_t *gai = (seq_analysis_item_t *)data; + struct sainfo_counter *sc = (struct sainfo_counter *)user_data; + if (gai->display) { + (sc->num_items)++; + gai->src_node = add_or_get_node(sc->sainfo, &(gai->src_addr)); + gai->dst_node = add_or_get_node(sc->sainfo, &(gai->dst_addr)); + } +} + +/* Get the nodes from the list */ +/****************************************************************************/ +int +sequence_analysis_get_nodes(seq_analysis_info_t *sainfo) +{ + struct sainfo_counter sc = {sainfo, 0}; + + /* Fill the node array */ + g_queue_foreach(sainfo->items, sequence_analysis_get_nodes_item_proc, &sc); + + return sc.num_items; +} + +/* Free the node address list */ +/****************************************************************************/ +void +sequence_analysis_free_nodes(seq_analysis_info_t *sainfo) +{ + int i; + + for (i=0; inodes[i]); + } + sainfo->num_nodes = 0; +} + +/* + * Editor modelines + * + * Local Variables: + * c-basic-offset: 4 + * tab-width: 8 + * indent-tabs-mode: nil + * End: + * + * ex: set shiftwidth=4 tabstop=8 expandtab: + * :indentSize=4:tabSize=8:noTabs=true: + */ -- cgit v1.2.3