diff --git a/epan/conversation_filter.c b/epan/conversation_filter.c index 0eea70398e..0f29c6569a 100644 --- a/epan/conversation_filter.c +++ b/epan/conversation_filter.c @@ -20,6 +20,19 @@ GList *packet_conv_filter_list = NULL; GList *log_conv_filter_list = NULL; +static GSList *conversation_proto_names = NULL; + +void conversation_filters_init(void) +{ + // add_conversation_filter_protocol prepends entries to the list. Add + // lower layers first so that upper-layer conversations take precedence. + add_conversation_filter_protocol("eth"); + add_conversation_filter_protocol("ipv6"); + add_conversation_filter_protocol("ip"); + add_conversation_filter_protocol("udp"); + add_conversation_filter_protocol("tcp"); +} + static void do_register_conversation_filter(GList **conv_filter_list, const char *proto_name, const char *display_name, is_filter_valid_func is_filter_valid, build_filter_string_func build_filter_string) { conversation_filter_t *entry; @@ -52,6 +65,16 @@ void register_log_conversation_filter(const char *proto_name, const char *displa build_filter_string); } +void add_conversation_filter_protocol(const char *proto_name) +{ + for (GSList *cur_entry = conversation_proto_names; cur_entry; cur_entry = g_slist_next(cur_entry)) { + if (strcmp(proto_name, cur_entry->data) == 0) { + return; + } + } + conversation_proto_names = g_slist_prepend(conversation_proto_names, (void *)proto_name); +} + static struct conversation_filter_s* find_conversation_filter(GList *conv_filter_list, const char *name) { GList *list_entry = conv_filter_list; @@ -79,17 +102,17 @@ void conversation_filters_cleanup(void) g_list_free(packet_conv_filter_list); g_list_foreach(log_conv_filter_list, conversation_filter_free, NULL); g_list_free(log_conv_filter_list); + + g_slist_free(conversation_proto_names); } static gchar *conversation_filter_from_pinfo(GList *conv_filter_list, struct _packet_info *pinfo) { - const char *layers[] = { "tcp", "udp", "ip", "ipv6", "eth" }; conversation_filter_t *conv_filter; gchar *filter; - size_t i; - for (i = 0; i < G_N_ELEMENTS(layers); i++) { - conv_filter = find_conversation_filter(conv_filter_list, layers[i]); + for (GSList *cur_entry = conversation_proto_names; cur_entry; cur_entry = g_slist_next(cur_entry)) { + conv_filter = find_conversation_filter(conv_filter_list, (const char *) cur_entry->data); if (conv_filter && conv_filter->is_filter_valid(pinfo)) { if ((filter = conv_filter->build_filter_string(pinfo)) != NULL) return filter; diff --git a/epan/conversation_filter.h b/epan/conversation_filter.h index e0286cbd66..7fd4f0f78e 100644 --- a/epan/conversation_filter.h +++ b/epan/conversation_filter.h @@ -21,6 +21,9 @@ extern "C" { /** @file */ +/** Initialize internal structures */ +extern void conversation_filters_init(void); + /** callback function definition: is a filter available for this packet? */ typedef gboolean (*is_filter_valid_func)(struct _packet_info *pinfo); @@ -35,8 +38,13 @@ WS_DLL_PUBLIC void register_conversation_filter(const char *proto_name, const ch /** register a dissector filter for logs */ WS_DLL_PUBLIC void register_log_conversation_filter(const char *proto_name, const char *display_name, is_filter_valid_func is_filter_valid, build_filter_string_func build_filter_string); +/** + * Prepend a protocol to the list of filterable protocols. + * @param A valid protocol name. + */ +WS_DLL_PUBLIC void add_conversation_filter_protocol(const char *proto_name); -/* Cleanup internal structures */ +/** Cleanup internal structures */ extern void conversation_filters_cleanup(void); /** diff --git a/epan/epan.c b/epan/epan.c index 0fe4adc588..23dba61e3d 100644 --- a/epan/epan.c +++ b/epan/epan.c @@ -302,6 +302,7 @@ epan_init(register_cb cb, gpointer client_data, gboolean load_plugins) conversation_init(); capture_dissector_init(); reassembly_tables_init(); + conversation_filters_init(); g_slist_foreach(epan_plugins, epan_plugin_init, NULL); proto_init(epan_plugin_register_all_procotols, epan_plugin_register_all_handoffs, cb, client_data); g_slist_foreach(epan_plugins, epan_plugin_register_all_tap_listeners, NULL); diff --git a/packaging/debian/libwireshark0.symbols b/packaging/debian/libwireshark0.symbols index ba44007c20..26f2329c8e 100644 --- a/packaging/debian/libwireshark0.symbols +++ b/packaging/debian/libwireshark0.symbols @@ -22,6 +22,7 @@ libwireshark.so.0 libwireshark0 #MINVER# abs_time_secs_to_str_ex@Base 3.7.0 abs_time_to_str_ex@Base 3.7.0 add_ber_encoded_label@Base 3.7.0 + add_conversation_filter_protocol@Base 3.7.0 add_conversation_table_data@Base 2.5.0 add_conversation_table_data_with_conv_id@Base 2.5.0 add_hostlist_table_data@Base 2.5.0 diff --git a/plugins/epan/falco_bridge/packet-falco-bridge.c b/plugins/epan/falco_bridge/packet-falco-bridge.c index 55761c1bb6..9ae05f5558 100644 --- a/plugins/epan/falco_bridge/packet-falco-bridge.c +++ b/plugins/epan/falco_bridge/packet-falco-bridge.c @@ -123,7 +123,6 @@ static conv_fld_info conv_fld_infos[MAX_N_CONV_FILTERS]; DECLARE_CONV_FLTS() static char conv_flt_vals[MAX_N_CONV_FILTERS][MAX_CONV_FILTER_STR_LEN]; static guint conv_vals_cnt = 0; -static guint conv_fld_cnt = 0; void register_conversation_filters_mappings(void) @@ -161,6 +160,8 @@ configure_plugin(bridge_info* bi, char* config _U_) bi->field_flags = (guint32*)wmem_alloc(wmem_epan_scope(), bi->visible_fields * sizeof(guint32)); uint32_t fld_cnt = 0; + size_t conv_fld_cnt = 0; + for (uint32_t j = 0; j < tot_fields; j++) { bi->hf_ids[fld_cnt] = -1; @@ -227,13 +228,16 @@ configure_plugin(bridge_info* bi, char* config _U_) conv_fld_infos[conv_fld_cnt].field_info = ri; const char *source_name = get_sinsp_source_name(bi->ssi); conv_fld_infos[conv_fld_cnt].proto_name = source_name; + // XXX We currently build a filter per field. Should we "and" them instead? register_log_conversation_filter(source_name, finfo.hfinfo.name, fv_func[conv_fld_cnt], bfs_func[conv_fld_cnt]); conv_fld_cnt++; } fld_cnt++; } proto_register_field_array(proto_falco_bridge, bi->hf, fld_cnt); - + if (conv_fld_cnt > 0) { + add_conversation_filter_protocol(get_sinsp_source_name(bi->ssi)); + } } } diff --git a/ui/logwolf/logwolf_main_window_slots.cpp b/ui/logwolf/logwolf_main_window_slots.cpp index 5790ae9d99..09271f0adf 100644 --- a/ui/logwolf/logwolf_main_window_slots.cpp +++ b/ui/logwolf/logwolf_main_window_slots.cpp @@ -2493,7 +2493,7 @@ void LogwolfMainWindow::colorizeConversation(bool create_rule) if (capture_file_.capFile() && selectedRows().count() > 0) { packet_info *pi = capture_file_.packetInfo(); guint8 cc_num = colorize_action->data().toUInt(); - gchar *filter = conversation_filter_from_packet(pi); + gchar *filter = conversation_filter_from_log(pi); if (filter == NULL) { mainApp->pushStatus(WiresharkApplication::TemporaryStatus, tr("Unable to build conversation filter.")); return;