Reworking plugin interface to not rely on macros.

The Plugin.cc file is now just a standard class, with the interface
changed a bit to make it more easy to write. However, there're still
some conventions that one must follow to make everything work (like
using the right namespace structure).

This commit also includes the option to compile built-in plugins
dynamically instead of statically by adding
SET(BRO_PLUGIN_BUILD_DYNAMIC TRUE) to their CMake config. This hasn't
been tested much yet, and I'm still undecided if it's somethign we
would want to do by default--but we could now if wanted. :)

Also some minor other cleanup of plugin APIs and built infrastructure.

All tested on MacOS only currently.
This commit is contained in:
Robin Sommer 2014-01-18 22:06:30 +01:00
parent 9227a57935
commit ea01a1be30
21 changed files with 273 additions and 333 deletions

View file

@ -31,10 +31,12 @@ configure_file(bro-path-dev.in ${CMAKE_CURRENT_BINARY_DIR}/bro-path-dev)
file(WRITE ${CMAKE_CURRENT_BINARY_DIR}/bro-path-dev.sh
"export BROPATH=`${CMAKE_CURRENT_BINARY_DIR}/bro-path-dev`\n"
"export BROMAGIC=\"${BRO_MAGIC_SOURCE_PATH}\"\n"
"export BRO_PLUGIN_PATH=\"${CMAKE_CURRENT_BINARY_DIR}/src:${BRO_PLUGIN_INSTALL_PATH}\"\n"
"export PATH=\"${CMAKE_CURRENT_BINARY_DIR}/src\":$PATH\n")
file(WRITE ${CMAKE_CURRENT_BINARY_DIR}/bro-path-dev.csh
"setenv BROPATH `${CMAKE_CURRENT_BINARY_DIR}/bro-path-dev`\n"
"setenv BROMAGIC \"${BRO_MAGIC_SOURCE_PATH}\"\n"
"setenv BRO_PLUGIN_PATH \"${CMAKE_CURRENT_BINARY_DIR}/src:${BRO_PLUGIN_INSTALL_PATH}\"\n"
"setenv PATH \"${CMAKE_CURRENT_BINARY_DIR}/src\":$PATH\n")
file(STRINGS "${CMAKE_CURRENT_SOURCE_DIR}/VERSION" VERSION LIMIT_COUNT 1)

@ -1 +1 @@
Subproject commit 14457e3f222bd2678376e7bbbd15a1497df1828e
Subproject commit 4dafab5aa006173f80ae3fea4adb66117e574f6f

@ -1 +1 @@
Subproject commit 26c3136d56493017bc33c5a2f22ae393d585c2d9
Subproject commit ce366206e3407e534a786ad572c342e9f9fef26b

2
cmake

@ -1 +1 @@
Subproject commit 14141bc12b7a904619101d2caa1b1eee8ec8fbb6
Subproject commit 37c0425715e71fc175b4b9527443b8f0174f1292

View file

@ -98,20 +98,20 @@ option:
That looks quite good, except for the dummy description that we should
replace with something nicer so that users will know what our plugin
is about. We do this by editing the ``BRO_PLUGIN_DESCRIPTION`` line
in ``src/Plugin.cc``, like this:
is about. We do this by editing the ``config.description`` line in
``src/Plugin.cc``, like this:
# cat src/Plugin.cc
#include <plugin/Plugin.h>
BRO_PLUGIN_BEGIN(Demo, Rot13)
BRO_PLUGIN_VERSION(1);
BRO_PLUGIN_DESCRIPTION("Caesar cipher rotating a string's characters by 13 places.");
BRO_PLUGIN_BIF_FILE(consts);
BRO_PLUGIN_BIF_FILE(events);
BRO_PLUGIN_BIF_FILE(functions);
BRO_PLUGIN_END
[...]
plugin::Configuration Configure()
{
plugin::Configuration config;
config.name = "Demo::Rot13";
config.description = "Caesar cipher rotating a string's characters by 13 places.";
config.version.major = 1;
config.version.minor = 0;
return config;
}
[...]
# make
[...]

View file

