Updates of the dynamic plugin code.

Includes:

    - Cleanup of the plugin API, in particular generally changing
      const char* to std::string

    - Renaming environment variable BRO_PLUGINS to BRO_PLUGIN_PATH,
      defaulting to <prefix>/lib/bro/plugins

    - Reworking how dynamic plugins are searched and activated. See
      doc/devel/plugins.rst for details.

    - New @load-plugin directive to explicitly activate a plugin

    - Support for Darwin. (Linux untested right now)

    - The init-plugin updates come with support for "make test", "make
      sdist", and "make bdist" (see how-to).

    - Test updates.

Notes: The new hook mechanism, which allows plugins to hook into Bro's
core a well-defined points, is still essentially untested.
This commit is contained in:
Robin Sommer 2013-12-16 10:08:38 -08:00
parent 987452beff
commit a80dd10215
18 changed files with 257 additions and 143 deletions

View file

@ -22,10 +22,11 @@ set(BRO_SCRIPT_SOURCE_PATH ${CMAKE_CURRENT_SOURCE_DIR}/scripts)
get_filename_component(BRO_SCRIPT_INSTALL_PATH ${BRO_SCRIPT_INSTALL_PATH}
ABSOLUTE)
set(BRO_PLUGIN_INSTALL_PATH ${BRO_ROOT_DIR}/lib/bro/plugins)
set(BRO_PLUGIN_INSTALL_PATH ${BRO_ROOT_DIR}/lib/bro/plugins CACHE STRING "Installation path for plugins" FORCE)
set(BRO_MAGIC_INSTALL_PATH ${BRO_ROOT_DIR}/share/bro/magic)
set(BRO_MAGIC_SOURCE_PATH ${CMAKE_CURRENT_SOURCE_DIR}/magic/database)
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"

@ -1 +1 @@
Subproject commit 715937ad72d9158d8c3142f81ee7005601d75db8
Subproject commit f89d870437dbbbb107fd29f1085aef070e3bf373

2
cmake

@ -1 +1 @@
Subproject commit 6eb4cbfbc75f0bd13e247150b19932905a85e10c
Subproject commit 763b6d2574294e62f116e167c564a6292206a655

View file

@ -214,7 +214,7 @@
#define HOST_ARCHITECTURE "@HOST_ARCHITECTURE@"
/* String with extension of dynamic libraries (e.g., ".so") */
#define SHARED_LIBRARY_SUFFIX "@CMAKE_SHARED_LIBRARY_SUFFIX@"
#define DYNAMIC_PLUGIN_SUFFIX "@CMAKE_SHARED_MODULE_SUFFIX@"
/* True if we're building outside of the main Bro source code tree. */
#ifndef BRO_PLUGIN_INTERNAL_BUILD

View file

@ -467,7 +467,7 @@ static void WritePluginSectionHeading(FILE* f, const plugin::Plugin* p)
fprintf(f, "-");
fprintf(f, "\n\n");
fprintf(f, "%s\n\n", p->Description());
fprintf(f, "%s\n\n", p->Description().c_str());
}
static void WriteAnalyzerComponent(FILE* f, const analyzer::Component* c)
@ -568,7 +568,7 @@ static void WritePluginBifItems(FILE* f, const plugin::Plugin* p,
if ( o )
o->WriteReST(f);
else
reporter->Warning("No docs for ID: %s\n", it->GetID());
reporter->Warning("No docs for ID: %s\n", it->GetID().c_str());
}
}

View file

@ -389,6 +389,9 @@ install(TARGETS bro DESTINATION bin)
set(BRO_EXE bro
CACHE STRING "Bro executable binary" FORCE)
set(BRO_EXE_PATH ${CMAKE_CURRENT_BINARY_DIR}/bro
CACHE STRING "Path to Bro executable binary" FORCE)
# Target to create all the autogenerated files.
add_custom_target(generate_outputs_stage1)
add_dependencies(generate_outputs_stage1 ${bro_ALL_GENERATED_OUTPUTS})

View file

@ -117,7 +117,7 @@ void DebugLogger::Log(const plugin::Plugin& plugin, const char* fmt, ...)
return;
fprintf(file, "%17.06f/%17.06f [plugin %s] ",
network_time, current_time(true), plugin.Name());
network_time, current_time(true), plugin.Name().c_str());
va_list ap;
va_start(ap, fmt);

