aboutsummaryrefslogtreecommitdiffstats
path: root/epan
diff options
context:
space:
mode:
authorMichael Mann <mmann78@netscape.net>2016-03-12 22:11:03 -0500
committerMichael Mann <mmann78@netscape.net>2016-03-20 12:48:31 +0000
commit6da50e2fde7b678cfbee922e3b12d588d75b6eef (patch)
tree6a77a67af9ec3cc9c3ec16937751406ae35ebe66 /epan
parentbb74293fa7b018123e34f1f8ca2c7779c0085293 (diff)
Start work on API to generate protocol dependency tree.
Dissector and heuristic tables now setup protocol dependencies. "Manual" dependencies in separate patch. Ping-Bug: 1402 Change-Id: I8da1239306de8676dcb05f8807914376816fc44f Reviewed-on: https://code.wireshark.org/review/14447 Petri-Dish: Roland Knall <rknall@gmail.com> Tested-by: Petri Dish Buildbot <buildbot-no-reply@wireshark.org> Reviewed-by: Michael Mann <mmann78@netscape.net>
Diffstat (limited to 'epan')
-rw-r--r--epan/packet.c113
-rw-r--r--epan/packet.h38
2 files changed, 150 insertions, 1 deletions
diff --git a/epan/packet.c b/epan/packet.c
index 05bae051c2..d347625a07 100644
--- a/epan/packet.c
+++ b/epan/packet.c
@@ -110,6 +110,25 @@ static GHashTable *dissector_tables = NULL;
static GHashTable *registered_dissectors = NULL;
/*
+ * A dissector dependency list.
+ */
+struct depend_dissector_list {
+ GSList *dissectors;
+};
+
+static GHashTable *depend_dissector_lists = NULL;
+
+static void
+destroy_depend_dissector_list(void *data)
+{
+ depend_dissector_list_t dissector_list = (depend_dissector_list_t)data;
+ GSList **list = &(dissector_list->dissectors);
+
+ g_slist_free(*list);
+ g_slice_free(struct depend_dissector_list, dissector_list);
+}
+
+/*
* A heuristics dissector list.
*/
struct heur_dissector_list {
@@ -159,6 +178,9 @@ packet_init(void)
registered_dissectors = g_hash_table_new_full(g_str_hash, g_str_equal,
NULL, NULL);
+ depend_dissector_lists = g_hash_table_new_full(g_str_hash, g_str_equal,
+ NULL, destroy_depend_dissector_list);
+
heur_dissector_lists = g_hash_table_new_full(g_str_hash, g_str_equal,
NULL, destroy_heuristic_dissector_list);
@@ -186,6 +208,7 @@ packet_cleanup(void)
{
g_hash_table_destroy(dissector_tables);
g_hash_table_destroy(registered_dissectors);
+ g_hash_table_destroy(depend_dissector_lists);
g_hash_table_destroy(heur_dissector_lists);
g_hash_table_destroy(heuristic_short_names);
}
@@ -1596,7 +1619,7 @@ void dissector_add_guid(const char *name, guid_key* guid_val, dissector_handle_t
* Now add it to the list of handles that could be used with this
* table, because it *is* being used with this table.
*/
- dissector_add_handle(name, handle);
+ dissector_add_for_decode_as(name, handle);
}
@@ -1726,6 +1749,12 @@ dissector_add_for_decode_as(const char *name, dissector_handle_t handle)
return;
}
+ /* Add the dissector as a dependency
+ (some dissector tables don't have protocol association, so there is
+ the need for the NULL check */
+ if (sub_dissectors->protocol != NULL)
+ register_depend_dissector(proto_get_protocol_short_name(sub_dissectors->protocol), proto_get_protocol_short_name(handle->protocol));
+
/* Is it already in this list? */
entry = g_slist_find(sub_dissectors->dissector_handles, (gpointer)handle);
if (entry != NULL) {
@@ -2245,6 +2274,12 @@ heur_dissector_add(const char *name, heur_dissector_t dissector, const char *dis
/* XXX - could be optimized to pass hdtbl_entry directly */
proto_add_heuristic_dissector(hdtbl_entry->protocol, short_name);
+
+ /* Add the dissector as a dependency
+ (some heuristic tables don't have protocol association, so there is
+ the need for the NULL check */
+ if (sub_dissectors->protocol != NULL)
+ register_depend_dissector(proto_get_protocol_short_name(sub_dissectors->protocol), proto_get_protocol_short_name(hdtbl_entry->protocol));
}
@@ -2589,6 +2624,18 @@ find_dissector(const char *name)
return (dissector_handle_t)g_hash_table_lookup(registered_dissectors, name);
}
+/** Find a dissector by name and add parent protocol as a depedency*/
+dissector_handle_t find_dissector_add_dependency(const char *name, const int parent_proto)
+{
+ dissector_handle_t handle = (dissector_handle_t)g_hash_table_lookup(registered_dissectors, name);
+ if ((handle != NULL) && (parent_proto > 0))
+ {
+ register_depend_dissector(proto_get_protocol_short_name(find_protocol_by_id(parent_proto)), dissector_handle_get_short_name(handle));
+ }
+
+ return handle;
+}
+
/* Get a dissector name from handle. */
const char *
dissector_handle_get_dissector_name(const dissector_handle_t handle)
@@ -2769,6 +2816,70 @@ void call_heur_dissector_direct(heur_dtbl_entry_t *heur_dtbl_entry, tvbuff_t *tv
}
+gboolean register_depend_dissector(const char* parent, const char* dependent)
+{
+ guint i, list_size;
+ GSList *list_entry;
+ const char *protocol_name;
+ depend_dissector_list_t sub_dissectors;
+
+ if ((parent == NULL) || (dependent == NULL))
+ {
+ /* XXX - assert on parent? */
+ return FALSE;
+ }
+
+ sub_dissectors = find_depend_dissector_list(parent);
+ if (sub_dissectors == NULL) {
+ /* parent protocol doesn't exist, create it */
+ sub_dissectors = g_slice_new(struct depend_dissector_list);
+ sub_dissectors->dissectors = NULL; /* initially empty */
+ g_hash_table_insert(depend_dissector_lists, (gpointer)parent, (gpointer) sub_dissectors);
+ }
+
+ /* Verify that sub-dissector is not already in the list */
+ list_size = g_slist_length(sub_dissectors->dissectors);
+ for (i = 0; i < list_size; i++)
+ {
+ list_entry = g_slist_nth(sub_dissectors->dissectors, i);
+ protocol_name = (const char*)list_entry->data;
+ if (strcmp(dependent, protocol_name) == 0)
+ return TRUE; /* Dependency already exists */
+ }
+
+ sub_dissectors->dissectors = g_slist_prepend(sub_dissectors->dissectors, (gpointer)dependent);
+ return TRUE;
+}
+
+static int
+find_matching_depend_dissector( gconstpointer a, gconstpointer b) {
+ return (strcmp((const char*)a, (const char*)b) != 0);
+}
+
+gboolean deregister_depend_dissector(const char* parent, const char* dependent)
+{
+ depend_dissector_list_t sub_dissectors = find_depend_dissector_list(parent);
+ GSList *found_entry;
+
+ /* sanity check */
+ g_assert(sub_dissectors != NULL);
+
+ found_entry = g_slist_find_custom(sub_dissectors->dissectors,
+ (gpointer)dependent, find_matching_depend_dissector);
+
+ if (found_entry) {
+ sub_dissectors->dissectors = g_slist_delete_link(sub_dissectors->dissectors, found_entry);
+ return TRUE;
+ }
+
+ return FALSE;
+}
+
+depend_dissector_list_t find_depend_dissector_list(const char* name)
+{
+ return (depend_dissector_list_t)g_hash_table_lookup(depend_dissector_lists, name);
+}
+
/*
* Dumps the "layer type"/"decode as" associations to stdout, similar
* to the proto_registrar_dump_*() routines.
diff --git a/epan/packet.h b/epan/packet.h
index 1fb6453217..b36ffd43b9 100644
--- a/epan/packet.h
+++ b/epan/packet.h
@@ -515,6 +515,9 @@ WS_DLL_PUBLIC GList* get_dissector_names(void);
/** Find a dissector by name. */
WS_DLL_PUBLIC dissector_handle_t find_dissector(const char *name);
+/** Find a dissector by name and add parent protocol as a depedency*/
+WS_DLL_PUBLIC dissector_handle_t find_dissector_add_dependency(const char *name, const int parent_proto);
+
/** Get a dissector name from handle. */
WS_DLL_PUBLIC const char *dissector_handle_get_dissector_name(const dissector_handle_t handle);
@@ -569,6 +572,41 @@ WS_DLL_PUBLIC int call_dissector_only(dissector_handle_t handle, tvbuff_t *tvb,
WS_DLL_PUBLIC void call_heur_dissector_direct(heur_dtbl_entry_t *heur_dtbl_entry, tvbuff_t *tvb,
packet_info *pinfo, proto_tree *tree, void *data);
+/* This is opaque outside of "packet.c". */
+struct depend_dissector_list;
+typedef struct depend_dissector_list *depend_dissector_list_t;
+
+/** Register a protocol dependency
+ * This is done automatically when registering with a dissector or
+ * heuristic table. This is for "manual" registration when a dissector
+ * ends up calling another through call_dissector (or similar) so
+ * dependencies can be determined
+ *
+ * @param parent "Parent" protocol short name
+ * @param dependent "Dependent" protocol short name
+ * @return return TRUE if dependency was successfully registered
+ */
+WS_DLL_PUBLIC gboolean register_depend_dissector(const char* parent, const char* dependent);
+
+/** Unregister a protocol dependency
+ * This is done automatically when removing from a dissector or
+ * heuristic table. This is for "manual" deregistration for things
+ * like Lua
+ *
+ * @param parent "Parent" protocol short name
+ * @param dependent "Dependent" protocol short name
+ * @return return TRUE if dependency was successfully unregistered
+ */
+WS_DLL_PUBLIC gboolean deregister_depend_dissector(const char* parent, const char* dependent);
+
+/** Find the list of protocol dependencies
+ *
+ * @param name Protocol short name to search for
+ * @return return list of dependent was successfully registered
+ */
+WS_DLL_PUBLIC depend_dissector_list_t find_depend_dissector_list(const char* name);
+
+
/* Do all one-time initialization. */
extern void dissect_init(void);