@ -8,6 +8,7 @@ set(bro_ALL_GENERATED_OUTPUTS CACHE INTERNAL "automatically generated files" FO
# This collects bif inputs that we'll load automatically.
set(bro_AUTO_BIFS CACHE INTERNAL "BIFs for automatic inclusion" FORCE)
set(bro_REGISTER_BIFS CACHE INTERNAL "BIFs for automatic registering" FORCE)
# If TRUE, use CMake's object libraries for sub-directories instead of
# static libraries. This requires CMake >= 2.8.8.
@ -164,8 +165,8 @@ if ( NOT bro_HAVE_OBJECT_LIBRARIES )
foreach (_plugin ${bro_PLUGIN_LIBS})
string(REGEX REPLACE "plugin-" "" _plugin "${_plugin}")
string(REGEX REPLACE "-" "_" _plugin "${_plugin}")
set(_decl "namespace plugin { namespace ${_plugin} { class Plugin; extern Plugin __plugin; } };")
set(_use "i += (size_t)(&(plugin::${_plugin}::__plugin));")
set(_decl "namespace plugin { namespace ${_plugin} { class Plugin; extern Plugin plugin; } };")
set(_use "i += (size_t)(&(plugin::${_plugin}::plugin));")
set(__BRO_DECL_PLUGINS "${__BRO_DECL_PLUGINS}${_decl}\n")
set(__BRO_USE_PLUGINS "${__BRO_USE_PLUGINS}${_use}\n")
endforeach()
@ -368,7 +369,6 @@ set(bro_SRCS
plugin/TaggedComponent.h
plugin/Manager.cc
plugin/Plugin.cc
plugin/Macros.h
nb_dns.c
digest.h
@ -397,12 +397,14 @@ add_custom_target(generate_outputs_stage1)
add_dependencies(generate_outputs_stage1 ${bro_ALL_GENERATED_OUTPUTS})
# Target to create the joint includes files that pull in the bif code.
bro_bif_create_includes(generate_outputs_stage2 ${CMAKE_CURRENT_BINARY_DIR} "${bro_AUTO_BIFS}")
add_dependencies(generate_outputs_stage2 generate_outputs_stage1)
bro_bif_create_includes(generate_outputs_stage2a ${CMAKE_CURRENT_BINARY_DIR} "${bro_AUTO_BIFS}")
bro_bif_create_register(generate_outputs_stage2b ${CMAKE_CURRENT_BINARY_DIR} "${bro_REGISTER_BIFS}")
add_dependencies(generate_outputs_stage2a generate_outputs_stage1)
add_dependencies(generate_outputs_stage2b generate_outputs_stage1)
# Global target to trigger creation of autogenerated code.
add_custom_target(generate_outputs)
add_dependencies(generate_outputs generate_outputs_stage2)
add_dependencies(generate_outputs generate_outputs_stage2a generate_outputs_stage2b)
# Build __load__.bro files for standard *.bif.bro.
bro_bif_create_loader(bif_loader ${CMAKE_BINARY_DIR}/scripts/base/bif)

View file

@ -606,6 +606,7 @@ void builtin_error(const char* msg, BroObj* arg)
#include "strings.bif.func_def"
#include "__all__.bif.cc" // Autogenerated for compiling in the bif_target() code.
#include "__all__.bif.register.cc" // Autogenerated for compiling in the bif_target() code.
void init_builtin_funcs()
{

View file

@ -8,4 +8,3 @@ bro_plugin_cc(HTTP.cc Plugin.cc)
bro_plugin_bif(events.bif)
bro_plugin_bif(functions.bif)
bro_plugin_end()

View file

@ -9,7 +9,7 @@
#include "analyzer/protocol/mime/MIME.h"
#include "binpac_bro.h"
#include "IPAddr.h"
#include "events.bif.h"
#include "analyzer/protocol/http/events.bif.h"
#include "HTTP.h"

View file

@ -1,6 +1,6 @@
%%{
#include "protocol/http/HTTP.h"
#include "analyzer/protocol/http/HTTP.h"
%%}
## Skips the data of the HTTP entity.

View file

@ -152,6 +152,7 @@ FILE* fp_bro_init = 0;
FILE* fp_func_def = 0;
FILE* fp_func_h = 0;
FILE* fp_func_init = 0;
FILE* fp_func_register = 0;
FILE* fp_netvar_h = 0;
FILE* fp_netvar_def = 0;
FILE* fp_netvar_init = 0;
@ -190,6 +191,7 @@ void init_alternative_mode()
fp_func_h = open_output_file("h");
fp_func_def = open_output_file("cc");
fp_func_init = open_output_file("init.cc");
fp_func_register = plugin ? open_output_file("register.cc") : NULL;
fp_netvar_h = fp_func_h;
fp_netvar_def = fp_func_def;
@ -207,6 +209,9 @@ void init_alternative_mode()
fprintf(fp_func_h, "// %s\n\n", auto_gen_comment);
fprintf(fp_func_init, "// %s\n\n", auto_gen_comment);
if ( fp_func_register )
fprintf(fp_func_register, "// %s\n\n", auto_gen_comment);
static char guard[1024];
if ( getcwd(guard, sizeof(guard)) == NULL )
{
@ -244,16 +249,32 @@ void init_alternative_mode()
if ( plugin )
{
static char plugin_canon[1024];
strncpy(plugin_canon, plugin, sizeof(plugin_canon));
char* colon = strstr(plugin_canon, "::");
if ( colon ) {
*colon = '_';
memmove(colon + 1, colon + 2, plugin_canon + strlen(plugin_canon) - colon);
}
fprintf(fp_func_init, "\n");
fprintf(fp_func_init, "#include <list>\n");
fprintf(fp_func_init, "#include <string>\n");
fprintf(fp_func_init, "#include \"plugin/Plugin.h\"\n");
fprintf(fp_func_init, "#include \"%s.h\"\n", input_filename);
fprintf(fp_func_init, "\n");
fprintf(fp_func_init, "namespace plugin { namespace %s {\n", plugin);
fprintf(fp_func_init, "namespace plugin { namespace %s {\n", plugin_canon);
fprintf(fp_func_init, "\n");
fprintf(fp_func_init, "void __bif_%s_init(plugin::Plugin* plugin)\n", name);
fprintf(fp_func_init, "\t{\n");
fprintf(fp_func_register, "#include \"plugin/Manager.h\"\n");
fprintf(fp_func_register, "\n");
fprintf(fp_func_register, "namespace plugin { namespace %s {\n", plugin_canon);
fprintf(fp_func_register, "void __bif_%s_init(plugin::Plugin* plugin);\n", name);
fprintf(fp_func_register, "::plugin::__RegisterBif __register_bifs_%s_%s(\"%s\", __bif_%s_init);\n", plugin_canon, name, plugin, name);
fprintf(fp_func_register, "} }\n");
}
}
@ -268,6 +289,7 @@ void finish_alternative_mode()
fprintf(fp_func_init, "\t}\n");
fprintf(fp_func_init, "} }\n");
fprintf(fp_func_init, "\n");
fprintf(fp_func_init, "\n");
}
}
@ -364,6 +386,7 @@ void close_all_output_files(void)
close_if_open(&fp_func_h);
close_if_open(&fp_func_def);
close_if_open(&fp_func_init);
close_if_open(&fp_func_register);
if ( ! alternative_mode )
{
@ -389,6 +412,7 @@ void err_exit(void)
remove_file("func_h");
remove_file("func_def");
remove_file("func_init");
remove_file("func_register");
remove_file("netvar_h");
remove_file("netvar_def");
remove_file("netvar_init");

View file

@ -1,138 +0,0 @@
// See the file "COPYING" in the main distribution directory for copyright.
/**
* A set of macros wrapping internal logic for defining plugins and
* components.
*/
#ifndef PLUGIN_MACROS_H
#define PLUGIN_MACROS_H
#include "analyzer/Component.h"
#include "file_analysis/Component.h"
/**
* The current plugin API version. Plugins that won't match this version will
* be rejected.
*/
#define BRO_PLUGIN_API_VERSION 1
/**
* Starts the definition of a new plugin.
*
* @param _ns: A namespace for the plugin. All plugins compiled in statically
* must use the reserved "Bro" namespace. External plugins should define
* their own namespace to avoid collisions.
*
* @param _name: The plugin's name. The combiniation of namespace and name
* must be unique across all loaded plugins.
*/
#define BRO_PLUGIN_BEGIN(_ns, _name) \
namespace plugin { namespace _ns ## _ ## _name { \
class Plugin : public plugin::Plugin { \
protected: \
void InitPreScript() \
{ \
SetName(#_ns "::" #_name); \
SetVersion(-1); \
SetAPIVersion(BRO_PLUGIN_API_VERSION); \
SetDynamicPlugin(! BRO_PLUGIN_INTERNAL_BUILD);\
/**
* Ends the definition of a plugin.
*/
#define BRO_PLUGIN_END \
} \
}; \
\
Plugin __plugin; \
} }
/**
* Provides a textual description for a plugin.
*
* @param d A string with the description.
*/
#define BRO_PLUGIN_DESCRIPTION(d) SetDescription(d)
/**
* Defines a version of the plugin. The version is mostly informational for
* the user; if a plugin's functionality changes, the version should be
* increased.
*
* @param v An integer version.
*/
#define BRO_PLUGIN_VERSION(v) SetVersion(v)
/**
* Enables a hook for the plugin. Once enabled, Bro will call the
* corresponding virtual function.
*
* @param h The \a HookType to able.
*/
#define BRO_PLUGIN_ENABLE_HOOK(h) EnableHook(h)
/**
* Adds script-level items defined in a \c *.bif file to what the plugin
* provides.
*
* @param file A string with the name of \c *.bif file. When loaded, the
* plugin will make all items defined in the file available to Bro's script
* interpreter.
*/
#define BRO_PLUGIN_BIF_FILE(file) \
extern void __bif_##file##_init(plugin::Plugin*); \
__AddBifInitFunction(&__bif_##file##_init);
/**
* Defines a component implementing a protocol analyzer.
*
* @param tag A string with the analyzer's tag. This must be unique across
* all loaded analyzers and will translate into a corresponding \c ANALYZER_*
* constant at the script-layer.
*
* @param cls The class that implements the analyzer. It must be derived
* (directly or indirectly) from analyzer::Analyzer.
*/
#define BRO_PLUGIN_ANALYZER(tag, cls) \
AddComponent(new ::analyzer::Component(tag, ::analyzer::cls::InstantiateAnalyzer));
/**
* Defines a component implementing a file analyzer.
*
* @param tag A string with the analyzer's tag. This must be unique across
* all loaded analyzers and will translate into a corresponding \c ANALYZER_*
* constant at the script-layer.
*
* @param cls The class that implements the analyzer. It must be derived
* (directly or indirectly) from file_analysis::Analyzer.
*/
#define BRO_PLUGIN_FILE_ANALYZER(tag, cls) \
AddComponent(new ::file_analysis::Component(tag, ::file_analysis::cls::Instantiate));
/**
* Defines a component implementing a protocol analyzer class that will
* not be instantiated dynamically. This is for two use-cases: (1) abstract
* analyzer base classes that aren't instantiated directly; and (2) analyzers
* that are only instantiated explicitly by other Bro components, but not
* dynamically by the manager based on their tag (e.g., the ZIP analyzer is
* attached by the HTTP analyzer when corresponding content is found).
*
* @param tag A string with the analyzer's tag. This must be unique across
* all loaded analyzers and will translate into a corresponding \c ANALYZER_*
* constant at the script-layer.
*/
#define BRO_PLUGIN_ANALYZER_BARE(tag) \
AddComponent(new ::analyzer::Component(tag, 0));
/**
* Defines a component implementating a support analyzer.
*
* @param tag A string with the analyzer's tag. This must be unique across
* all loaded analyzers and will translate into a corresponding \c ANALYZER_*
* constant at the script-layer.
*/
#define BRO_PLUGIN_SUPPORT_ANALYZER(tag) \
AddComponent(new ::analyzer::Component(tag, 0));
#endif

View file

@ -83,8 +83,13 @@ void Manager::SearchDynamicPlugins(const std::string& dir)
if ( name.empty() )
reporter->FatalError("empty plugin magic file %s", magic.c_str());
// Record it, so that we can later activate it.
if ( dynamic_plugins.find(name) != dynamic_plugins.end() )
{
DBG_LOG(DBG_PLUGINS, "Found already known plugin %s in %s, ignoring", name.c_str(), dir.c_str());
return;
}
// Record it, so that we can later activate it.
dynamic_plugins.insert(std::make_pair(name, dir));
DBG_LOG(DBG_PLUGINS, "Found plugin %s in %s", name.c_str(), dir.c_str());
@ -124,6 +129,8 @@ void Manager::SearchDynamicPlugins(const std::string& dir)
if ( st.st_mode & S_IFDIR )
SearchDynamicPlugins(path);
}
closedir(d);
}
bool Manager::ActivateDynamicPluginInternal(const std::string& name)
@ -202,6 +209,9 @@ bool Manager::ActivateDynamicPluginInternal(const std::string& name)
if ( ! current_plugin )
reporter->FatalError("load plugin library %s did not instantiate a plugin", path);
current_plugin->SetDynamic(true);
current_plugin->DoConfigure();
// We execute the pre-script initialization here; this in
// fact could be *during* script initialization if we got
// triggered via @load-plugin.
@ -267,7 +277,7 @@ static bool plugin_cmp(const Plugin* a, const Plugin* b)
return a->Name() < b->Name();
}
bool Manager::RegisterPlugin(Plugin *plugin)
void Manager::RegisterPlugin(Plugin *plugin)
{
Manager::PluginsInternal()->push_back(plugin);
@ -279,7 +289,18 @@ bool Manager::RegisterPlugin(Plugin *plugin)
PluginsInternal()->sort(plugin_cmp);
current_plugin = plugin;
return true;
}
void Manager::RegisterBifFile(const char* plugin, bif_init_func c)
{
bif_init_func_map* bifs = BifFilesInternal();
bif_init_func_map::iterator i = bifs->find(plugin);
if ( i == bifs->end() )
i = bifs->insert(std::make_pair(std::string(plugin), new bif_init_func_list())).first;
i->second->push_back(c);
}
void Manager::InitPreScript()
@ -289,6 +310,7 @@ void Manager::InitPreScript()
for ( plugin_list::iterator i = Manager::PluginsInternal()->begin(); i != Manager::PluginsInternal()->end(); i++ )
{
Plugin* plugin = *i;
plugin->DoConfigure();
plugin->InitPreScript();
}
@ -297,8 +319,18 @@ void Manager::InitPreScript()
void Manager::InitBifs()
{
bif_init_func_map* bifs = BifFilesInternal();
for ( plugin_list::iterator i = Manager::PluginsInternal()->begin(); i != Manager::PluginsInternal()->end(); i++ )
(*i)->InitBifs();
{
bif_init_func_map::const_iterator b = bifs->find((*i)->Name());
if ( b != bifs->end() )
{
for ( bif_init_func_list::const_iterator j = b->second->begin(); j != b->second->end(); ++j )
(**j)(*i);
}
}
}
void Manager::InitPostScript()
@ -339,6 +371,16 @@ Manager::plugin_list* Manager::PluginsInternal()
return plugins;
}
Manager::bif_init_func_map* Manager::BifFilesInternal()
{
static bif_init_func_map* bifs = 0;
if ( ! bifs )
bifs = new bif_init_func_map;
return bifs;
}
static bool hook_cmp(std::pair<int, Plugin*> a, std::pair<int, Plugin*> b)
{
if ( a.first == b.first )

View file

@ -20,12 +20,14 @@ namespace plugin {
#define PLUGIN_HOOK_VOID(hook, method_call) \
if ( plugin_mgr->HavePluginForHook(plugin::hook) ) plugin_mgr->method_call;
/**
* A singleton object managing all plugins.
*/
class Manager
{
public:
typedef void (*bif_init_func)(Plugin *);
typedef std::list<Plugin*> plugin_list;
typedef Plugin::component_list component_list;
@ -218,7 +220,12 @@ public:
* ownership, yet assumes the pointer will stay valid at least until
* the Manager is destroyed.
*/
static bool RegisterPlugin(Plugin* plugin);
static void RegisterPlugin(Plugin* plugin);
/**
* Internal method that registers a bif file's init function for a plugin.
*/
static void RegisterBifFile(const char* plugin, bif_init_func c);
private:
bool ActivateDynamicPluginInternal(const std::string& name);
@ -251,6 +258,14 @@ private:
// This is a static method so that plugins can register themselves
// even before the manager exists.
static plugin_list* PluginsInternal();
typedef std::list<bif_init_func> bif_init_func_list;
typedef std::map<std::string, bif_init_func_list*> bif_init_func_map;
// Returns a modifiable map of all bif files. This is a static method
// so that plugins can register their bifs even before the manager
// exists.
static bif_init_func_map* BifFilesInternal();
};
template<class T>
@ -274,6 +289,17 @@ std::list<T *> Manager::Components() const
return result;
}
/**
* Internal class used by bifcl-generated code to register its init functions at runtime.
*/
class __RegisterBif {
public:
__RegisterBif(const char* plugin, Manager::bif_init_func init)
{
Manager::RegisterBifFile(plugin, init);
}
};
}
/**

View file

@ -55,16 +55,7 @@ BifItem::~BifItem()
Plugin::Plugin()
{
name = "<NAME-NOT-SET>";
description = "";
// These will be reset by the BRO_PLUGIN_* macros.
version = -9999;
api_version = -9999;
dynamic = false;
base_dir = "";
sopath = "";
Manager::RegisterPlugin(this);
}
@ -73,39 +64,29 @@ Plugin::~Plugin()
Done();
}
const std::string& Plugin::Name() const
void Plugin::DoConfigure()
{
return name;
config = Configure();
}
void Plugin::SetName(const std::string& arg_name)
const std::string& Plugin::Name() const
{
name = arg_name;
return config.name;
}
const std::string& Plugin::Description() const
{
return description;
return config.description;
}
void Plugin::SetDescription(const std::string& arg_description)
VersionNumber Plugin::Version() const
{
description = arg_description;
}
int Plugin::Version() const
{
return dynamic ? version : 0;
}
void Plugin::SetVersion(int arg_version)
{
version = arg_version;
return config.version;
}
int Plugin::APIVersion() const
{
return api_version;
return config.api_version;
}
bool Plugin::DynamicPlugin() const
@ -123,22 +104,17 @@ const std::string& Plugin::PluginPath() const
return sopath;
}
void Plugin::SetAPIVersion(int arg_version)
{
api_version = arg_version;
}
void Plugin::SetDynamicPlugin(bool arg_dynamic)
{
dynamic = arg_dynamic;
}
void Plugin::SetPluginLocation(const std::string& arg_dir, const std::string& arg_sopath)
{
base_dir = arg_dir;
sopath = arg_sopath;
}
void Plugin::SetDynamic(bool is_dynamic)
{
dynamic = is_dynamic;
}
void Plugin::InitPreScript()
{
}
@ -147,12 +123,6 @@ void Plugin::InitPostScript()
{
}
void Plugin::InitBifs()
{
for ( bif_init_func_list::const_iterator f = bif_inits.begin(); f != bif_inits.end(); f++ )
(**f)(this);
}
Plugin::bif_item_list Plugin::BifItems() const
{
bif_item_list l1 = bif_items;
@ -193,11 +163,6 @@ bool Plugin::LoadBroFile(const std::string& file)
return true;
}
void Plugin::__AddBifInitFunction(bif_init_func c)
{
bif_inits.push_back(c);
}
void Plugin::AddBifItem(const std::string& name, BifItem::Type type)
{
BifItem bi(name, (BifItem::Type)type);
@ -254,24 +219,28 @@ void Plugin::HookUpdateNetworkTime(double network_time)
void Plugin::Describe(ODesc* d) const
{
d->Add("Plugin: ");
d->Add(name);
d->Add(config.name);
if ( description.size() )
if ( config.description.size() )
{
d->Add(" - ");
d->Add(description);
d->Add(config.description);
}
if ( dynamic )
{
if ( version > 0 )
d->Add(" (dynamic, ");
if ( config.version )
{
d->Add(" (dynamic, version ");
d->Add(version);
d->Add("version ");
d->Add(config.version.major);
d->Add(".");
d->Add(config.version.minor);
d->Add(")");
}
else
d->Add(" (version not set)");
d->Add("no version information)");
}
else

View file

@ -6,7 +6,9 @@
#include <list>
#include <string>
#include "Macros.h"
#include "config.h"
#include "analyzer/Component.h"
#include "file_analysis/Component.h"
class ODesc;
class Func;
@ -14,8 +16,11 @@ class Event;
namespace plugin {
#define BRO_PLUGIN_API_VERSION 2
class Manager;
class Component;
class Plugin;
/**
* Hook types that a plugin may define. Each label maps to the corresponding
@ -32,6 +37,45 @@ enum HookType {
NUM_HOOKS,
};
/**
* Helper class to capture a plugin's version. A boolean operator evaluates
* to true if the version has been set.
*/
struct VersionNumber {
int major; //< Major version number;
int minor; //< Minor version number;
VersionNumber() { major = minor = -1; }
operator bool() const { return major >= 0 && minor >= 0; }
};
/**
* A class defining a plugin's static configuration parameters.
*/
class Configuration {
public:
std::string name; //< The plugin's name, including a namespace. Mandatory.
std::string description; //< A short textual description of the plugin. Mandatory.
VersionNumber version; //< THe plugin's version. Optional.
Configuration();
private:
friend class Plugin;
int api_version; // Current BRO_PLUGIN_API_VERSION. Automatically set.
};
// Note we inline this method here so that when plugins create an instance,
// *their* defaults will be used for the internal fields.
inline Configuration::Configuration()
{
name = "";
description = "";
api_version = BRO_PLUGIN_API_VERSION;
}
/**
* A class describing an item defined in \c *.bif file.
*/
@ -105,7 +149,7 @@ private:
* Note that a plugin needs to explicitly register all the functionality it
* provides. For components, it needs to call AddComponent(); for BiFs
* AddBifItem(); and for hooks EnableHook() and then also implemennt the
* corresponding virtual method).
* corresponding virtual methods).
*
*/
class Plugin {
@ -113,8 +157,6 @@ public:
typedef std::list<Component *> component_list;
typedef std::list<BifItem> bif_item_list;
typedef std::list<std::pair<HookType, int> > hook_list;
typedef std::list<std::pair<std::string, int> > bif_init_func_result;
typedef void (*bif_init_func)(Plugin *);
/**
* Constructor.
@ -141,7 +183,7 @@ public:
* dynamically compiled plugins; for statically compiled ones, this
* will always return 0.
*/
int Version() const;
VersionNumber Version() const;
/**
* Returns true if this is a dynamically linked in plugin.
@ -180,6 +222,17 @@ public:
*/
bif_item_list BifItems() const;
/**
* A function called when the plugin is instantiated to query basic
* configuration parameters.
*
* The plugin must override this method and return a suitably
* initialized configuration object.
*
* @return A configuration describing the plugin.
*/
virtual Configuration Configure() { return Configuration(); } // TODO: Change to abstract method.
/**
* First-stage initialization of the plugin called early during Bro's
* startup, before scripts are parsed. This can be overridden by
@ -244,15 +297,15 @@ public:
*/
bool LoadBroFile(const std::string& file);
/**
* Internal function adding an entry point for registering
* auto-generated BiFs.
*/
void __AddBifInitFunction(bif_init_func c);
protected:
friend class Manager;
/**
* Intializes the plugin's configutation. Called by the manager
* before anything else.
*/
void DoConfigure();
/**
* Registers and activates a component.
*
@ -388,59 +441,6 @@ protected:
// Methods that are used internally primarily.
/**
* Sets the plugins name.
*
* This is used primarily internally; plugin code should pass the
* name via the BRO_PLUGIN_BEGIN macro instead.
*
* @param name The name. Makes a copy internally.
*/
void SetName(const std::string& name);
/**
* Sets the plugin's textual description.
*
* This is used primarily internally; plugin code should pass the
* name via the BRO_PLUGIN_DESCRIPTION macro instead.
*
* @param name The description. Makes a copy internally.
*/
void SetDescription(const std::string& descr);
/**
* Sets the plugin's version.
*
* This is used primarily internally; plugin code should pass the
* name via the BRO_PLUGIN_VERSION macro instead.
*
* @param version The version.
*/
void SetVersion(int version);
/**
* Sets the API version the plugin requires.
* BRO_PLUGIN_VERSION_BUILTIN indicates that it's a plugin linked in
* statically.
*
* This is used primarily internally; plugins automatically set
* either API version of the Bro they are compiled dynamically for,
* or BRO_PLUGIN_VERSION_BUILTIN if they are linked in statically.
*
* @param version The version.
*/
void SetAPIVersion(int version);
/**
* Marks the plugin as statically or dynamically linked.
*
* This is used primarily internally; plugins automatically set this
* based on which way they are compiled.
*
* @param dynamic True if this is a dynamically linked plugin.
*/
void SetDynamicPlugin(bool dynamic);
/**
* Sets the base directory and shared library path from which the
* plugin was loaded.
@ -456,26 +456,25 @@ protected:
*/
void SetPluginLocation(const std::string& dir, const std::string& sopath);
private:
/**
* Initializes the BiF items added with AddBifItem(). Internal method
* that will be called by the manager at the right time.
* Marks the plugin as dynamically loaded.
*
* This is used primarily internally; plugins will have this called
* by the manager.
*
* @param is_dynamic True if it's a dynamically loaded module.
*/
void InitBifs();
void SetDynamic(bool is_dynamic);
typedef std::list<bif_init_func> bif_init_func_list;
private:
Configuration config;
std::string name;
std::string description;
std::string base_dir;
std::string sopath;
int version;
int api_version;
bool dynamic;
std::string base_dir; // The plugin's base directory.
std::string sopath; // For dynamic plugins, the full path to the shared library.
bool dynamic; // True if a dynamic plugin.
component_list components;
bif_item_list bif_items;
bif_init_func_list bif_inits;
};
}