View file

@ -15,6 +15,7 @@ extern int brolex();
extern char last_tok[128];
extern void add_input_file(const char* file);
extern void add_input_file_at_front(const char* file);
// Adds the substrings (using the given delimiter) in a string to the
// given namelist.

View file

@ -223,7 +223,7 @@ void usage()
fprintf(stderr, " $BROPATH | file search path (%s)\n", bro_path().c_str());
fprintf(stderr, " $BROMAGIC | libmagic mime magic database search path (%s)\n", bro_magic_path());
fprintf(stderr, " $BRO_PLUGINS | plugin search path (%s)\n", bro_plugin_path());
fprintf(stderr, " $BRO_PLUGIN_PATH | plugin search path (%s)\n", bro_plugin_path());
fprintf(stderr, " $BRO_PREFIXES | prefix list (%s)\n", bro_prefixes().c_str());
fprintf(stderr, " $BRO_DNS_FAKE | disable DNS lookups (%s)\n", bro_dns_fake());
fprintf(stderr, " $BRO_SEED_FILE | file to load seeds from (not set)\n");
@ -820,7 +820,7 @@ int main(int argc, char** argv)
if ( ! bare_mode )
add_input_file("base/init-default.bro");
plugin_mgr->LoadPluginsFrom(bro_plugin_path());
plugin_mgr->SearchDynamicPlugins(bro_plugin_path());
if ( optind == argc &&
read_files.length() == 0 && flow_files.length() == 0 &&
@ -860,6 +860,9 @@ int main(int argc, char** argv)
analyzer_mgr->InitPreScript();
file_mgr->InitPreScript();
if ( ! bare_mode )
plugin_mgr->ActivateAllDynamicPlugins();
if ( events_file )
event_player = new EventPlayer(events_file);
@ -896,13 +899,14 @@ int main(int argc, char** argv)
if ( reporter->Errors() > 0 )
exit(1);
plugin_mgr->InitPostScript();
if ( print_plugins )
{
show_plugins(print_plugins);
exit(1);
}
plugin_mgr->InitPostScript();
analyzer_mgr->InitPostScript();
file_mgr->InitPostScript();

View file

@ -1,6 +1,7 @@
// See the file "COPYING" in the main distribution directory for copyright.
#include <sstream>
#include <fstream>
#include <dirent.h>
#include <glob.h>
#include <dlfcn.h>
@ -15,6 +16,7 @@
using namespace plugin;
Plugin* Manager::current_plugin = 0;
string Manager::current_dir;
string Manager::current_sopath;
@ -37,7 +39,7 @@ Manager::~Manager()
delete [] hooks;
}
void Manager::LoadPluginsFrom(const string& dir)
void Manager::SearchDynamicPlugins(const std::string& dir)
{
assert(! init);
@ -51,7 +53,7 @@ void Manager::LoadPluginsFrom(const string& dir)
std::string d;
while ( std::getline(s, d, ':') )
LoadPluginsFrom(d);
SearchDynamicPlugins(d);
return;
}
@ -62,12 +64,34 @@ void Manager::LoadPluginsFrom(const string& dir)
return;
}
int rc = LoadPlugin(dir);
// Check if it's a plugin dirctory.
if ( rc >= 0 )
const std::string magic = dir + "/__bro_plugin__";
if ( is_file(magic) )
{
// It's a plugin, get it's name.
std::ifstream in(magic);
if ( in.fail() )
reporter->FatalError("cannot open plugin magic file %s", magic.c_str());
std::string name;
std::getline(in, name);
strstrip(name);
if ( name.empty() )
reporter->FatalError("empty plugin magic file %s", magic.c_str());
// 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());
return;
}
DBG_LOG(DBG_PLUGINS, "Searching directory %s recursively for plugins", dir.c_str());
// No plugin here, traverse subirectories.
DIR* d = opendir(dir.c_str());
@ -98,22 +122,33 @@ void Manager::LoadPluginsFrom(const string& dir)
}
if ( st.st_mode & S_IFDIR )
LoadPluginsFrom(path);
SearchDynamicPlugins(path);
}
}
int Manager::LoadPlugin(const std::string& dir)
bool Manager::ActivateDynamicPluginInternal(const std::string& name)
{
assert(! init);
dynamic_plugin_map::iterator m = dynamic_plugins.find(name);
// Check if it's a plugin dirctory.
if ( ! is_file(dir + "/__bro_plugin__") )
return -1;
if ( m == dynamic_plugins.end() )
{
reporter->Error("plugin %s is not available", name.c_str());
return false;
}
DBG_LOG(DBG_PLUGINS, "Loading plugin from %s", dir.c_str());
std::string dir = m->second + "/";
if ( dir.empty() )
{
// That's our marker that we have already activated this
// plugin. Silently ignore the new request.
return true;
}
DBG_LOG(DBG_PLUGINS, "Activating plugin %s", name.c_str());
// Add the "scripts" and "bif" directories to BROPATH.
string scripts = dir + "/scripts";
std::string scripts = dir + "scripts";
if ( is_dir(scripts) )
{
@ -121,44 +156,27 @@ int Manager::LoadPlugin(const std::string& dir)
add_to_bro_path(scripts);
}
string bif = dir + "/bif";
// Load {bif,scripts}/__load__.bro automatically.
if ( is_dir(bif) )
{
DBG_LOG(DBG_PLUGINS, " Adding %s to BROPATH", bif.c_str());
add_to_bro_path(bif);
}
// Load dylib/scripts/__load__.bro automatically.
string dyinit = dir + "/dylib/scripts/__load__.bro";
if ( is_file(dyinit) )
{
DBG_LOG(DBG_PLUGINS, " Adding %s for loading", dyinit.c_str());
add_input_file(dyinit.c_str());
}
// Load scripts/__load__.bro automatically.
string init = scripts + "/__load__.bro";
string init = dir + "lib/bif/__load__.bro";
if ( is_file(init) )
{
DBG_LOG(DBG_PLUGINS, " Adding %s for loading", init.c_str());
add_input_file(init.c_str());
DBG_LOG(DBG_PLUGINS, " Loading %s", init.c_str());
scripts_to_load.push_back(init);
}
// Load bif/__load__.bro automatically.
init = bif + "/__load__.bro";
init = dir + "scripts/__load__.bro";
if ( is_file(init) )
{
DBG_LOG(DBG_PLUGINS, " Adding %s for loading", init.c_str());
add_input_file(init.c_str());
DBG_LOG(DBG_PLUGINS, " Loading %s", init.c_str());
scripts_to_load.push_back(init);
}
// Load shared libraries.
string dypattern = dir + "/dylib/*." + HOST_ARCHITECTURE + SHARED_LIBRARY_SUFFIX;
string dypattern = dir + "/lib/*." + HOST_ARCHITECTURE + DYNAMIC_PLUGIN_SUFFIX;
DBG_LOG(DBG_PLUGINS, " Searching for shared libraries %s", dypattern.c_str());
@ -170,11 +188,10 @@ int Manager::LoadPlugin(const std::string& dir)
{
const char* path = gl.gl_pathv[i];
current_plugin = 0;
current_dir = dir;
current_sopath = path;
void* hdl = dlopen(path, RTLD_LAZY | RTLD_GLOBAL);
current_dir.clear();
current_sopath.clear();
if ( ! hdl )
{
@ -182,6 +199,24 @@ int Manager::LoadPlugin(const std::string& dir)
reporter->FatalError("cannot load plugin library %s: %s", path, err ? err : "<unknown error>");
}
if ( ! current_plugin )
reporter->FatalError("load plugin library %s did not instantiate a plugin", path);
// We execute the pre-script initialization here; this in
// fact could be *during* script initialization if we got
// triggered via @load-plugin.
current_plugin->InitPreScript();
// Make sure the name the plugin reports is consistent with
// what we expect from its magic file.
if ( string(current_plugin->Name()) != name )
reporter->FatalError("inconsistent plugin name: %s vs %s",
current_plugin->Name().c_str(), name.c_str());
current_dir.clear();
current_sopath.clear();
current_plugin = 0;
DBG_LOG(DBG_PLUGINS, " Loaded %s", path);
}
}
@ -189,10 +224,42 @@ int Manager::LoadPlugin(const std::string& dir)
else
{
DBG_LOG(DBG_PLUGINS, " No shared library found");
return 1;
}
return 1;
// Mark this plugin as activated by clearing the path.
m->second.clear();
return true;
}
bool Manager::ActivateDynamicPlugin(const std::string& name)
{
if ( ! ActivateDynamicPluginInternal(name) )
return false;
UpdateInputFiles();
return true;
}
bool Manager::ActivateAllDynamicPlugins()
{
for ( dynamic_plugin_map::const_iterator i = dynamic_plugins.begin();
i != dynamic_plugins.end(); i++ )
{
if ( ! ActivateDynamicPluginInternal(i->first) )
return false;
}
UpdateInputFiles();
return true;
}
void Manager::UpdateInputFiles()
{
for ( file_list::const_reverse_iterator i = scripts_to_load.rbegin();
i != scripts_to_load.rend(); i++ )
add_input_file_at_front((*i).c_str());
}
static bool plugin_cmp(const Plugin* a, const Plugin* b)
@ -205,11 +272,13 @@ bool Manager::RegisterPlugin(Plugin *plugin)
Manager::PluginsInternal()->push_back(plugin);
if ( current_dir.size() && current_sopath.size() )
// A dynamic plugin, record its location.
plugin->SetPluginLocation(current_dir.c_str(), current_sopath.c_str());
// Sort plugins by name to make sure we have a deterministic order.
PluginsInternal()->sort(plugin_cmp);
current_plugin = plugin;
return true;
}
@ -220,7 +289,6 @@ void Manager::InitPreScript()
for ( plugin_list::iterator i = Manager::PluginsInternal()->begin(); i != Manager::PluginsInternal()->end(); i++ )
{
Plugin* plugin = *i;
plugin->InitPreScript();
}
@ -333,7 +401,7 @@ void Manager::DisableHook(HookType hook, Plugin* plugin)
}
}
int Manager::HookLoadFile(const char* file)
int Manager::HookLoadFile(const string& file)
{
hook_list* l = hooks[HOOK_LOAD_FILE];

View file

@ -40,17 +40,41 @@ public:
virtual ~Manager();
/**
* Loads all plugins dynamically from a set of directories. Multiple
* directories are split by ':'. If a directory does not contain a
* plugin itself, the method searches for plugins recursively. For
* plugins found, the method loads the plugin's shared library and
* makes its scripts available to the interpreter.
* Searches a set of directories for plugins. If a specificed
* directory does not contain a plugin itself, the method searches
* for plugins recursively. For plugins found, the method makes them
* available for later activation via ActivatePlugin().
*
* This must be called only before InitPluginsPreScript().
*
* @param dir The directory to search for plugins.
* @param dir The directory to search for plugins. Multiple
* directories are split by ':'.
*/
void LoadPluginsFrom(const std::string& dir);
void SearchDynamicPlugins(const std::string& dir);
/**
* Activates a plugin that SearchPlugins() has previously discovered.
* Activing a plugin involved loading its dynamic module, making its
* bifs available, and adding its script paths to BROPATH.
*
* @param name The name of the plugin, as determined previously by
* SearchPlugin().
*
* @return True if the plugin has been loaded successfully.
*
*/
bool ActivateDynamicPlugin(const std::string& name);
/**
* Activates all plugins that SearchPlugins() has previously
* discovered. The effect is the same all calling \a
* ActivePlugin(name) for every plugin.
*
* @return True if all plugins have been loaded successfully. If one
* fail to load, the method stops there without loading any furthers
* and returns false.
*/
bool ActivateAllDynamicPlugins();
/**
* First-stage initializion of the manager. This is called early on
@ -148,7 +172,7 @@ public:
* successfully; 0 if a plugin took over the file but had trouble
* loading it; and -1 if no plugin was interested in the file at all.
*/
virtual int HookLoadFile(const char* file);
virtual int HookLoadFile(const string& file);
/**
* Hook that filters calls to a script function/event/hook.
@ -196,40 +220,37 @@ public:
*/
static bool RegisterPlugin(Plugin* plugin);
protected:
/**
* Loads a plugin dynamically from a given directory. It loads the
* plugin's shared library, and makes its scripts available to the
* interpreter. Different from LoadPluginsFrom() this method does not
* further descend the directory tree recursively to search for
* plugins.
*
* This must be called only before InitPluginsPreScript()
*
* @param file The path to the plugin to load.
*
* @return 0 if there's a plugin in this directory, but there was a
* problem loading it; -1 if there's no plugin at all in this
* directory; 1 if there's a plugin in this directory and we loaded
* it successfully.
*/
int LoadPlugin(const std::string& dir);
private:
bool ActivateDynamicPluginInternal(const std::string& name);
void UpdateInputFiles();
// All found dynamic plugins, mapping their names to base directory.
typedef std::map<std::string, std::string> dynamic_plugin_map;
dynamic_plugin_map dynamic_plugins;
// We buffer scripts to load temporarliy to get them to load in the
// right order.
typedef std::list<std::string> file_list;
file_list scripts_to_load;
bool init;
// A hook list keeps pairs of plugin and priority interested in a
// given hook.
typedef std::list<std::pair<int, Plugin*> > hook_list;
static plugin_list* PluginsInternal();
bool init;
// An array indexed by HookType. An entry is null if there's no hook
// of that type enabled.
hook_list** hooks;
static Plugin* current_plugin;
static string current_dir;
static string current_sopath;
// Returns a modifiable list of all plugins, both static and dynamic.
// This is a static method so that plugins can register themselves
// even before the manager exists.
static plugin_list* PluginsInternal();
};
template<class T>

