Add new plugin type for libwireshark

Allow epan itself to be extended by plugins. Adds the following new plugin
interfaces:

  void plugin_epan_init()
  void plugin_epan_dissect_init(epan_dissect_t *)
  void plugin_epan_dissect_cleanup(epan_dissect_t *)
  void plugin_epan_cleanup()
  void plugin_epan_register_all_protocols(register_cb, gointer) [OPTIONAL]
  void plugin_epan_register_all_handoffs(register_cb, gointer) [OPTIONAL]

Any one of these can be an empty function but the first four must be
present.

The motivation for the change is a better way to implement a language binding
other than registering a fake protocol and stuffing everything into a single
dissector call (and maybe require an extra packet_info field) but I expect
there would be other interesting use cases.

Change-Id: I215d50750ac7561fe25fdcdcfbc6a3f351984785
Reviewed-on: https://code.wireshark.org/review/24813
Petri-Dish: João Valverde <j@v6e.pt>
Tested-by: Petri Dish Buildbot
Reviewed-by: João Valverde <j@v6e.pt>
This commit is contained in:
João Valverde 2017-08-29 15:34:31 +01:00 committed by João Valverde
parent 629596ebef
commit cebb8ea20e
4 changed files with 88 additions and 8 deletions

View File

@ -70,6 +70,10 @@
#include "stats_tree.h"
#include <dtd.h>
#ifdef HAVE_PLUGINS
#include <wsutil/plugins.h>
#endif
#ifdef HAVE_LUA
#include <lua.h>
#include <wslua/wslua.h>
@ -92,10 +96,14 @@
#include <libxml/parser.h>
#endif
static GSList *epan_register_all_procotols = NULL;
static GSList *epan_register_all_handoffs = NULL;
static wmem_allocator_t *pinfo_pool_cache = NULL;
#ifdef HAVE_PLUGINS
plugins_t *libwireshark_plugins = NULL;
static GSList *epan_plugins = NULL;
#endif
const gchar*
@ -140,6 +148,41 @@ quiet_gcrypt_logger (void *dummy _U_, int level, const char *format, va_list arg
}
#endif // _WIN32
#ifdef HAVE_PLUGINS
static void
epan_plugin_init(gpointer data, gpointer user_data _U_)
{
((epan_plugin *)data)->init();
}
static void
epan_plugin_dissect_init(gpointer data, gpointer user_data)
{
((epan_plugin *)data)->dissect_init((epan_dissect_t *)user_data);
}
static void
epan_plugin_dissect_cleanup(gpointer data, gpointer user_data)
{
((epan_plugin *)data)->dissect_cleanup((epan_dissect_t *)user_data);
}
static void
epan_plugin_cleanup(gpointer data, gpointer user_data _U_)
{
((epan_plugin *)data)->cleanup();
}
void epan_register_plugin(const epan_plugin *plug)
{
epan_plugins = g_slist_prepend(epan_plugins, (epan_plugin *)plug);
if (plug->register_all_protocols)
epan_register_all_procotols = g_slist_prepend(epan_register_all_procotols, plug->register_all_protocols);
if (plug->register_all_handoffs)
epan_register_all_handoffs = g_slist_prepend(epan_register_all_handoffs, plug->register_all_handoffs);
}
#endif
gboolean
epan_init(void (*register_all_protocols_func)(register_cb cb, gpointer client_data),
void (*register_all_handoffs_func)(register_cb cb, gpointer client_data),
@ -185,8 +228,12 @@ epan_init(void (*register_all_protocols_func)(register_cb cb, gpointer client_da
conversation_init();
capture_dissector_init();
reassembly_tables_init();
proto_init(register_all_protocols_func, register_all_handoffs_func,
cb, client_data);
#ifdef HAVE_PLUGINS
g_slist_foreach(epan_plugins, epan_plugin_init, NULL);
#endif
epan_register_all_procotols = g_slist_prepend(epan_register_all_procotols, register_all_protocols_func);
epan_register_all_handoffs = g_slist_prepend(epan_register_all_handoffs, register_all_handoffs_func);
proto_init(epan_register_all_procotols, epan_register_all_handoffs, cb, client_data);
packet_cache_proto_handles();
dfilter_init();
final_registration_all_protocols();
@ -244,6 +291,16 @@ epan_load_settings(void)
void
epan_cleanup(void)
{
#ifdef HAVE_PLUGINS
g_slist_foreach(epan_plugins, epan_plugin_cleanup, NULL);
g_slist_free_full(epan_plugins, g_free);
epan_plugins = NULL;
#endif
g_slist_free(epan_register_all_procotols);
epan_register_all_procotols = NULL;
g_slist_free(epan_register_all_handoffs);
epan_register_all_handoffs = NULL;
dfilter_cleanup();
proto_cleanup();
prefs_cleanup();
@ -401,6 +458,10 @@ epan_dissect_init(epan_dissect_t *edt, epan_t *session, const gboolean create_pr
}
edt->tvb = NULL;
#ifdef HAVE_PLUGINS
g_slist_foreach(epan_plugins, epan_plugin_dissect_init, edt);
#endif
}
void
@ -512,6 +573,10 @@ epan_dissect_cleanup(epan_dissect_t* edt)
{
g_assert(edt);
#ifdef HAVE_PLUGINS
g_slist_foreach(epan_plugins, epan_plugin_dissect_cleanup, edt);
#endif
g_slist_free(edt->pi.proto_data);
g_slist_free(edt->pi.dependent_frames);

View File

@ -128,6 +128,18 @@ e_prefs *epan_load_settings(void);
WS_DLL_PUBLIC
void epan_cleanup(void);
#ifdef HAVE_PLUGINS
typedef struct {
void (*init)(void);
void (*dissect_init)(epan_dissect_t *);
void (*dissect_cleanup)(epan_dissect_t *);
void (*cleanup)(void);
void (*register_all_protocols)(register_cb, gpointer);
void (*register_all_handoffs)(register_cb, gpointer);
} epan_plugin;
WS_DLL_PUBLIC void epan_register_plugin(const epan_plugin *plugin);
#endif
/**
* Initialize the table of conversations. Conversations are identified by
* their endpoints; they are used for protocols such as IP, TCP, and UDP,

View File

@ -468,8 +468,8 @@ call_plugin_register_handoff(gpointer data, gpointer user_data _U_)
/* initialize data structures and register protocols and fields */
void
proto_init(void (register_all_protocols_func)(register_cb cb, gpointer client_data),
void (register_all_handoffs_func)(register_cb cb, gpointer client_data),
proto_init(GSList *register_all_protocols_list,
GSList *register_all_handoffs_list,
register_cb cb,
gpointer client_data)
{
@ -506,7 +506,9 @@ proto_init(void (register_all_protocols_func)(register_cb cb, gpointer client_da
dissector tables, and dissectors to be called through a
handle, and do whatever one-time initialization it needs to
do. */
register_all_protocols_func(cb, client_data);
for (GSList *l = register_all_protocols_list; l != NULL; l = l->next) {
((void (*)(register_cb, gpointer))l->data)(cb, client_data);
}
/* Now that the VINES dissector has registered it's address
type, grab the value for the field type */
@ -523,7 +525,9 @@ proto_init(void (register_all_protocols_func)(register_cb cb, gpointer client_da
dissectors; those routines register the dissector in other
dissectors' handoff tables, and fetch any dissector handles
they need. */
register_all_handoffs_func(cb, client_data);
for (GSList *l = register_all_handoffs_list; l != NULL; l = l->next) {
((void (*)(register_cb, gpointer))l->data)(cb, client_data);
}
#ifdef HAVE_PLUGINS
/* Now do the same with plugins. */

View File

@ -921,8 +921,7 @@ WS_DLL_PUBLIC void proto_register_plugin(const proto_plugin *plugin);
#endif
/** Sets up memory used by proto routines. Called at program startup */
void proto_init(void (register_all_protocols_func)(register_cb cb, gpointer client_data),
void (register_all_handoffs_func)(register_cb cb, gpointer client_data),
void proto_init(GSList *register_all_protocols_list, GSList *register_all_handoffs_list,
register_cb cb, void *client_data);