276 lines
7.5 KiB
C
276 lines
7.5 KiB
C
|
/* sequence-analysis.c
|
||
|
* Flow sequence analysis
|
||
|
*
|
||
|
* Some code from from gtk/flow_graph.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.
|
||
|
*/
|
||
|
|
||
|
#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; i<MAX_NUM_NODES && i < sainfo->num_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; i<MAX_NUM_NODES; i++) {
|
||
|
free_address(&sainfo->nodes[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:
|
||
|
*/
|