View file

@ -26,15 +26,15 @@ const char* hook_name(HookType h)
return hook_names[int(h)];
}
BifItem::BifItem(const char* arg_id, Type arg_type)
BifItem::BifItem(const std::string& arg_id, Type arg_type)
{
id = copy_string(arg_id);
id = arg_id;
type = arg_type;
}
BifItem::BifItem(const BifItem& other)
{
id = copy_string(other.id);
id = other.id;
type = other.type;
}
@ -42,7 +42,7 @@ BifItem& BifItem::operator=(const BifItem& other)
{
if ( this != &other )
{
id = copy_string(other.id);
id = other.id;
type = other.type;
}
@ -51,20 +51,19 @@ BifItem& BifItem::operator=(const BifItem& other)
BifItem::~BifItem()
{
delete [] id;
}
Plugin::Plugin()
{
name = copy_string("<NAME-NOT-SET>");
description = copy_string("");
name = "<NAME-NOT-SET>";
description = "";
// These will be reset by the BRO_PLUGIN_* macros.
version = -9999;
api_version = -9999;
dynamic = false;
base_dir = 0;
sopath = 0;
base_dir = "";
sopath = "";
Manager::RegisterPlugin(this);
}
@ -72,33 +71,26 @@ Plugin::Plugin()
Plugin::~Plugin()
{
Done();
delete [] name;
delete [] description;
delete [] base_dir;
delete [] sopath;
}
const char* Plugin::Name() const
const std::string& Plugin::Name() const
{
return name;
}
void Plugin::SetName(const char* arg_name)
void Plugin::SetName(const std::string& arg_name)
{
delete [] name;
name = copy_string(arg_name);
name = arg_name;
}
const char* Plugin::Description() const
const std::string& Plugin::Description() const
{
return description;
}
void Plugin::SetDescription(const char* arg_description)
void Plugin::SetDescription(const std::string& arg_description)
{
delete [] description;
description = copy_string(arg_description);
description = arg_description;
}
int Plugin::Version() const
@ -121,12 +113,12 @@ bool Plugin::DynamicPlugin() const
return dynamic;
}
const char* Plugin::PluginDirectory() const
const std::string& Plugin::PluginDirectory() const
{
return base_dir;
}
const char* Plugin::PluginPath() const
const std::string& Plugin::PluginPath() const
{
return sopath;
}
@ -141,12 +133,10 @@ void Plugin::SetDynamicPlugin(bool arg_dynamic)
dynamic = arg_dynamic;
}
void Plugin::SetPluginLocation(const char* arg_dir, const char* arg_sopath)
void Plugin::SetPluginLocation(const std::string& arg_dir, const std::string& arg_sopath)
{
delete [] base_dir;
delete [] sopath;
base_dir = copy_string(arg_dir);
sopath = copy_string(arg_sopath);
base_dir = arg_dir;
sopath = arg_sopath;
}
void Plugin::InitPreScript()
@ -197,9 +187,9 @@ static bool component_cmp(const Component* a, const Component* b)
return a->Name() < b->Name();
}
bool Plugin::LoadBroFile(const char* file)
bool Plugin::LoadBroFile(const std::string& file)
{
::add_input_file(file);
::add_input_file(file.c_str());
return true;
}
@ -208,7 +198,7 @@ void Plugin::__AddBifInitFunction(bif_init_func c)
bif_inits.push_back(c);
}
void Plugin::AddBifItem(const char* name, BifItem::Type type)
void Plugin::AddBifItem(const std::string& name, BifItem::Type type)
{
BifItem bi(name, (BifItem::Type)type);
bif_items.push_back(bi);
@ -238,7 +228,7 @@ void Plugin::DisableHook(HookType hook)
plugin_mgr->DisableHook(hook, this);
}
int Plugin::HookLoadFile(const char* file)
int Plugin::HookLoadFile(const std::string& file)
{
return -1;
}
@ -266,7 +256,7 @@ void Plugin::Describe(ODesc* d) const
d->Add("Plugin: ");
d->Add(name);
if ( description && *description )
if ( description.size() )
{
d->Add(" - ");
d->Add(description);

View file

@ -50,7 +50,7 @@ public:
*
* @param type The type of the item.
*/
BifItem(const char* id, Type type);
BifItem(const std::string& id, Type type);
/**
* Copy constructor.
@ -70,7 +70,7 @@ public:
/**
* Returns the script-level ID as passed into the constructor.
*/
const char* GetID() const { return id; }
const std::string& GetID() const { return id; }
/**
* Returns the type as passed into the constructor.
@ -78,7 +78,7 @@ public:
Type GetType() const { return type; }
private:
const char* id;
std::string id;
Type type;
};
@ -113,7 +113,7 @@ 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<const char*, int> > bif_init_func_result;
typedef std::list<std::pair<std::string, int> > bif_init_func_result;
typedef void (*bif_init_func)(Plugin *);
/**
@ -129,12 +129,12 @@ public:
/**
* Returns the name of the plugin.
*/
const char* Name() const;
const std::string& Name() const;
/**
* Returns a short textual description of the plugin, if provided.
*/
const char* Description() const;
const std::string& Description() const;
/**
* Returns the version of the plugin. Version are only meaningful for
@ -152,13 +152,13 @@ public:
* For dynamic plugins, returns the base directory from which it was
* loaded. For static plugins, returns null.
**/
const char* PluginDirectory() const;
const std::string& PluginDirectory() const;
/**
* For dynamic plugins, returns the full path to the shared library
* from which it was loaded. For static plugins, returns null.
**/
const char* PluginPath() const;
const std::string& PluginPath() const;
/**
* Returns the internal API version that this plugin relies on. Only
@ -225,7 +225,7 @@ public:
*
* @param type The item's type.
*/
void AddBifItem(const char* name, BifItem::Type type);
void AddBifItem(const std::string& name, BifItem::Type type);
/**
* Adds a file to the list of files that Bro loads at startup. This
@ -242,7 +242,7 @@ public:
* @return True if successful (which however may only mean
* "successfully queued").
*/
bool LoadBroFile(const char* file);
bool LoadBroFile(const std::string& file);
/**
* Internal function adding an entry point for registering
@ -324,7 +324,7 @@ protected:
* printed an error message); and -1 if the plugin wasn't interested
* in the file at all.
*/
virtual int HookLoadFile(const char* file);
virtual int HookLoadFile(const std::string& file);
/**
* Hook into executing a script-level function/event/hook. Whenever
@ -396,7 +396,7 @@ protected:
*
* @param name The name. Makes a copy internally.
*/
void SetName(const char* name);
void SetName(const std::string& name);
/**
* Sets the plugin's textual description.
@ -406,7 +406,7 @@ protected:
*
* @param name The description. Makes a copy internally.
*/
void SetDescription(const char* descr);
void SetDescription(const std::string& descr);
/**
* Sets the plugin's version.
@ -454,7 +454,7 @@ protected:
* @param sopath The full path the shared library loaded. The
* functions makes an internal copy of string.
*/
void SetPluginLocation(const char* dir, const char* sopath);
void SetPluginLocation(const std::string& dir, const std::string& sopath);
private:
/**
@ -465,10 +465,10 @@ private:
typedef std::list<bif_init_func> bif_init_func_list;
const char* name;
const char* description;
const char* base_dir;
const char* sopath;
std::string name;
std::string description;
std::string base_dir;
std::string sopath;
int version;
int api_version;
bool dynamic;

View file

@ -407,6 +407,11 @@ when return TOK_WHEN;
new_sig_file);
}
@load-plugin{WS}{ID} {
const char* plugin = skip_whitespace(yytext + 12);
plugin_mgr->ActivateDynamicPlugin(plugin);
}
@unload{WS}{FILE} {
// Skip "@unload".
const char* new_file = skip_whitespace(yytext + 7);
@ -829,6 +834,17 @@ void add_input_file(const char* file)
input_files.append(copy_string(file));
}
void add_input_file_at_front(const char* file)
{
if ( ! file )
reporter->InternalError("empty filename");
if ( ! filename )
(void) load_files(file);
else
input_files.insert(copy_string(file));
}
void add_to_name_list(char* s, char delim, name_list& nl)
{
while ( s )

View file

@ -664,6 +664,13 @@ string strreplace(const string& s, const string& o, const string& n)
return r;
}
std::string strstrip(std::string s)
{
s.erase(s.begin(), std::find_if(s.begin(), s.end(), std::not1(std::ptr_fun<int, int>(std::isspace))));
s.erase(std::find_if(s.rbegin(), s.rend(), std::not1(std::ptr_fun<int, int>(std::isspace))).base(), s.end());
return s;
}
int hmac_key_set = 0;
uint8 shared_hmac_md5_key[16];
@ -942,7 +949,7 @@ const char* bro_magic_path()
const char* bro_plugin_path()
{
const char* path = getenv("BRO_PLUGINS");
const char* path = getenv("BRO_PLUGIN_PATH");
if ( ! path )
path = BRO_PLUGIN_INSTALL_PATH;

View file

@ -155,6 +155,9 @@ bool is_file(const std::string& path);
// Replaces all occurences of *o* in *s* with *n*.
extern std::string strreplace(const std::string& s, const std::string& o, const std::string& n);
// Remove all leading and trainling white space from string.
extern std::string strstrip(std::string s);
extern uint8 shared_hmac_md5_key[16];
extern int hmac_key_set;

View file

@ -1,9 +1,9 @@
# @TEST-EXEC: ${DIST}/aux/bro-aux/plugin-support/init-plugin Demo Foo
# @TEST-EXEC: cp -r %DIR/analyzer-plugin/* .
# @TEST-EXEC: make BRO=${DIST}
# @TEST-EXEC: BROPLUGINS=`pwd` bro -NN | awk '/^Plugin:.*Demo/ {p=1; print; next} /^Plugin:/{p=0} p==1{print}' >>output
# @TEST-EXEC: BRO_PLUGIN_PATH=`pwd` bro -NN | awk '/^Plugin:.*Demo/ {p=1; print; next} /^Plugin:/{p=0} p==1{print}' >>output
# @TEST-EXEC: echo === >>output
# @TEST-EXEC: BROPLUGINS=`pwd` bro -r $TRACES/port4242.trace %INPUT >>output
# @TEST-EXEC: BRO_PLUGIN_PATH=`pwd` bro -r $TRACES/port4242.trace %INPUT >>output
# @TEST-EXEC: btest-diff output
event foo_message(c: connection, data: string)

View file

@ -1,11 +1,11 @@
# @TEST-EXEC: ${DIST}/aux/bro-aux/plugin-support/init-plugin Demo Foo
# @TEST-EXEC: bash %INPUT
# @TEST-EXEC: make BRO=${DIST}
# @TEST-EXEC: BROPLUGINS=`pwd` bro -NN | awk '/^Plugin:.*Demo/ {p=1; print; next} /^Plugin:/{p=0} p==1{print}' >>output
# @TEST-EXEC: BRO_PLUGIN_PATH=`pwd` bro -NN | awk '/^Plugin:.*Demo/ {p=1; print; next} /^Plugin:/{p=0} p==1{print}' >>output
# @TEST-EXEC: echo === >>output
# @TEST-EXEC: BROPLUGINS=`pwd` bro -r $TRACES/empty.trace >>output
# @TEST-EXEC: BRO_PLUGIN_PATH=`pwd` bro -r $TRACES/empty.trace >>output
# @TEST-EXEC: echo === >>output
# @TEST-EXEC: BROPLUGINS=`pwd` bro demo/foo -r $TRACES/empty.trace >>output
# @TEST-EXEC: BRO_PLUGIN_PATH=`pwd` bro demo/foo -r $TRACES/empty.trace >>output
# @TEST-EXEC: btest-diff output
cat >scripts/__load__.bro <<EOF