diff options
author | Michael Mann <mmann78@netscape.net> | 2016-03-12 22:11:03 -0500 |
---|---|---|
committer | Michael Mann <mmann78@netscape.net> | 2016-03-20 12:48:31 +0000 |
commit | 6da50e2fde7b678cfbee922e3b12d588d75b6eef (patch) | |
tree | 6a77a67af9ec3cc9c3ec16937751406ae35ebe66 | |
parent | bb74293fa7b018123e34f1f8ca2c7779c0085293 (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>
-rw-r--r-- | debian/libwireshark0.symbols | 4 | ||||
-rw-r--r-- | epan/packet.c | 113 | ||||
-rw-r--r-- | epan/packet.h | 38 |
3 files changed, 154 insertions, 1 deletions
diff --git a/debian/libwireshark0.symbols b/debian/libwireshark0.symbols index db4f0b833b..76f9a386d8 100644 --- a/debian/libwireshark0.symbols +++ b/debian/libwireshark0.symbols @@ -236,6 +236,7 @@ libwireshark.so.0 libwireshark0 #MINVER# decode_tcp_ports@Base 1.99.0 decode_udp_ports@Base 1.99.0 delete_itu_tcap_subdissector@Base 1.9.1 + deregister_depend_dissector@Base 2.1.0 destroy_print_stream@Base 1.12.0~rc1 dfilter_apply_edt@Base 1.9.1 dfilter_compile@Base 1.9.1 @@ -540,7 +541,9 @@ libwireshark.so.0 libwireshark0 #MINVER# find_circuit@Base 1.9.1 find_conversation@Base 1.9.1 find_conversation_filter@Base 2.0.0 + find_depend_dissector_list@Base 2.1.0 find_dissector@Base 1.9.1 + find_dissector_add_dependency@Base 2.1.0 find_dissector_table@Base 1.9.1 find_heur_dissector_by_unique_short_name@Base 1.99.8 find_heur_dissector_list@Base 1.99.2 @@ -1156,6 +1159,7 @@ libwireshark.so.0 libwireshark0 #MINVER# register_custom_dissector_table@Base 1.99.8 register_custom_dissector_table@Base 1.99.8 register_decode_as@Base 1.12.0~rc1 + register_depend_dissector@Base 2.1.0 register_dissector@Base 2.1.0 register_dissector_table@Base 1.9.1 register_export_pdu_tap@Base 1.99.0 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); |