diff options
Diffstat (limited to 'epan/expert.c')
-rw-r--r-- | epan/expert.c | 201 |
1 files changed, 194 insertions, 7 deletions
diff --git a/epan/expert.c b/epan/expert.c index af547a2e3c..b8f439a63b 100644 --- a/epan/expert.c +++ b/epan/expert.c @@ -26,6 +26,8 @@ #include "config.h" +#include <stdio.h> + #include "packet.h" #include "expert.h" #include "emem.h" @@ -47,8 +49,36 @@ static int hf_expert_msg = -1; static int hf_expert_group = -1; static int hf_expert_severity = -1; +struct expert_module +{ + const char* proto_name; + int proto_id; /* Cache this for registering hfs */ + GList *experts; /* expert_infos for this protocol */ + GList *last_expert; /* pointer to end of list of expert_infos */ +}; + +/* List which stores protocols and expert_info that have been registered */ +typedef struct _gpa_expertinfo_t { + guint32 len; + guint32 allocated_len; + expert_field_info **ei; +} gpa_expertinfo_t; +static gpa_expertinfo_t gpa_expertinfo; + +/* + * List of all modules with expert info. + */ +static emem_tree_t *expert_modules = NULL; + + +#define EXPERT_REGISTRAR_GET_NTH(eiindex, expinfo) \ + if((guint)eiindex >= gpa_expertinfo.len && getenv("WIRESHARK_ABORT_ON_DISSECTOR_BUG")) \ + g_error("Unregistered expert info! index=%d", eiindex); \ + DISSECTOR_ASSERT_HINT((guint)eiindex < gpa_expertinfo.len, "Unregistered expert info!");\ + expinfo = gpa_expertinfo.ei[eiindex]; + void -expert_init(void) +expert_packet_init(void) { static hf_register_info hf[] = { { &hf_expert_msg, @@ -78,13 +108,34 @@ expert_init(void) } highest_severity = 0; + + if (expert_modules == NULL) { + expert_modules = pe_tree_create(EMEM_TREE_TYPE_RED_BLACK, "expert_modules"); + } } +void +expert_init(void) +{ + gpa_expertinfo.len = 0; + gpa_expertinfo.allocated_len = 0; + gpa_expertinfo.ei = NULL; +} void -expert_cleanup(void) +expert_packet_cleanup(void) { +} +void +expert_cleanup(void) +{ + if (gpa_expertinfo.allocated_len) { + gpa_expertinfo.len = 0; + gpa_expertinfo.allocated_len = 0; + g_free(gpa_expertinfo.ei); + gpa_expertinfo.ei = NULL; + } } @@ -94,6 +145,97 @@ expert_get_highest_severity(void) return highest_severity; } +expert_module_t *expert_register_protocol(int id) +{ + expert_module_t *module; + protocol_t *protocol; + + protocol = find_protocol_by_id(id); + + module = g_new(expert_module_t,1); + module->proto_id = id; + module->proto_name = proto_get_protocol_short_name(protocol); + module->experts = NULL; + module->last_expert = NULL; + + /* + * Insert this module into the appropriate place in the tree. + */ + pe_tree_insert_string(expert_modules, module->proto_name, module, EMEM_TREE_STRING_NOCASE); + + return module; +} + +static int +expert_register_field_init(expert_field_info *expinfo, expert_module_t* module) +{ + expinfo->protocol = module->proto_name; + + /* if we always add and never delete, then id == len - 1 is correct */ + if (gpa_expertinfo.len >= gpa_expertinfo.allocated_len) { + if (!gpa_expertinfo.ei) { + gpa_expertinfo.allocated_len = PRE_ALLOC_EXPERT_FIELDS_MEM; + gpa_expertinfo.ei = (expert_field_info **)g_malloc(sizeof(expert_field_info *)*PRE_ALLOC_EXPERT_FIELDS_MEM); + } else { + gpa_expertinfo.allocated_len += 1000; + gpa_expertinfo.ei = (expert_field_info **)g_realloc(gpa_expertinfo.ei, + sizeof(expert_field_info *)*gpa_expertinfo.allocated_len); + } + } + gpa_expertinfo.ei[gpa_expertinfo.len] = expinfo; + gpa_expertinfo.len++; + expinfo->id = gpa_expertinfo.len - 1; + + return expinfo->id; +} + + +/* for use with static arrays only, since we don't allocate our own copies +of the expert_field_info struct contained within the exp_register_info struct */ +void +expert_register_field_array(expert_module_t* module, ei_register_info *exp, const int num_records) +{ + int i; + ei_register_info *ptr = exp; + + for (i = 0; i < num_records; i++, ptr++) { + /* + * Make sure we haven't registered this yet. + * Most fields have variables associated with them + * that are initialized to -1; some have array elements, + * or possibly uninitialized variables, so we also allow + * 0 (which is unlikely to be the field ID we get back + * from "expert_register_field_init()"). + */ + if (ptr->ids->ei != -1 && ptr->ids->ei != 0) { + fprintf(stderr, + "Duplicate field detected in call to expert_register_field_array: '%s' is already registered\n", + ptr->eiinfo.summary); + return; + } + + if (module != NULL) { + if (module->experts == NULL) { + module->experts = g_list_append(NULL, ptr); + module->last_expert = module->experts; + } else { + module->last_expert = + g_list_append(module->last_expert, ptr)->next; + } + } + + /* Register the field with the experts */ + ptr->ids->ei = expert_register_field_init(&ptr->eiinfo, module); + + /* Register with the header field info, so it's display filterable */ + ptr->eiinfo.hf_info.p_id = &ptr->ids->hf; + ptr->eiinfo.hf_info.hfinfo.abbrev = ptr->eiinfo.name; + ptr->eiinfo.hf_info.hfinfo.blurb = ptr->eiinfo.summary; + + proto_register_field_array(module->proto_id, &ptr->eiinfo.hf_info, 1); + } +} + /* set's the PI_ flags to a protocol item * (and its parent items till the toplevel) */ @@ -131,7 +273,8 @@ expert_create_tree(proto_item *pi, int group, int severity, const char *msg) } static void -expert_set_info_vformat(packet_info *pinfo, proto_item *pi, int group, int severity, const char *format, va_list ap) +expert_set_info_vformat(packet_info *pinfo, proto_item *pi, int group, int severity, int hf_index, gboolean use_vaformat, + const char *format, va_list ap) { char formatted[ITEM_LABEL_LENGTH]; int tap; @@ -158,12 +301,27 @@ expert_set_info_vformat(packet_info *pinfo, proto_item *pi, int group, int sever col_add_str(pinfo->cinfo, COL_EXPERT, val_to_str(severity, expert_severity_vals, "Unknown (%u)")); - g_vsnprintf(formatted, ITEM_LABEL_LENGTH, format, ap); + if (use_vaformat) { + g_vsnprintf(formatted, ITEM_LABEL_LENGTH, format, ap); + } else { + g_strlcpy(formatted, format, ITEM_LABEL_LENGTH); + } tree = expert_create_tree(pi, group, severity, formatted); - ti = proto_tree_add_string(tree, hf_expert_msg, NULL, 0, 0, formatted); - PROTO_ITEM_SET_GENERATED(ti); + if (hf_index == -1) { + /* If no filterable expert info, just add the message */ + ti = proto_tree_add_string(tree, hf_expert_msg, NULL, 0, 0, formatted); + PROTO_ITEM_SET_GENERATED(ti); + } else { + /* If filterable expert info, hide the "generic" form of the message, + and generate the formatted filterable expert info */ + ti = proto_tree_add_none_format(tree, hf_index, NULL, 0, 0, "%s", formatted); + PROTO_ITEM_SET_GENERATED(ti); + ti = proto_tree_add_string(tree, hf_expert_msg, NULL, 0, 0, formatted); + PROTO_ITEM_SET_HIDDEN(ti); + } + ti = proto_tree_add_uint_format_value(tree, hf_expert_severity, NULL, 0, 0, severity, "%s", val_to_str_const(severity, expert_severity_vals, "Unknown")); PROTO_ITEM_SET_GENERATED(ti); @@ -201,7 +359,36 @@ expert_add_info_format(packet_info *pinfo, proto_item *pi, int group, int severi va_list ap; va_start(ap, format); - expert_set_info_vformat(pinfo, pi, group, severity, format, ap); + expert_set_info_vformat(pinfo, pi, group, severity, -1, TRUE, format, ap); + va_end(ap); +} + +void +expert_add_info(packet_info *pinfo, proto_item *pi, expert_field* expindex) +{ + va_list ap; + expert_field_info* eiinfo; + + /* Look up the item */ + EXPERT_REGISTRAR_GET_NTH(expindex->ei, eiinfo); + + /* Not used by expert_set_info_vformat, but need the variable initialized */ + va_start(ap, eiinfo); + expert_set_info_vformat(pinfo, pi, eiinfo->group, eiinfo->severity, *eiinfo->hf_info.p_id, FALSE, eiinfo->summary, ap); + va_end(ap); +} + +void +expert_add_info_format_text(packet_info *pinfo, proto_item *pi, expert_field* expindex, const char *format, ...) +{ + va_list ap; + expert_field_info* eiinfo; + + /* Look up the item */ + EXPERT_REGISTRAR_GET_NTH(expindex->ei, eiinfo); + + va_start(ap, format); + expert_set_info_vformat(pinfo, pi, eiinfo->group, eiinfo->severity, *eiinfo->hf_info.p_id, TRUE, format, ap); va_end(ap); } |