#include "config.h"
+#include <stdio.h>
+
#include "packet.h"
#include "expert.h"
#include "emem.h"
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,
}
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;
+ }
}
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) */
}
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;
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);
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);
}
proto_item *pitem;
} expert_info_t;
+/* Expert Info and Display hf data */
+typedef struct expert_field
+{
+ int ei;
+ int hf;
+} expert_field;
+
+#define EI_INIT {-1, -1}
+
+typedef struct expert_field_info {
+ /* ---------- set by dissector --------- */
+ const char *name;
+ int group;
+ int severity;
+ const gchar *summary;
+
+ /* ------- set by register routines (prefilled by EXPFILL macro, see below) ------ */
+ int id;
+ const gchar *protocol;
+ hf_register_info hf_info;
+
+} expert_field_info;
+
+#define EXPFILL 0, NULL, \
+ {0, {"Expert Info", NULL, FT_NONE, BASE_NONE, NULL, 0, NULL, HFILL}}
+
+typedef struct ei_register_info {
+ expert_field *ids; /**< written to by register() function */
+ expert_field_info eiinfo; /**< the field info to be registered */
+} ei_register_info;
+
+typedef struct expert_module expert_module_t;
+
static const value_string expert_group_vals[] = {
{ PI_CHECKSUM, "Checksum" },
{ PI_SEQUENCE, "Sequence" },
{ 0, NULL }
};
+#define PRE_ALLOC_EXPERT_FIELDS_MEM 5000
+
/* "proto_expert" is exported from libwireshark.dll.
* Thus we need a special declaration.
*/
extern void
expert_init(void);
+extern void
+expert_packet_init(void);
+
extern void
expert_cleanup(void);
+extern void
+expert_packet_cleanup(void);
+
WS_DLL_PUBLIC int
expert_get_highest_severity(void);
+/** Add an expert info.
+ Add an expert info tree to a protocol item using registered expert info item
+ @param pinfo Packet info of the currently processed packet. May be NULL if
+ pi is supplied
+ @param pi Current protocol item (or NULL)
+ @param eiindex The registered expert info item
+ */
+WS_DLL_PUBLIC void
+expert_add_info(packet_info *pinfo, proto_item *pi, expert_field* eiindex);
+
/** Add an expert info.
Add an expert info tree to a protocol item, with classification and message.
@param pinfo Packet info of the currently processed packet. May be NULL if
int severity, const char *format, ...)
G_GNUC_PRINTF(5, 6);
+/** Add an expert info.
+ Add an expert info tree to a protocol item, using registered expert info item,
+ but with a formatted message.
+ @param pinfo Packet info of the currently processed packet. May be NULL if
+ pi is supplied
+ @param pi Current protocol item (or NULL)
+ @param eiindex The registered expert info item
+ @param format Printf-style format string for additional arguments
+ */
+WS_DLL_PUBLIC void
+expert_add_info_format_text(packet_info *pinfo, proto_item *pi, expert_field* eiindex,
+ const char *format, ...) G_GNUC_PRINTF(5, 6);
+
+/*
+ * Register that a protocol has expert info.
+ */
+WS_DLL_PUBLIC expert_module_t *expert_register_protocol(int id);
+
+/** Register a expert field array.
+ @param module the protocol handle from expert_register_protocol()
+ @param ei the ei_register_info array
+ @param num_records the number of records in exp */
+WS_DLL_PUBLIC void
+expert_register_field_array(expert_module_t* module, ei_register_info *ei, const int num_records);
+
+
/** Add an expert info about not dissected "item"
Add an expert info tree to a not dissected protocol item.
@param tvb The tvb associated with the item.