From 507d07eda6ad562d4567cf0ee83aa9b03997beca Mon Sep 17 00:00:00 2001 From: Michael Mann Date: Tue, 15 Jul 2014 23:04:41 -0400 Subject: Allow severity levels of expert info items to be configured by the user. UAT was the easiest way to do this and I like the "file format" of the data, but the presentation doesn't seem that great. Bug:10180 Change-Id: I7e6bc9e148bc47585a0a7eb8f96900a5c374e673 Reviewed-on: https://code.wireshark.org/review/3082 Petri-Dish: Michael Mann Tested-by: Petri Dish Buildbot Reviewed-by: Michael Mann --- epan/expert.c | 157 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++-- epan/expert.h | 4 +- 2 files changed, 157 insertions(+), 4 deletions(-) (limited to 'epan') diff --git a/epan/expert.c b/epan/expert.c index a69566d120..287be9981e 100644 --- a/epan/expert.c +++ b/epan/expert.c @@ -29,7 +29,8 @@ #include "packet.h" #include "expert.h" -#include "emem.h" +#include "uat.h" +#include "prefs.h" #include "wmem/wmem.h" #include "tap.h" @@ -64,6 +65,9 @@ typedef struct _gpa_expertinfo_t { } gpa_expertinfo_t; static gpa_expertinfo_t gpa_expertinfo; +/* Hash table of abbreviations and IDs */ +static GHashTable *gpa_name_map = NULL; + const value_string expert_group_vals[] = { { PI_CHECKSUM, "Checksum" }, { PI_SEQUENCE, "Sequence" }, @@ -85,7 +89,7 @@ const value_string expert_severity_vals[] = { { PI_NOTE, "Note" }, { PI_CHAT, "Chat" }, { PI_COMMENT, "Comment" }, - { 0, "Ok" }, + { 1, "Ok" }, { 0, NULL } }; @@ -98,6 +102,83 @@ const value_string expert_checksum_vals[] = { { 0, NULL } }; +static expert_field_info* expert_registrar_get_byname(const char *field_name); + +/*----------------------------------------------------------------------------*/ +/* UAT for customizing severity levels. */ +/*----------------------------------------------------------------------------*/ +typedef struct +{ + char * field; + guint32 severity; +} expert_level_entry_t; + +static expert_level_entry_t* uat_expert_entries = NULL; +static guint expert_level_entry_count = 0; +/* Array of field names currently in UAT */ +static GArray *uat_saved_fields = NULL; + +UAT_CSTRING_CB_DEF(uat_expert_entries, field, expert_level_entry_t) +UAT_VS_DEF(uat_expert_entries, severity, expert_level_entry_t, guint32, PI_ERROR, "Error") + +static void uat_expert_update_cb(void* r, const char** err) +{ + expert_level_entry_t* rec = (expert_level_entry_t *)r; + + if (expert_registrar_get_byname(rec->field) == NULL) { + *err = g_strdup_printf("Expert Info field doesn't exist"); + } +} + +static void* uat_expert_copy_cb(void* n, const void* o, size_t siz _U_) +{ + expert_level_entry_t* new_record = (expert_level_entry_t*)n; + const expert_level_entry_t* old_record = (const expert_level_entry_t*)o; + + if (old_record->field) { + new_record->field = g_strdup(old_record->field); + } else { + new_record->field = NULL; + } + + new_record->severity = old_record->severity; + + return new_record; +} + +static void uat_expert_free_cb(void*r) +{ + expert_level_entry_t* rec = (expert_level_entry_t *)r; + + if (rec->field) + g_free(rec->field); +} + +static void uat_expert_post_update_cb(void) +{ + guint i; + expert_field_info* field; + + /* Reset any of the previous list of expert info fields to their original severity */ + for ( i = 0 ; i < uat_saved_fields->len; i++ ) { + field = g_array_index(uat_saved_fields, expert_field_info*, i); + if (field != NULL) { + field->severity = field->orig_severity; + } + } + + g_array_set_size(uat_saved_fields, 0); + + for (i = 0; i < expert_level_entry_count; i++) + { + field = expert_registrar_get_byname(uat_expert_entries[i].field); + if (field != NULL) + { + field->severity = uat_expert_entries[i].severity; + g_array_append_val(uat_saved_fields, field); + } + } +} #define EXPERT_REGISTRAR_GET_NTH(eiindex, expinfo) \ if((guint)eiindex >= gpa_expertinfo.len && getenv("WIRESHARK_ABORT_ON_DISSECTOR_BUG")) \ @@ -108,6 +189,9 @@ const value_string expert_checksum_vals[] = { void expert_packet_init(void) { + module_t *module_expert; + uat_t * expert_uat; + static hf_register_info hf[] = { { &hf_expert_msg, { "Message", "_ws.expert.message", FT_STRING, BASE_NONE, NULL, 0, "Wireshark expert information", HFILL } @@ -124,6 +208,13 @@ expert_packet_init(void) &ett_subexpert }; + /* UAT for overriding severity levels */ + static uat_field_t custom_expert_fields[] = { + UAT_FLD_CSTRING(uat_expert_entries, field, "Field name", "Expert Info filter name"), + UAT_FLD_VS(uat_expert_entries, severity, "Severity", expert_severity_vals, "Custom severity level"), + UAT_END_FIELDS + }; + if (expert_tap == -1) { expert_tap = register_tap("expert"); } @@ -133,6 +224,29 @@ expert_packet_init(void) proto_register_field_array(proto_expert, hf, array_length(hf)); proto_register_subtree_array(ett, array_length(ett)); proto_set_cant_toggle(proto_expert); + + module_expert = prefs_register_protocol(proto_expert, NULL); + + expert_uat = uat_new("Expert Info Severity Level Configuration", + sizeof(expert_level_entry_t), + "expert_severity", + TRUE, + (void * *)&uat_expert_entries, + &expert_level_entry_count, + UAT_AFFECTS_DISSECTION, + NULL, + uat_expert_copy_cb, + uat_expert_update_cb, + uat_expert_free_cb, + uat_expert_post_update_cb, + custom_expert_fields); + + prefs_register_uat_preference(module_expert, + "expert_severity_levels", + "Severity Level Configuration", + "A table that overrides Expert Info field severity levels to user configured levels", + expert_uat); + } highest_severity = 0; @@ -146,6 +260,8 @@ expert_init(void) gpa_expertinfo.len = 0; gpa_expertinfo.allocated_len = 0; gpa_expertinfo.ei = NULL; + gpa_name_map = g_hash_table_new_full(g_str_hash, g_str_equal, NULL, NULL); + uat_saved_fields = g_array_new(FALSE, FALSE, sizeof(expert_field_info*)); } void @@ -162,6 +278,18 @@ expert_cleanup(void) g_free(gpa_expertinfo.ei); gpa_expertinfo.ei = NULL; } + + /* Free the abbrev/ID GTree */ + if (gpa_name_map) { + g_hash_table_destroy(gpa_name_map); + gpa_name_map = NULL; + } + + /* Free the UAT saved fields */ + if (uat_saved_fields) { + g_array_free(uat_saved_fields, TRUE); + uat_saved_fields = NULL; + } } @@ -211,6 +339,11 @@ expert_register_field_init(expert_field_info *expinfo, expert_module_t* module) gpa_expertinfo.ei[gpa_expertinfo.len] = expinfo; gpa_expertinfo.len++; expinfo->id = gpa_expertinfo.len - 1; + /* Save the original severity so it can be restored by the UAT */ + expinfo->orig_severity = expinfo->severity; + + /* save field name for lookup */ + g_hash_table_insert(gpa_name_map, (gpointer) (expinfo->name), expinfo); return expinfo->id; } @@ -252,6 +385,24 @@ expert_register_field_array(expert_module_t* module, ei_register_info *exp, cons } } +/* Finds a record in the expert array by name. + * For the moment, this function is only used "internally" + * but may find a reason to be exported + */ +static expert_field_info * +expert_registrar_get_byname(const char *field_name) +{ + expert_field_info *hfinfo; + + if (!field_name) + return NULL; + + hfinfo = (expert_field_info*)g_hash_table_lookup(gpa_name_map, field_name); + + return hfinfo; +} + + /** clear flags according to the mask and set new flag values */ #define FI_REPLACE_FLAGS(fi, mask, flags_in) { \ (fi->flags = (fi)->flags & ~(mask)); \ @@ -270,7 +421,7 @@ expert_set_item_flags(proto_item *pi, const int group, const guint severity) /* propagate till toplevel item */ pi = proto_item_get_parent(pi); expert_set_item_flags(pi, group, severity); - } + } } static proto_tree* diff --git a/epan/expert.h b/epan/expert.h index 095b472deb..f903295520 100644 --- a/epan/expert.h +++ b/epan/expert.h @@ -65,11 +65,13 @@ typedef struct expert_field_info { /* ------- set by register routines (prefilled by EXPFILL macro, see below) ------ */ int id; const gchar *protocol; + int orig_severity; /* Matches severity when registered, used to restore original severity + * if UAT severity entry is removed */ hf_register_info hf_info; } expert_field_info; -#define EXPFILL 0, NULL, \ +#define EXPFILL 0, NULL, 0, \ {0, {"Expert Info", NULL, FT_NONE, BASE_NONE, NULL, 0, NULL, HFILL}} typedef struct ei_register_info { -- cgit v1.2.3