View file

@ -1,4 +1,4 @@
Plugin: Demo::Foo - A Foo test analyzer (dynamic, version 1)
Plugin: Demo::Foo - A Foo test analyzer (dynamic, version 1.0)
[Analyzer] Foo (ANALYZER_FOO, enabled)
[Event] foo_message

View file

@ -1,4 +1,4 @@
Plugin: Demo::Foo - <Insert brief description of plugin> (dynamic, version 1)
Plugin: Demo::Foo - Caesar cipher rotating a string's characters by 13 places. (dynamic, version 1.0)
[Event] plugin_event
[Function] hello_plugin_world

View file

@ -10,6 +10,7 @@ PartFinalizer = btest-diff-rst
BROPATH=`bash -c %(testbase)s/../../build/bro-path-dev`
BROMAGIC=%(testbase)s/../../magic/database
BRO_SEED_FILE=%(testbase)s/random.seed
BRO_PLUGIN_PATH=
TZ=UTC
LC_ALL=C
BTEST_PATH=%(testbase)s/../../aux/btest

View file

@ -19,7 +19,7 @@ public:
virtual void Undelivered(int seq, int len, bool orig);
virtual void EndpointEOF(bool is_orig);
static analyzer::Analyzer* InstantiateAnalyzer(Connection* conn)
static analyzer::Analyzer* Instantiate(Connection* conn)
{ return new Foo_Analyzer(conn); }
protected:

View file

@ -3,10 +3,23 @@
#include "Foo.h"
BRO_PLUGIN_BEGIN(Demo, Foo)
BRO_PLUGIN_VERSION(1);
BRO_PLUGIN_DESCRIPTION("A Foo test analyzer");
BRO_PLUGIN_ANALYZER("Foo", Foo::Foo_Analyzer);
BRO_PLUGIN_BIF_FILE(events);
BRO_PLUGIN_BIF_FILE(functions);
BRO_PLUGIN_END
namespace plugin {
namespace Demo_Foo {
class Plugin : public plugin::Plugin {
public:
plugin::Configuration Configure()
{
AddComponent(new ::analyzer::Component("Foo", ::analyzer::Foo::Foo_Analyzer::Instantiate));
plugin::Configuration config;
config.name = "Demo::Foo";
config.description = "A Foo test analyzer";
config.version.major = 1;
config.version.minor = 0;
return config;
}
} plugin;
}
}