aboutsummaryrefslogtreecommitdiffstats
path: root/epan/conversation_table.c
diff options
context:
space:
mode:
authorMichael Mann <mmann78@netscape.net>2014-07-25 11:34:51 -0400
committerAnders Broman <a.broman58@gmail.com>2014-08-18 04:24:39 +0000
commit018b84de84343306f731ca04b3d20dd07064cdef (patch)
treee240d07f614c2a910745351f9cf9c1602d2d5da3 /epan/conversation_table.c
parenta76c888cd981bbe77dd8306871791578cd6ba9ca (diff)
Refactor "common" hostlist/endpoint table functionality.
This is very similar in architecture to the changes made to the Conversation table functionality. Since all conversations have endpoints/hostlists, the "registered" list is shared for both. Change-Id: Ie8c6910a68a1b3f27c5b18c4494f49b9404a7b31 Reviewed-on: https://code.wireshark.org/review/3214 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>
Diffstat (limited to 'epan/conversation_table.c')
-rw-r--r--epan/conversation_table.c246
1 files changed, 228 insertions, 18 deletions
diff --git a/epan/conversation_table.c b/epan/conversation_table.c
index 61ec310a19..b3c90e5b7a 100644
--- a/epan/conversation_table.c
+++ b/epan/conversation_table.c
@@ -38,8 +38,11 @@ GList *cmd_string_list_ = NULL;
struct register_ct {
gboolean hide_ports; /* hide TCP / UDP port columns */
int proto_id; /* protocol id (0-indexed) */
- tap_packet_cb packet_func; /* function to be called for new incoming packets */
- conv_gui_init_cb gui_init_cb; /* GUI specific function to initialize conversation */
+ tap_packet_cb conv_func; /* function to be called for new incoming packets for conversation*/
+ tap_packet_cb host_func; /* function to be called for new incoming packets for hostlist */
+ host_tap_prefix prefix_func; /* function to provide prefix if different than default (host) */
+ conv_gui_init_cb conv_gui_init; /* GUI specific function to initialize conversation */
+ host_gui_init_cb host_gui_init; /* GUI specific function to initialize hostlist */
};
gboolean get_conversation_hide_ports(register_ct_t* ct)
@@ -57,9 +60,20 @@ int get_conversation_proto_id(register_ct_t* ct)
tap_packet_cb get_conversation_packet_func(register_ct_t* ct)
{
- return ct->packet_func;
+ return ct->conv_func;
}
+tap_packet_cb get_hostlist_packet_func(register_ct_t* ct)
+{
+ return ct->host_func;
+}
+
+host_tap_prefix get_hostlist_prefix_func(register_ct_t* ct)
+{
+ return ct->prefix_func;
+}
+
+
static GSList *registered_ct_tables = NULL;
void
@@ -77,10 +91,29 @@ dissector_conversation_init(const char *opt_arg, void* userdata)
}
g_string_free(cmd_str, TRUE);
- if (table->gui_init_cb)
- table->gui_init_cb(table, filter);
+ if (table->conv_gui_init)
+ table->conv_gui_init(table, filter);
}
+void
+dissector_hostlist_init(const char *opt_arg, void* userdata)
+{
+ register_ct_t *table = (register_ct_t*)userdata;
+ GString *cmd_str = g_string_new("");
+ const char *filter=NULL;
+
+ g_string_printf(cmd_str, "%s,%s,", (table->prefix_func != NULL) ? table->prefix_func() : "host", proto_get_protocol_filter_name(table->proto_id));
+ if(!strncmp(opt_arg, cmd_str->str, cmd_str->len)){
+ filter=opt_arg+cmd_str->len;
+ } else {
+ filter=NULL;
+ }
+
+ g_string_free(cmd_str, TRUE);
+
+ if (table->host_gui_init)
+ table->host_gui_init(table, filter);
+}
/** get conversation from protocol ID
*
* @param proto_id protocol ID
@@ -110,37 +143,58 @@ insert_sorted_by_table_name(gconstpointer aparam, gconstpointer bparam)
}
void
-register_conversation_table(const int proto_id, gboolean hide_ports, tap_packet_cb packet_func)
+register_conversation_table(const int proto_id, gboolean hide_ports, tap_packet_cb conv_packet_func, tap_packet_cb hostlist_func, host_tap_prefix prefix_func)
{
register_ct_t *table;
- GString *cmd_str = g_string_new("conv,");
+ GString *conv_cmd_str = g_string_new("conv,");
+ GString *host_cmd_str = g_string_new("");
table = g_new(register_ct_t,1);
- table->hide_ports = hide_ports;
- table->proto_id = proto_id;
- table->packet_func = packet_func;
- table->gui_init_cb = NULL;
+ table->hide_ports = hide_ports;
+ table->proto_id = proto_id;
+ table->conv_func = conv_packet_func;
+ table->host_func = hostlist_func;
+ table->conv_gui_init = NULL;
+ table->host_gui_init = NULL;
+ table->prefix_func = prefix_func;
registered_ct_tables = g_slist_insert_sorted(registered_ct_tables, table, insert_sorted_by_table_name);
- g_string_append(cmd_str, proto_get_protocol_filter_name(table->proto_id));
- cmd_string_list_ = g_list_append(cmd_string_list_, cmd_str->str);
- register_stat_cmd_arg(cmd_str->str, dissector_conversation_init, table);
- g_string_free(cmd_str, FALSE);
+ g_string_append(conv_cmd_str, proto_get_protocol_filter_name(table->proto_id));
+ cmd_string_list_ = g_list_append(cmd_string_list_, conv_cmd_str->str);
+ register_stat_cmd_arg(conv_cmd_str->str, dissector_conversation_init, table);
+ g_string_free(conv_cmd_str, FALSE);
+
+ g_string_printf(host_cmd_str, "%s,%s", (get_hostlist_prefix_func(table) != NULL) ? get_hostlist_prefix_func(table)() : "host",
+ proto_get_protocol_filter_name(table->proto_id));
+ register_stat_cmd_arg(host_cmd_str->str, dissector_hostlist_init, table);
+ g_string_free(host_cmd_str, FALSE);
}
/* Set GUI fields for register_ct list */
static void
-set_gui_data(gpointer data, gpointer user_data)
+set_conv_gui_data(gpointer data, gpointer user_data)
{
register_ct_t *table = (register_ct_t*)data;
- table->gui_init_cb = (conv_gui_init_cb)user_data;
+ table->conv_gui_init = (conv_gui_init_cb)user_data;
}
void conversation_table_set_gui_info(conv_gui_init_cb init_cb)
{
- g_slist_foreach(registered_ct_tables, set_gui_data, init_cb);
+ g_slist_foreach(registered_ct_tables, set_conv_gui_data, init_cb);
+}
+
+static void
+set_host_gui_data(gpointer data, gpointer user_data)
+{
+ register_ct_t *table = (register_ct_t*)data;
+ table->host_gui_init = (host_gui_init_cb)user_data;
+}
+
+void hostlist_table_set_gui_info(host_gui_init_cb init_cb)
+{
+ g_slist_foreach(registered_ct_tables, set_host_gui_data, init_cb);
}
void conversation_table_iterate_tables(GFunc func, gpointer user_data)
@@ -243,6 +297,30 @@ reset_conversation_table_data(conv_hash_t *ch)
ch->hashtable=NULL;
}
+void reset_hostlist_table_data(conv_hash_t *ch)
+{
+ if (!ch) {
+ return;
+ }
+
+ if (ch->conv_array != NULL) {
+ guint i;
+ for(i = 0; i < ch->conv_array->len; i++){
+ hostlist_talker_t *host = &g_array_index(ch->conv_array, hostlist_talker_t, i);
+ g_free((gpointer)host->myaddress.data);
+ }
+
+ g_array_free(ch->conv_array, TRUE);
+ }
+
+ if (ch->hashtable != NULL) {
+ g_hash_table_destroy(ch->hashtable);
+ }
+
+ ch->conv_array=NULL;
+ ch->hashtable=NULL;
+}
+
const char *get_conversation_address(address *addr, gboolean resolve_names)
{
if (resolve_names) {
@@ -288,6 +366,17 @@ conversation_get_filter_name(conv_item_t *conv_item, conv_filter_type_e filter_t
return conv_item->dissector_info->get_filter_type(conv_item, filter_type);
}
+static const char *
+hostlist_get_filter_name(hostlist_talker_t *host, conv_filter_type_e filter_type)
+{
+
+ if ((host == NULL) || (host->dissector_info == NULL) || (host->dissector_info->get_filter_type == NULL)) {
+ return CONV_FILTER_INVALID;
+ }
+
+ return host->dissector_info->get_filter_type(host, filter_type);
+}
+
/* Convert a port number into a string or NULL */
static char *
ct_port_to_str(port_type ptype, guint32 port)
@@ -438,6 +527,24 @@ const char *get_conversation_filter(conv_item_t *conv_item, conv_direction_e dir
return str;
}
+const char *get_hostlist_filter(hostlist_talker_t *host)
+{
+ char *sport;
+ const char *str;
+
+ sport=ct_port_to_str(host->ptype, host->port);
+
+ str = g_strdup_printf("%s==%s%s%s%s%s",
+ hostlist_get_filter_name(host, CONV_FT_ANY_ADDRESS),
+ ep_address_to_str(&host->myaddress),
+ sport?" && ":"",
+ sport?hostlist_get_filter_name(host, CONV_FT_ANY_PORT):"",
+ sport?"==":"",
+ sport?sport:"");
+
+ return str;
+}
+
void
add_conversation_table_data(conv_hash_t *ch, const address *src, const address *dst, guint32 src_port, guint32 dst_port, int num_frames, int num_bytes,
nstime_t *ts, nstime_t *abs_ts, ct_dissector_info_t *ct_info, port_type ptype)
@@ -573,6 +680,109 @@ add_conversation_table_data_with_conv_id(
}
/*
+ * Compute the hash value for a given address/port pairs if the match
+ * is to be exact.
+ */
+static guint
+host_hash(gconstpointer v)
+{
+ const host_key_t *key = (const host_key_t *)v;
+ guint hash_val;
+
+ hash_val = 0;
+ ADD_ADDRESS_TO_HASH(hash_val, &key->myaddress);
+ hash_val += key->port;
+ return hash_val;
+}
+
+/*
+ * Compare two host keys for an exact match.
+ */
+static gint
+host_match(gconstpointer v, gconstpointer w)
+{
+ const host_key_t *v1 = (const host_key_t *)v;
+ const host_key_t *v2 = (const host_key_t *)w;
+
+ if (v1->port == v2->port &&
+ ADDRESSES_EQUAL(&v1->myaddress, &v2->myaddress)) {
+ return 1;
+ }
+ /*
+ * The addresses or the ports don't match.
+ */
+ return 0;
+}
+
+void
+add_hostlist_table_data(conv_hash_t *ch, const address *addr, guint32 port, gboolean sender, int num_frames, int num_bytes, hostlist_dissector_info_t *host_info, port_type port_type_val)
+{
+ hostlist_talker_t *talker=NULL;
+ int talker_idx=0;
+
+ /* XXX should be optimized to allocate n extra entries at a time
+ instead of just one */
+ /* if we dont have any entries at all yet */
+ if(ch->conv_array==NULL){
+ ch->conv_array=g_array_sized_new(FALSE, FALSE, sizeof(hostlist_talker_t), 10000);
+ ch->hashtable = g_hash_table_new_full(host_hash,
+ host_match, /* key_equal_func */
+ g_free, /* key_destroy_func */
+ NULL); /* value_destroy_func */
+ }
+ else {
+ /* try to find it among the existing known conversations */
+ host_key_t existing_key;
+
+ existing_key.myaddress = *addr;
+ existing_key.port = port;
+
+ if (g_hash_table_lookup_extended(ch->hashtable, &existing_key, NULL, (gpointer *) &talker_idx)) {
+ talker = &g_array_index(ch->conv_array, hostlist_talker_t, talker_idx);
+ }
+ }
+
+ /* if we still dont know what talker this is it has to be a new one
+ and we have to allocate it and append it to the end of the list */
+ if(talker==NULL){
+ host_key_t *new_key;
+ hostlist_talker_t host;
+
+ COPY_ADDRESS(&host.myaddress, addr);
+ host.dissector_info = host_info;
+ host.ptype=port_type_val;
+ host.port=port;
+ host.rx_frames=0;
+ host.tx_frames=0;
+ host.rx_bytes=0;
+ host.tx_bytes=0;
+ host.modified = TRUE;
+
+ g_array_append_val(ch->conv_array, host);
+ talker_idx= ch->conv_array->len - 1;
+ talker=&g_array_index(ch->conv_array, hostlist_talker_t, talker_idx);
+
+ /* hl->hosts address is not a constant but address.data is */
+ new_key = g_new(host_key_t,1);
+ SET_ADDRESS(&new_key->myaddress, talker->myaddress.type, talker->myaddress.len, talker->myaddress.data);
+ new_key->port = port;
+ g_hash_table_insert(ch->hashtable, new_key, GUINT_TO_POINTER(talker_idx));
+ }
+
+ /* if this is a new talker we need to initialize the struct */
+ talker->modified = TRUE;
+
+ /* update the talker struct */
+ if( sender ){
+ talker->tx_frames+=num_frames;
+ talker->tx_bytes+=num_bytes;
+ } else {
+ talker->rx_frames+=num_frames;
+ talker->rx_bytes+=num_bytes;
+ }
+}
+
+/*
* Editor modelines
*
* Local Variables: