mirror of
https://github.com/zeek/zeek.git
synced 2025-10-14 04:28:20 +00:00
Restructuring the plugin API to accomodate hooks.
I got rid of the earlier separate InterpreterPlugin class. Instead Plugin now has a set of virtual methods HookSomething()... that plugins can override. For efficiency purposes, they however need to register first that they are interested in a hook, otherwise the virtual method will never be called. The idea is to extend the set of hooks over time as we figure out what's useful. This is a checkpoint commit that's essentially untested and probably broken. It compiles, though.
This commit is contained in:
parent
555df1e7ea
commit
bda0c29f66
11 changed files with 529 additions and 445 deletions
|
@ -78,8 +78,7 @@ EventMgr::~EventMgr()
|
||||||
|
|
||||||
void EventMgr::QueueEvent(Event* event)
|
void EventMgr::QueueEvent(Event* event)
|
||||||
{
|
{
|
||||||
if ( plugin_mgr->QueueEvent(event) )
|
PLUGIN_HOOK_VOID(HOOK_QUEUE_EVENT, HookQueueEvent(event));
|
||||||
return;
|
|
||||||
|
|
||||||
if ( ! head )
|
if ( ! head )
|
||||||
head = tail = event;
|
head = tail = event;
|
||||||
|
@ -119,7 +118,7 @@ void EventMgr::Drain()
|
||||||
|
|
||||||
SegmentProfiler(segment_logger, "draining-events");
|
SegmentProfiler(segment_logger, "draining-events");
|
||||||
|
|
||||||
plugin_mgr->DrainEvents();
|
PLUGIN_HOOK_VOID(HOOK_DRAIN_EVENTS, HookDrainEvents());
|
||||||
|
|
||||||
draining = true;
|
draining = true;
|
||||||
while ( head )
|
while ( head )
|
||||||
|
|
|
@ -283,7 +283,7 @@ Val* BroFunc::Call(val_list* args, Frame* parent) const
|
||||||
DEBUG_MSG("Function: %s\n", id->Name());
|
DEBUG_MSG("Function: %s\n", id->Name());
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
Val* plugin_result = plugin_mgr->CallFunction(this, args);
|
Val* plugin_result = PLUGIN_HOOK_WITH_RESULT(HOOK_CALL_FUNCTION, HookCallFunction(this, args), 0);
|
||||||
|
|
||||||
if ( plugin_result )
|
if ( plugin_result )
|
||||||
{
|
{
|
||||||
|
|
|
@ -148,7 +148,7 @@ RETSIGTYPE watchdog(int /* signo */)
|
||||||
void net_update_time(double new_network_time)
|
void net_update_time(double new_network_time)
|
||||||
{
|
{
|
||||||
network_time = new_network_time;
|
network_time = new_network_time;
|
||||||
plugin_mgr->UpdateNetworkTime(network_time);
|
PLUGIN_HOOK_VOID(HOOK_UPDATE_NETWORK_TIME, HookUpdateNetworkTime(new_network_time));
|
||||||
}
|
}
|
||||||
|
|
||||||
void net_init(name_list& interfaces, name_list& readfiles,
|
void net_init(name_list& interfaces, name_list& readfiles,
|
||||||
|
|
|
@ -224,7 +224,6 @@ void usage()
|
||||||
fprintf(stderr, " $BROPATH | file search path (%s)\n", bro_path().c_str());
|
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, " $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_PLUGINS | plugin search path (%s)\n", bro_plugin_path());
|
||||||
fprintf(stderr, " $BRO_PREFIXES | prefix list (%s)\n", bro_prefixes());
|
|
||||||
fprintf(stderr, " $BRO_PREFIXES | prefix list (%s)\n", bro_prefixes().c_str());
|
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_DNS_FAKE | disable DNS lookups (%s)\n", bro_dns_fake());
|
||||||
fprintf(stderr, " $BRO_SEED_FILE | file to load seeds from (not set)\n");
|
fprintf(stderr, " $BRO_SEED_FILE | file to load seeds from (not set)\n");
|
||||||
|
|
|
@ -64,6 +64,14 @@
|
||||||
*/
|
*/
|
||||||
#define BRO_PLUGIN_VERSION(v) SetVersion(v)
|
#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
|
* Adds script-level items defined in a \c *.bif file to what the plugin
|
||||||
* provides.
|
* provides.
|
||||||
|
|
|
@ -21,11 +21,20 @@ string Manager::current_sopath;
|
||||||
Manager::Manager()
|
Manager::Manager()
|
||||||
{
|
{
|
||||||
init = false;
|
init = false;
|
||||||
|
hooks = new hook_list*[NUM_HOOKS];
|
||||||
|
|
||||||
|
for ( int i = 0; i < NUM_HOOKS; i++ )
|
||||||
|
hooks[i] = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
Manager::~Manager()
|
Manager::~Manager()
|
||||||
{
|
{
|
||||||
assert(! init);
|
assert(! init);
|
||||||
|
|
||||||
|
for ( int i = 0; i < NUM_HOOKS; i++ )
|
||||||
|
delete hooks[i];
|
||||||
|
|
||||||
|
delete [] hooks;
|
||||||
}
|
}
|
||||||
|
|
||||||
void Manager::LoadPluginsFrom(const string& dir)
|
void Manager::LoadPluginsFrom(const string& dir)
|
||||||
|
@ -204,15 +213,6 @@ bool Manager::RegisterPlugin(Plugin *plugin)
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool interpreter_plugin_cmp(const InterpreterPlugin* a, const InterpreterPlugin* b)
|
|
||||||
{
|
|
||||||
if ( a->Priority() == b->Priority() )
|
|
||||||
return a->Name() < b->Name();
|
|
||||||
|
|
||||||
// Reverse sort.
|
|
||||||
return a->Priority() > b->Priority();
|
|
||||||
}
|
|
||||||
|
|
||||||
void Manager::InitPreScript()
|
void Manager::InitPreScript()
|
||||||
{
|
{
|
||||||
assert(! init);
|
assert(! init);
|
||||||
|
@ -221,26 +221,9 @@ void Manager::InitPreScript()
|
||||||
{
|
{
|
||||||
Plugin* plugin = *i;
|
Plugin* plugin = *i;
|
||||||
|
|
||||||
if ( plugin->PluginType() == Plugin::INTERPRETER )
|
|
||||||
interpreter_plugins.push_back(dynamic_cast<InterpreterPlugin *>(plugin));
|
|
||||||
|
|
||||||
plugin->InitPreScript();
|
plugin->InitPreScript();
|
||||||
|
|
||||||
// Track the file extensions the plugin can handle.
|
|
||||||
std::stringstream ext(plugin->FileExtensions());
|
|
||||||
|
|
||||||
// Split at ":".
|
|
||||||
std::string e;
|
|
||||||
|
|
||||||
while ( std::getline(ext, e, ':') )
|
|
||||||
{
|
|
||||||
DBG_LOG(DBG_PLUGINS, "Plugin %s handles *.%s", plugin->Name(), e.c_str());
|
|
||||||
extensions.insert(std::make_pair(e, plugin));
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
interpreter_plugins.sort(interpreter_plugin_cmp);
|
|
||||||
|
|
||||||
init = true;
|
init = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -273,28 +256,6 @@ void Manager::FinishPlugins()
|
||||||
init = false;
|
init = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
int Manager::TryLoadFile(const char* file)
|
|
||||||
{
|
|
||||||
assert(file);
|
|
||||||
const char* ext = strrchr(file, '.');
|
|
||||||
|
|
||||||
if ( ! ext )
|
|
||||||
return -1;
|
|
||||||
|
|
||||||
extension_map::iterator i = extensions.find(++ext);
|
|
||||||
if ( i == extensions.end() )
|
|
||||||
return -1;
|
|
||||||
|
|
||||||
Plugin* plugin = i->second;
|
|
||||||
|
|
||||||
DBG_LOG(DBG_PLUGINS, "Loading %s with %s", file, plugin->Name());
|
|
||||||
|
|
||||||
if ( i->second->LoadFile(file) )
|
|
||||||
return 1;
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
Manager::plugin_list Manager::Plugins() const
|
Manager::plugin_list Manager::Plugins() const
|
||||||
{
|
{
|
||||||
return *Manager::PluginsInternal();
|
return *Manager::PluginsInternal();
|
||||||
|
@ -310,66 +271,135 @@ Manager::plugin_list* Manager::PluginsInternal()
|
||||||
return plugins;
|
return plugins;
|
||||||
}
|
}
|
||||||
|
|
||||||
Val* Manager::CallFunction(const Func* func, val_list* args) const
|
static bool hook_cmp(std::pair<int, Plugin*> a, std::pair<int, Plugin*> b)
|
||||||
{
|
{
|
||||||
Val* result = 0;
|
if ( a.first == b.first )
|
||||||
|
return a.second->Name() < a.second->Name();
|
||||||
|
|
||||||
for ( interpreter_plugin_list::const_iterator i = interpreter_plugins.begin();
|
// Reverse sort.
|
||||||
i != interpreter_plugins.end() && ! result; i++ )
|
return a.first > b.first;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::list<std::pair<HookType, int> > Manager::HooksEnabledForPlugin(const Plugin* plugin) const
|
||||||
|
{
|
||||||
|
std::list<std::pair<HookType, int> > enabled;
|
||||||
|
|
||||||
|
for ( int i = 0; i < NUM_HOOKS; i++ )
|
||||||
{
|
{
|
||||||
result = (*i)->CallFunction(func, args);
|
hook_list* l = hooks[i];
|
||||||
|
|
||||||
if ( result )
|
if ( ! l )
|
||||||
|
continue;
|
||||||
|
|
||||||
|
for ( hook_list::iterator j = l->begin(); j != l->end(); j++ )
|
||||||
{
|
{
|
||||||
DBG_LOG(DBG_PLUGINS, "Plugin %s replaced call to %s", (*i)->Name(), func->Name());
|
if ( (*j).second == plugin )
|
||||||
return result;
|
enabled.push_back(std::make_pair((HookType)i, (*j).first));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return enabled;
|
||||||
|
}
|
||||||
|
|
||||||
|
void Manager::EnableHook(HookType hook, Plugin* plugin, int prio)
|
||||||
|
{
|
||||||
|
if ( ! hooks[hook] )
|
||||||
|
hooks[hook] = new hook_list;
|
||||||
|
|
||||||
|
hooks[hook]->push_back(std::make_pair(prio, plugin));
|
||||||
|
hooks[hook]->sort(hook_cmp);
|
||||||
|
}
|
||||||
|
|
||||||
|
void Manager::DisableHook(HookType hook, Plugin* plugin)
|
||||||
|
{
|
||||||
|
hook_list* l = hooks[hook];
|
||||||
|
|
||||||
|
if ( ! l )
|
||||||
|
return;
|
||||||
|
|
||||||
|
for ( hook_list::iterator i = l->begin(); i != l->end(); i++ )
|
||||||
|
{
|
||||||
|
if ( (*i).second == plugin )
|
||||||
|
{
|
||||||
|
l->erase(i);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if ( l->empty() )
|
||||||
|
{
|
||||||
|
delete l;
|
||||||
|
hooks[hook] = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
int Manager::HookLoadFile(const char* file)
|
||||||
|
{
|
||||||
|
hook_list* l = hooks[HOOK_LOAD_FILE];
|
||||||
|
|
||||||
|
for ( hook_list::iterator i = l->begin(); l && i != l->end(); i++ )
|
||||||
|
{
|
||||||
|
Plugin* p = (*i).second;
|
||||||
|
|
||||||
|
int rc = p->HookLoadFile(file);
|
||||||
|
|
||||||
|
if ( rc >= 0 )
|
||||||
|
return rc;
|
||||||
|
}
|
||||||
|
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
Val* Manager::HookCallFunction(const Func* func, val_list* args) const
|
||||||
|
{
|
||||||
|
hook_list* l = hooks[HOOK_CALL_FUNCTION];
|
||||||
|
|
||||||
|
for ( hook_list::iterator i = l->begin(); l && i != l->end(); i++ )
|
||||||
|
{
|
||||||
|
Plugin* p = (*i).second;
|
||||||
|
|
||||||
|
Val* v = p->HookCallFunction(func, args);
|
||||||
|
|
||||||
|
if ( v )
|
||||||
|
return v;
|
||||||
|
}
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Manager::QueueEvent(Event* event) const
|
bool Manager::HookQueueEvent(Event* event) const
|
||||||
{
|
{
|
||||||
for ( interpreter_plugin_list::const_iterator i = interpreter_plugins.begin();
|
hook_list* l = hooks[HOOK_QUEUE_EVENT];
|
||||||
i != interpreter_plugins.end(); i++ )
|
|
||||||
|
for ( hook_list::iterator i = l->begin(); l && i != l->end(); i++ )
|
||||||
{
|
{
|
||||||
if ( (*i)->QueueEvent(event) )
|
Plugin* p = (*i).second;
|
||||||
{
|
|
||||||
DBG_LOG(DBG_PLUGINS, "Plugin %s handled queueing of event %s", (*i)->Name(), event->Handler()->Name());
|
if ( p->HookQueueEvent(event) )
|
||||||
return true;
|
return true;
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void Manager::HookDrainEvents() const
|
||||||
void Manager::UpdateNetworkTime(double network_time) const
|
|
||||||
{
|
{
|
||||||
for ( interpreter_plugin_list::const_iterator i = interpreter_plugins.begin();
|
hook_list* l = hooks[HOOK_DRAIN_EVENTS];
|
||||||
i != interpreter_plugins.end(); i++ )
|
|
||||||
(*i)->UpdateNetworkTime(network_time);
|
|
||||||
}
|
|
||||||
|
|
||||||
void Manager::DrainEvents() const
|
for ( hook_list::iterator i = l->begin(); l && i != l->end(); i++ )
|
||||||
{
|
|
||||||
for ( interpreter_plugin_list::const_iterator i = interpreter_plugins.begin();
|
|
||||||
i != interpreter_plugins.end(); i++ )
|
|
||||||
(*i)->DrainEvents();
|
|
||||||
}
|
|
||||||
|
|
||||||
void Manager::DisableInterpreterPlugin(const InterpreterPlugin* plugin)
|
|
||||||
{
|
|
||||||
for ( interpreter_plugin_list::iterator i = interpreter_plugins.begin();
|
|
||||||
i != interpreter_plugins.end(); i++ )
|
|
||||||
{
|
{
|
||||||
if ( *i == plugin )
|
Plugin* p = (*i).second;
|
||||||
{
|
p->HookDrainEvents();
|
||||||
interpreter_plugins.erase(i);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void Manager::HookUpdateNetworkTime(double network_time) const
|
||||||
|
{
|
||||||
|
hook_list* l = hooks[HOOK_UPDATE_NETWORK_TIME];
|
||||||
|
|
||||||
|
for ( hook_list::iterator i = l->begin(); l && i != l->end(); i++ )
|
||||||
|
{
|
||||||
|
Plugin* p = (*i).second;
|
||||||
|
p->HookUpdateNetworkTime(network_time);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -12,6 +12,14 @@
|
||||||
|
|
||||||
namespace plugin {
|
namespace plugin {
|
||||||
|
|
||||||
|
// Macros that trigger a plugin hook. We put this into macros to short-cut
|
||||||
|
// the code for the most common case that no plugin defines the hook.
|
||||||
|
#define PLUGIN_HOOK_WITH_RESULT(hook, method_call, default_result) \
|
||||||
|
(plugin_mgr->HavePluginForHook(plugin::hook) ? plugin_mgr->method_call : (default_result))
|
||||||
|
|
||||||
|
#define PLUGIN_HOOK_VOID(hook, method_call) \
|
||||||
|
if ( plugin_mgr->HavePluginForHook(plugin::hook) ) plugin_mgr->method_call;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A singleton object managing all plugins.
|
* A singleton object managing all plugins.
|
||||||
*/
|
*/
|
||||||
|
@ -19,7 +27,6 @@ class Manager
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
typedef std::list<Plugin*> plugin_list;
|
typedef std::list<Plugin*> plugin_list;
|
||||||
typedef std::list<InterpreterPlugin*> interpreter_plugin_list;
|
|
||||||
typedef Plugin::component_list component_list;
|
typedef Plugin::component_list component_list;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -30,7 +37,7 @@ public:
|
||||||
/**
|
/**
|
||||||
* Destructor.
|
* Destructor.
|
||||||
*/
|
*/
|
||||||
~Manager();
|
virtual ~Manager();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Loads all plugins dynamically from a set of directories. Multiple
|
* Loads all plugins dynamically from a set of directories. Multiple
|
||||||
|
@ -71,22 +78,6 @@ public:
|
||||||
*/
|
*/
|
||||||
void FinishPlugins();
|
void FinishPlugins();
|
||||||
|
|
||||||
/**
|
|
||||||
* This tries to load the given file by searching for a plugin that
|
|
||||||
* support that extension. If a correspondign plugin is found, it's
|
|
||||||
* asked to loead the file. If that fails, the method reports an
|
|
||||||
* error message.
|
|
||||||
*
|
|
||||||
* This method must be called only between InitPreScript() and
|
|
||||||
* InitPostScript().
|
|
||||||
*
|
|
||||||
* @return 1 if the file was sucessfully loaded by a plugin; 0 if a
|
|
||||||
* plugin was found that supports the file's extension, yet it
|
|
||||||
* encountered a problem loading the file; and -1 if we don't have a
|
|
||||||
* plugin that supports this extension.
|
|
||||||
*/
|
|
||||||
int TryLoadFile(const char* file);
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns a list of all available plugins. This includes all that
|
* Returns a list of all available plugins. This includes all that
|
||||||
* are compiled in statically, as well as those loaded dynamically so
|
* are compiled in statically, as well as those loaded dynamically so
|
||||||
|
@ -102,7 +93,65 @@ public:
|
||||||
template<class T> std::list<T *> Components() const;
|
template<class T> std::list<T *> Components() const;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Filters a function/event/hook call through all interpreter plugins.
|
* Returns true if there's at least one plugin interested in a given
|
||||||
|
* hook.
|
||||||
|
*
|
||||||
|
* @param The hook to check.
|
||||||
|
*
|
||||||
|
* @return True if there's a plugin for that hook.
|
||||||
|
*/
|
||||||
|
bool HavePluginForHook(HookType hook) const
|
||||||
|
{
|
||||||
|
// Inline to make avoid the function call.
|
||||||
|
return hooks[hook] != 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns all the hooks, with their priorities, that are currently
|
||||||
|
* enabled for a given plugin.
|
||||||
|
*
|
||||||
|
* @param plugin The plugin to return the hooks for.
|
||||||
|
*/
|
||||||
|
std::list<std::pair<HookType, int> > HooksEnabledForPlugin(const Plugin* plugin) const;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Enables a hook for a given plugin.
|
||||||
|
*
|
||||||
|
* hook: The hook to enable.
|
||||||
|
*
|
||||||
|
* plugin: The plugin defining the hook.
|
||||||
|
*
|
||||||
|
* prio: The priority to associate with the plugin for this hook.
|
||||||
|
*/
|
||||||
|
void EnableHook(HookType hook, Plugin* plugin, int prio);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Disables a hook for a given plugin.
|
||||||
|
*
|
||||||
|
* hook: The hook to enable.
|
||||||
|
*
|
||||||
|
* plugin: The plugin that used to define the hook.
|
||||||
|
*/
|
||||||
|
void DisableHook(HookType hook, Plugin* plugin);
|
||||||
|
|
||||||
|
// Hook entry functions.
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Hook that gives plugins a chance to take over loading an input
|
||||||
|
* input file. This method must be called between InitPreScript() and
|
||||||
|
* InitPostScript() for each input file Bro is about to load, either
|
||||||
|
* given on the command line or via @load script directives. The hook
|
||||||
|
* can take over the file, in which case Bro must not further process
|
||||||
|
* it otherwise.
|
||||||
|
*
|
||||||
|
* @return 1 if a plugin took over the file and loaded it
|
||||||
|
* 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);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Hook that filters calls to a script function/event/hook.
|
||||||
*
|
*
|
||||||
* @param func The function to be called.
|
* @param func The function to be called.
|
||||||
*
|
*
|
||||||
|
@ -113,39 +162,29 @@ public:
|
||||||
* events, it may be any Val and must be ignored). If no plugin
|
* events, it may be any Val and must be ignored). If no plugin
|
||||||
* handled the call, the method returns null.
|
* handled the call, the method returns null.
|
||||||
*/
|
*/
|
||||||
Val* CallFunction(const Func* func, val_list* args) const;
|
Val* HookCallFunction(const Func* func, val_list* args) const;
|
||||||
|
|
||||||
/**
|
|
||||||
* Filter the queuing of an event through all interpreter plugins.
|
|
||||||
*
|
|
||||||
* @param event The event to be queued; it may be modified.
|
|
||||||
*
|
|
||||||
* @return Returns true if a plugin handled the queuing; in that case the
|
|
||||||
* plugin will have taken ownership.
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
bool QueueEvent(Event* event) const;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Informs all interpreter plugins about an update in network time.
|
* Hook that filters the queuing of an event.
|
||||||
*
|
*
|
||||||
* @param networkt_time The new network time.
|
* @param event The event to be queued; it may be modified.
|
||||||
|
*
|
||||||
|
* @return Returns true if a plugin handled the queuing; in that case
|
||||||
|
* the plugin will have taken ownership.
|
||||||
*/
|
*/
|
||||||
void UpdateNetworkTime(double network_time) const;
|
bool HookQueueEvent(Event* event) const;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Informs all interpreter plugins that the event queue has been drained.
|
* Hook that informs plugins about an update in network time.
|
||||||
|
*
|
||||||
|
* @param network_time The new network time.
|
||||||
*/
|
*/
|
||||||
void DrainEvents() const;
|
void HookUpdateNetworkTime(double network_time) const;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Disables an interpreter plugin's hooking of the script interpreter.
|
* Hooks that informs plugins that the event queue is being drained.
|
||||||
* The remaining functionality of the Plugin base class remains
|
*/
|
||||||
* available.
|
void HookDrainEvents() const;
|
||||||
*
|
|
||||||
* @param plugin The plugin to disable.
|
|
||||||
*/
|
|
||||||
void DisableInterpreterPlugin(const InterpreterPlugin* plugin);
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Internal method that registers a freshly instantiated plugin with
|
* Internal method that registers a freshly instantiated plugin with
|
||||||
|
@ -177,13 +216,17 @@ protected:
|
||||||
int LoadPlugin(const std::string& dir);
|
int LoadPlugin(const std::string& dir);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
// 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();
|
static plugin_list* PluginsInternal();
|
||||||
|
|
||||||
bool init;
|
bool init;
|
||||||
typedef std::map<std::string, Plugin*> extension_map;
|
|
||||||
extension_map extensions;
|
|
||||||
|
|
||||||
interpreter_plugin_list interpreter_plugins;
|
// An array indexed by HookType. An entry is null if there's no hook
|
||||||
|
// of that type enabled.
|
||||||
|
hook_list** hooks;
|
||||||
|
|
||||||
static string current_dir;
|
static string current_dir;
|
||||||
static string current_sopath;
|
static string current_sopath;
|
||||||
|
|
|
@ -10,6 +10,22 @@
|
||||||
|
|
||||||
using namespace plugin;
|
using namespace plugin;
|
||||||
|
|
||||||
|
const char* hook_name(HookType h)
|
||||||
|
{
|
||||||
|
static const char* hook_names[int(NUM_HOOKS) + 1] = {
|
||||||
|
// Order must match that of HookType.
|
||||||
|
"LoadFile",
|
||||||
|
"CallFunction",
|
||||||
|
"QueueEvent",
|
||||||
|
"DrainEvents",
|
||||||
|
"UpdateNetworkTime",
|
||||||
|
// End marker.
|
||||||
|
"<end>",
|
||||||
|
};
|
||||||
|
|
||||||
|
return hook_names[int(h)];
|
||||||
|
}
|
||||||
|
|
||||||
BifItem::BifItem(const char* arg_id, Type arg_type)
|
BifItem::BifItem(const char* arg_id, Type arg_type)
|
||||||
{
|
{
|
||||||
id = copy_string(arg_id);
|
id = copy_string(arg_id);
|
||||||
|
@ -49,7 +65,6 @@ Plugin::Plugin()
|
||||||
dynamic = false;
|
dynamic = false;
|
||||||
base_dir = 0;
|
base_dir = 0;
|
||||||
sopath = 0;
|
sopath = 0;
|
||||||
extensions = 0;
|
|
||||||
|
|
||||||
Manager::RegisterPlugin(this);
|
Manager::RegisterPlugin(this);
|
||||||
}
|
}
|
||||||
|
@ -62,12 +77,6 @@ Plugin::~Plugin()
|
||||||
delete [] description;
|
delete [] description;
|
||||||
delete [] base_dir;
|
delete [] base_dir;
|
||||||
delete [] sopath;
|
delete [] sopath;
|
||||||
delete [] extensions;
|
|
||||||
}
|
|
||||||
|
|
||||||
Plugin::Type Plugin::PluginType() const
|
|
||||||
{
|
|
||||||
return STANDARD;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
const char* Plugin::Name() const
|
const char* Plugin::Name() const
|
||||||
|
@ -170,22 +179,6 @@ Plugin::bif_item_list Plugin::CustomBifItems() const
|
||||||
return bif_item_list();
|
return bif_item_list();
|
||||||
}
|
}
|
||||||
|
|
||||||
const char* Plugin::FileExtensions() const
|
|
||||||
{
|
|
||||||
return extensions ? extensions : "";
|
|
||||||
}
|
|
||||||
|
|
||||||
void Plugin::SetFileExtensions(const char* ext)
|
|
||||||
{
|
|
||||||
extensions = copy_string(ext);
|
|
||||||
}
|
|
||||||
|
|
||||||
bool Plugin::LoadFile(const char* file)
|
|
||||||
{
|
|
||||||
reporter->InternalError("Plugin::LoadFile not overriden for %s", file);
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
void Plugin::Done()
|
void Plugin::Done()
|
||||||
{
|
{
|
||||||
for ( component_list::const_iterator i = components.begin(); i != components.end(); i++ )
|
for ( component_list::const_iterator i = components.begin(); i != components.end(); i++ )
|
||||||
|
@ -204,18 +197,9 @@ static bool component_cmp(const Component* a, const Component* b)
|
||||||
return a->Name() < b->Name();
|
return a->Name() < b->Name();
|
||||||
}
|
}
|
||||||
|
|
||||||
void Plugin::AddComponent(Component* c)
|
|
||||||
{
|
|
||||||
components.push_back(c);
|
|
||||||
|
|
||||||
// Sort components by name to make sure we have a deterministic
|
|
||||||
// order.
|
|
||||||
components.sort(component_cmp);
|
|
||||||
}
|
|
||||||
|
|
||||||
bool Plugin::LoadBroFile(const char* file)
|
bool Plugin::LoadBroFile(const char* file)
|
||||||
{
|
{
|
||||||
add_input_file(file);
|
::add_input_file(file);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -230,6 +214,53 @@ void Plugin::AddBifItem(const char* name, BifItem::Type type)
|
||||||
bif_items.push_back(bi);
|
bif_items.push_back(bi);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void Plugin::AddComponent(Component* c)
|
||||||
|
{
|
||||||
|
components.push_back(c);
|
||||||
|
|
||||||
|
// Sort components by name to make sure we have a deterministic
|
||||||
|
// order.
|
||||||
|
components.sort(component_cmp);
|
||||||
|
}
|
||||||
|
|
||||||
|
Plugin::hook_list Plugin::EnabledHooks() const
|
||||||
|
{
|
||||||
|
return plugin_mgr->HooksEnabledForPlugin(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
void Plugin::EnableHook(HookType hook, int priority)
|
||||||
|
{
|
||||||
|
plugin_mgr->EnableHook(hook, this, priority);
|
||||||
|
}
|
||||||
|
|
||||||
|
void Plugin::DisableHook(HookType hook)
|
||||||
|
{
|
||||||
|
plugin_mgr->DisableHook(hook, this);
|
||||||
|
}
|
||||||
|
|
||||||
|
int Plugin::HookLoadFile(const char* file)
|
||||||
|
{
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
Val* Plugin::HookCallFunction(const Func* func, val_list* args)
|
||||||
|
{
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool Plugin::HookQueueEvent(Event* event)
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
void Plugin::HookDrainEvents()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
void Plugin::HookUpdateNetworkTime(double network_time)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
void Plugin::Describe(ODesc* d) const
|
void Plugin::Describe(ODesc* d) const
|
||||||
{
|
{
|
||||||
d->Add("Plugin: ");
|
d->Add("Plugin: ");
|
||||||
|
@ -256,18 +287,6 @@ void Plugin::Describe(ODesc* d) const
|
||||||
else
|
else
|
||||||
d->Add(" (built-in)");
|
d->Add(" (built-in)");
|
||||||
|
|
||||||
switch ( PluginType() ) {
|
|
||||||
case STANDARD:
|
|
||||||
break;
|
|
||||||
|
|
||||||
case INTERPRETER:
|
|
||||||
d->Add( " (interpreter plugin)");
|
|
||||||
break;
|
|
||||||
|
|
||||||
default:
|
|
||||||
reporter->InternalError("unknown plugin type in Plugin::Describe");
|
|
||||||
}
|
|
||||||
|
|
||||||
d->Add("\n");
|
d->Add("\n");
|
||||||
|
|
||||||
if ( d->IsShort() )
|
if ( d->IsShort() )
|
||||||
|
@ -317,48 +336,19 @@ void Plugin::Describe(ODesc* d) const
|
||||||
d->Add((*i).GetID());
|
d->Add((*i).GetID());
|
||||||
d->Add("\n");
|
d->Add("\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
hook_list hooks = EnabledHooks();
|
||||||
|
|
||||||
|
for ( hook_list::iterator i = hooks.begin(); i != hooks.end(); i++ )
|
||||||
|
{
|
||||||
|
HookType hook = (*i).first;
|
||||||
|
int prio = (*i).second;
|
||||||
|
|
||||||
|
d->Add(" Implements ");
|
||||||
|
d->Add(hook_name(hook));
|
||||||
|
d->Add(" (priority ");
|
||||||
|
d->Add(prio);
|
||||||
|
d->Add("]\n");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
InterpreterPlugin::InterpreterPlugin(int arg_priority)
|
|
||||||
{
|
|
||||||
priority = arg_priority;
|
|
||||||
}
|
|
||||||
|
|
||||||
InterpreterPlugin::~InterpreterPlugin()
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
int InterpreterPlugin::Priority() const
|
|
||||||
{
|
|
||||||
return priority;
|
|
||||||
}
|
|
||||||
|
|
||||||
Plugin::Type InterpreterPlugin::PluginType() const
|
|
||||||
{
|
|
||||||
return INTERPRETER;
|
|
||||||
}
|
|
||||||
|
|
||||||
Val* InterpreterPlugin::CallFunction(const Func* func, val_list* args)
|
|
||||||
{
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool InterpreterPlugin::QueueEvent(Event* event)
|
|
||||||
{
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
void InterpreterPlugin::UpdateNetworkTime(double network_time)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
void InterpreterPlugin::DrainEvents()
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
void InterpreterPlugin::DisableInterpreterPlugin() const
|
|
||||||
{
|
|
||||||
plugin_mgr->DisableInterpreterPlugin(this);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -17,6 +17,21 @@ namespace plugin {
|
||||||
class Manager;
|
class Manager;
|
||||||
class Component;
|
class Component;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Hook types that a plugin may define. Each label maps to the corresponding
|
||||||
|
* virtual method in \a Plugin.
|
||||||
|
*/
|
||||||
|
enum HookType {
|
||||||
|
// Note: when changing this table, update hook_name() in Plugin.cc.
|
||||||
|
HOOK_LOAD_FILE,
|
||||||
|
HOOK_CALL_FUNCTION,
|
||||||
|
HOOK_QUEUE_EVENT,
|
||||||
|
HOOK_DRAIN_EVENTS,
|
||||||
|
HOOK_UPDATE_NETWORK_TIME,
|
||||||
|
// End marker.
|
||||||
|
NUM_HOOKS,
|
||||||
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A class describing an item defined in \c *.bif file.
|
* A class describing an item defined in \c *.bif file.
|
||||||
*/
|
*/
|
||||||
|
@ -70,45 +85,37 @@ private:
|
||||||
/**
|
/**
|
||||||
* Base class for all plugins.
|
* Base class for all plugins.
|
||||||
*
|
*
|
||||||
* Plugins encapsulate functionality that extends one of Bro's major
|
* Plugins encapsulate functionality that extends one or more of Bro's major
|
||||||
* subsystems, such as analysis of a specific protocol, or logging output in
|
* subsystems, such as analysis of a specific protocol, or logging output in
|
||||||
* a particular format. A plugin is a logical container that can provide one
|
* a particular format. A plugin acts a logical container that can provide a
|
||||||
* or more \a components implementing functionality. For example, a RPC
|
* set of different functionality. Specifically, it may:
|
||||||
* plugin could provide analyzer for set of related protocols (RPC, NFS,
|
*
|
||||||
* etc.), each of which would be a separate component. Likewise, a SQLite
|
* - Provide one or more \a components implementing functionality. For
|
||||||
* plugin could provide both a writer and reader component. In addition to
|
* example, a RPC plugin could provide analyzer for set of related
|
||||||
* components, a plugin can also provide of script-level elements defined in
|
* protocols (RPC, NFS, etc.), each of which would be a separate component.
|
||||||
* *.bif files.
|
* Likewise, a SQLite plugin could provide both a writer and reader
|
||||||
|
* component. In addition to components, a plugin can also provide of
|
||||||
|
* script-level elements defined in *.bif files.
|
||||||
|
*
|
||||||
|
* - Provide BiF elements (functions, events, types, globals).
|
||||||
|
*
|
||||||
|
* - Provide hooks (aka callbacks) into Bro's core processing to inject
|
||||||
|
* and/or alter functionality.
|
||||||
|
*
|
||||||
|
* 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).
|
||||||
*
|
*
|
||||||
* Currently, all plugins are compiled statically into the final Bro binary.
|
|
||||||
* Later, we will extend the infrastructure to also support plugins loaded
|
|
||||||
* dynamically as shared libraries.
|
|
||||||
*/
|
*/
|
||||||
class Plugin {
|
class Plugin {
|
||||||
public:
|
public:
|
||||||
typedef std::list<Component *> component_list;
|
typedef std::list<Component *> component_list;
|
||||||
typedef std::list<BifItem> bif_item_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<const char*, int> > bif_init_func_result;
|
||||||
typedef void (*bif_init_func)(Plugin *);
|
typedef void (*bif_init_func)(Plugin *);
|
||||||
|
|
||||||
/**
|
|
||||||
* Type of a plugin. Plugin types are set implicitly by deriving from
|
|
||||||
* the corresponding base class. */
|
|
||||||
enum Type {
|
|
||||||
/**
|
|
||||||
* A standard plugin. This is the type for all plugins
|
|
||||||
* derived directly from \a Plugin. */
|
|
||||||
STANDARD,
|
|
||||||
|
|
||||||
/**
|
|
||||||
* An interpreter plugin. These plugins get hooked into the
|
|
||||||
* script interpreter and can modify, or even replace, its
|
|
||||||
* execution of Bro script code. To create an interpreter
|
|
||||||
* plugin, derive from \aInterpreterPlugin.
|
|
||||||
*/
|
|
||||||
INTERPRETER
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Constructor.
|
* Constructor.
|
||||||
*/
|
*/
|
||||||
|
@ -119,11 +126,6 @@ public:
|
||||||
*/
|
*/
|
||||||
virtual ~Plugin();
|
virtual ~Plugin();
|
||||||
|
|
||||||
/**
|
|
||||||
* Returns the type of the plugin.
|
|
||||||
*/
|
|
||||||
virtual Type PluginType() const;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns the name of the plugin.
|
* Returns the name of the plugin.
|
||||||
*/
|
*/
|
||||||
|
@ -146,11 +148,6 @@ public:
|
||||||
*/
|
*/
|
||||||
bool DynamicPlugin() const;
|
bool DynamicPlugin() const;
|
||||||
|
|
||||||
/**
|
|
||||||
* Returns a colon-separated list of file extensions the plugin handles.
|
|
||||||
*/
|
|
||||||
const char* FileExtensions() const;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* For dynamic plugins, returns the base directory from which it was
|
* For dynamic plugins, returns the base directory from which it was
|
||||||
* loaded. For static plugins, returns null.
|
* loaded. For static plugins, returns null.
|
||||||
|
@ -201,8 +198,8 @@ public:
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Finalizer method that derived classes can override for performing
|
* Finalizer method that derived classes can override for performing
|
||||||
* custom tasks at shutdown. Implementation must call the parent's
|
* custom tasks at shutdown. This can be overridden by derived
|
||||||
* version.
|
* classes; they must however call the parent's implementation.
|
||||||
*/
|
*/
|
||||||
virtual void Done();
|
virtual void Done();
|
||||||
|
|
||||||
|
@ -216,12 +213,14 @@ public:
|
||||||
void Describe(ODesc* d) const;
|
void Describe(ODesc* d) const;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Registering an individual BiF that the plugin defines. The
|
* Registers an individual BiF that the plugin defines. The
|
||||||
* information is for informational purpuses only and will show up in
|
* information is for informational purpuses only and will show up in
|
||||||
* the result of BifItems() as well as in the Describe() output.
|
* the result of BifItems() as well as in the Describe() output.
|
||||||
* Another way to add this information is via overriding
|
* Another way to add this information is via overriding
|
||||||
* CustomBifItems().
|
* CustomBifItems().
|
||||||
*
|
*
|
||||||
|
* \todo Do we need both this an CustomBifItems()?
|
||||||
|
*
|
||||||
* @param name The name of the BiF item.
|
* @param name The name of the BiF item.
|
||||||
*
|
*
|
||||||
* @param type The item's type.
|
* @param type The item's type.
|
||||||
|
@ -229,10 +228,10 @@ public:
|
||||||
void AddBifItem(const char* name, BifItem::Type type);
|
void AddBifItem(const char* name, BifItem::Type type);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Adds a file to the list of files Bro loads at startup. This will
|
* Adds a file to the list of files that Bro loads at startup. This
|
||||||
* normally be a Bro script, but it passes through the plugin system
|
* will normally be a Bro script, but it passes through the plugin
|
||||||
* as well to load files with other extensions as supported by any of
|
* system as well to load files with other extensions as supported by
|
||||||
* the current plugins. In other words, calling this method is
|
* any of the current plugins. In other words, calling this method is
|
||||||
* similar to given a file on the command line. Note that the file
|
* similar to given a file on the command line. Note that the file
|
||||||
* may be only queued for now, and actually loaded later.
|
* may be only queued for now, and actually loaded later.
|
||||||
*
|
*
|
||||||
|
@ -245,161 +244,99 @@ public:
|
||||||
*/
|
*/
|
||||||
bool LoadBroFile(const char* file);
|
bool LoadBroFile(const char* file);
|
||||||
|
|
||||||
protected:
|
|
||||||
friend class Manager;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Sets the plugins name.
|
|
||||||
*
|
|
||||||
* @param name The name. Makes a copy internally.
|
|
||||||
*/
|
|
||||||
void SetName(const char* name);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Sets the plugin's textual description.
|
|
||||||
*
|
|
||||||
* @param name The description. Makes a copy internally.
|
|
||||||
*/
|
|
||||||
void SetDescription(const char* descr);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Sets the plugin's version.
|
|
||||||
*
|
|
||||||
* @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.
|
|
||||||
*/
|
|
||||||
void SetAPIVersion(int version);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Marks the plugin as statically or dynamically linked.
|
|
||||||
*
|
|
||||||
* @param dynamic True if this is a dynamically linked plugin.
|
|
||||||
*/
|
|
||||||
void SetDynamicPlugin(bool dynamic);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Reports the extensions of input files the plugin handles. If Bro
|
|
||||||
* wants to load a file with one of these extensions it will pass
|
|
||||||
* them to LoadFile() and then then ignore otherwise.
|
|
||||||
*
|
|
||||||
* ext: A list of colon-separated file extensions the plugin handles.
|
|
||||||
*/
|
|
||||||
void SetFileExtensions(const char* ext);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Sets the base directory and shared library path from which the
|
|
||||||
* plugin was loaded. This should be called only from the manager for
|
|
||||||
* dynamic plugins.
|
|
||||||
*
|
|
||||||
* @param dir The plugin directory. The functions makes an internal
|
|
||||||
* copy of string.
|
|
||||||
*
|
|
||||||
* @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);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Takes ownership.
|
|
||||||
*/
|
|
||||||
void AddComponent(Component* c);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Virtual method that can be overriden by derived class to provide
|
|
||||||
* information about further script-level elements that the plugins
|
|
||||||
* provides on its own, i.e., outside of the standard mechanism
|
|
||||||
* processing *.bif files automatically. The returned information is
|
|
||||||
* for informational purpuses only and will show up in the result of
|
|
||||||
* BifItems() as well as in the Describe() output.
|
|
||||||
*/
|
|
||||||
virtual bif_item_list CustomBifItems() const;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Virtual method that can be overriden by derived class to load
|
|
||||||
* files with extensions reported via SetFileExtension().
|
|
||||||
*
|
|
||||||
* This method will be called between InitPreScript() and
|
|
||||||
* InitPostScript(), but with no further order or timing guaranteed.
|
|
||||||
* It will be called once for each file encountered with of the
|
|
||||||
* specificed extensions (i.e., duplicates are filtered out
|
|
||||||
* automatically).
|
|
||||||
*
|
|
||||||
* @return True if the file was loaded successfuly, false if not. Bro
|
|
||||||
* will abort in the latter case.
|
|
||||||
*/
|
|
||||||
virtual bool LoadFile(const char* file);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Initializes the BiF items added with AddBifItem(). Internal method
|
|
||||||
* that will be called by the manager at the right time.
|
|
||||||
*/
|
|
||||||
void InitBifs();
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Internal function adding an entry point for registering
|
* Internal function adding an entry point for registering
|
||||||
* auto-generated BiFs.
|
* auto-generated BiFs.
|
||||||
*/
|
*/
|
||||||
void __AddBifInitFunction(bif_init_func c);
|
void __AddBifInitFunction(bif_init_func c);
|
||||||
|
|
||||||
private:
|
protected:
|
||||||
typedef std::list<bif_init_func> bif_init_func_list;
|
friend class Manager;
|
||||||
|
|
||||||
const char* name;
|
|
||||||
const char* description;
|
|
||||||
const char* base_dir;
|
|
||||||
const char* sopath;
|
|
||||||
const char* extensions;
|
|
||||||
int version;
|
|
||||||
int api_version;
|
|
||||||
bool dynamic;
|
|
||||||
|
|
||||||
component_list components;
|
|
||||||
bif_item_list bif_items;
|
|
||||||
bif_init_func_list bif_inits;
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Class for hooking into script execution. An interpreter plugin can do
|
|
||||||
* everything a normal plugin can, yet will also be interfaced to the script
|
|
||||||
* interpreter for learning about, modidying, or potentially replacing
|
|
||||||
* standard functionality.
|
|
||||||
*/
|
|
||||||
class InterpreterPlugin : public Plugin {
|
|
||||||
public:
|
|
||||||
/**
|
/**
|
||||||
* Constructor.
|
* Registers and activates a component.
|
||||||
*
|
*
|
||||||
* @param priority Imposes an order on InterpreterPlugins in which
|
* @param c The component. The method takes ownership.
|
||||||
* they'll be chained. The higher the prioritu, the earlier a plugin
|
|
||||||
* is called when the interpreter goes through the chain. */
|
|
||||||
InterpreterPlugin(int priority);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Destructor.
|
|
||||||
*/
|
*/
|
||||||
virtual ~InterpreterPlugin();
|
void AddComponent(Component* c);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns the plugins priority.
|
* Enables a hook. The corresponding virtual method will now be
|
||||||
|
* called as Bro's processing proceeds. Note that enabling hooks can
|
||||||
|
* have performance impaxct as many trigger frequently inside Bro's
|
||||||
|
* main processing path.
|
||||||
|
*
|
||||||
|
* Note that hooks may be enabled/disabled dynamically at any time,
|
||||||
|
* the output of Bro's \c -NN option will only reflect that state at
|
||||||
|
* startup time; hence usually one should call this for a plugin's
|
||||||
|
* hooks in either the plugin's ctor or in InitPreScript(). For
|
||||||
|
* consistency with other parts of the API, there's a macro
|
||||||
|
* PLUGIN_ENABLE_HOOK for use inside the ctor.
|
||||||
|
*
|
||||||
|
* @param hook The hook to enable.
|
||||||
|
*
|
||||||
|
* @param priority If multiple plugins enable the same hook, their
|
||||||
|
* priorities determine the order in which they'll be executed, from
|
||||||
|
* highest to lowest. If two plugins specify the same priority, order
|
||||||
|
* is undefined.
|
||||||
*/
|
*/
|
||||||
int Priority() const;
|
void EnableHook(HookType hook, int priority = 0);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Callback for executing a function/event/hook. Whenever the script
|
* Disables a hook. Bro will no longer call the corresponding virtual
|
||||||
* interpreter is about to execution a function, it first gives all
|
* method.
|
||||||
* InterpreterPlugins a chance to handle the call (in the order of their
|
*
|
||||||
* priorities). A plugin can either just inspect the call, or replace it
|
* @param hook The hook to disable.
|
||||||
* (i.e., prevent the interpreter from executing it). In the latter case
|
*/
|
||||||
* it must provide a matching return value.
|
void DisableHook(HookType hook);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns a list of hooks that are currently enabled for the plugin,
|
||||||
|
* along with their priorities.
|
||||||
|
*/
|
||||||
|
hook_list EnabledHooks() const;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Virtual method that can be overriden by derived class to provide
|
||||||
|
* information about further script-level elements that the plugin
|
||||||
|
* provides on its own, i.e., outside of the standard mechanism
|
||||||
|
* processing *.bif files automatically. The returned information is
|
||||||
|
* for informational purposes only and will show up in the result of
|
||||||
|
* BifItems() as well as in the Describe() output.
|
||||||
|
*
|
||||||
|
* \todo Do we need both this an AddBifItem()?
|
||||||
|
*/
|
||||||
|
virtual bif_item_list CustomBifItems() const;
|
||||||
|
|
||||||
|
// Hook functions.
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Hook into loading input files. This method will be called between
|
||||||
|
* InitPreScript() and InitPostScript(), but with no further order or
|
||||||
|
* timing guaranteed. It will be called once for each input file Bro
|
||||||
|
* is about to load, either given on the command line or via @load
|
||||||
|
* script directives. The hook can take over the file, in which case
|
||||||
|
* Bro not further process it otherwise.
|
||||||
|
*
|
||||||
|
* @return 1 if the plugin took over the file and loaded it
|
||||||
|
* successfully; 0 if the plugin took over the file but had trouble
|
||||||
|
* loading it (Bro will abort in this case, the plugin should have
|
||||||
|
* printed an error message); and -1 if the plugin wasn't interested
|
||||||
|
* in the file at all.
|
||||||
|
*/
|
||||||
|
virtual int HookLoadFile(const char* file);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Hook into executing a script-level function/event/hook. Whenever
|
||||||
|
* the script interpreter is about to execution a function, it first
|
||||||
|
* gives all plugins with this hook enabled a chance to handle the
|
||||||
|
* call (in the order of their priorities). A plugin can either just
|
||||||
|
* inspect the call, or replace it (i.e., prevent the interpreter
|
||||||
|
* from executing it). In the latter case it must provide a matching
|
||||||
|
* return value.
|
||||||
*
|
*
|
||||||
* The default implementation does never handle the call in any way.
|
* The default implementation does never handle the call in any way.
|
||||||
*
|
*
|
||||||
* @param func The function being called.
|
* @param func The function being called.
|
||||||
*
|
*
|
||||||
* @param args The function arguments. The method can modify the list
|
* @param args The function arguments. The method can modify the list
|
||||||
|
@ -412,55 +349,133 @@ public:
|
||||||
* TYPE_ANY). If the plugin did not handle the call, it must return
|
* TYPE_ANY). If the plugin did not handle the call, it must return
|
||||||
* null.
|
* null.
|
||||||
*/
|
*/
|
||||||
virtual Val* CallFunction(const Func* func, val_list* args);
|
virtual Val* HookCallFunction(const Func* func, val_list* args);
|
||||||
|
|
||||||
/**
|
|
||||||
* Callback for raising an event. Whenever the script interpreter is
|
|
||||||
* about to queue an event for later execution, it first gives all
|
|
||||||
* InterpreterPlugins a chance to handle the queuing otherwise (in the
|
|
||||||
* order of their priorities). A plugin can either just inspect the
|
|
||||||
* event, or take it over (i.e., prevent the interpreter from queuing it
|
|
||||||
* it).
|
|
||||||
*
|
|
||||||
* The default implementation does never handle the queuing in any way.
|
|
||||||
*
|
|
||||||
* @param event The even to be queued. The method can modify it in in
|
|
||||||
* place long as it ensures matching types and correct reference
|
|
||||||
* counting.
|
|
||||||
*
|
|
||||||
* @return True if the plugin took charge of the event; in that case it
|
|
||||||
* must have assumed ownership of the event and the intpreter will not do
|
|
||||||
* anything further with it. False otherwise.
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
virtual bool QueueEvent(Event* event);
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Callback for updates in network time. This method will be called
|
* Hook into raising events. Whenever the script interpreter is about
|
||||||
|
* to queue an event for later execution, it first gives all plugins
|
||||||
|
* with this hook enabled a chance to handle the queuing otherwise
|
||||||
|
* (in the order of their priorities). A plugin can either just
|
||||||
|
* inspect the event, or take it over (i.e., prevent the interpreter
|
||||||
|
* from queuing it it).
|
||||||
|
*
|
||||||
|
* The default implementation does never handle the queuing in any
|
||||||
|
* way.
|
||||||
|
*
|
||||||
|
* @param event The even to be queued. The method can modify it in in
|
||||||
|
* place long as it ensures matching types and correct reference
|
||||||
|
* counting.
|
||||||
|
*
|
||||||
|
* @return True if the plugin took charge of the event; in that case
|
||||||
|
* it must have assumed ownership of the event and the intpreter will
|
||||||
|
* not do anything further with it. False otherwise.
|
||||||
|
*/
|
||||||
|
virtual bool HookQueueEvent(Event* event);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Hook intp event queue draining. This method will be called
|
||||||
|
* whenever the event manager is draining its queue.
|
||||||
|
*/
|
||||||
|
virtual void HookDrainEvents();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Hook for updates to network time. This method will be called
|
||||||
* whenever network time is advanced.
|
* whenever network time is advanced.
|
||||||
*
|
*
|
||||||
* @param networkt_time The new network time.
|
* @param networkt_time The new network time.
|
||||||
*/
|
*/
|
||||||
virtual void UpdateNetworkTime(double network_time);
|
virtual void HookUpdateNetworkTime(double network_time);
|
||||||
|
|
||||||
|
// Methods that are used internally primarily.
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Callback for event queue draining. This method will be called
|
* Sets the plugins name.
|
||||||
* whenever the event manager has drained it queue.
|
*
|
||||||
|
* 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.
|
||||||
*/
|
*/
|
||||||
virtual void DrainEvents();
|
void SetName(const char* name);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Disables interpreter hooking. The functionality of the Plugin base
|
* Sets the plugin's textual description.
|
||||||
* class remains available.
|
*
|
||||||
|
* 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 DisableInterpreterPlugin() const;
|
void SetDescription(const char* descr);
|
||||||
|
|
||||||
// Overridden from base class.
|
/**
|
||||||
virtual Type PluginType() const;
|
* 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.
|
||||||
|
*
|
||||||
|
* This is used primarily internally; plugins will have there
|
||||||
|
* location set automatically.
|
||||||
|
*
|
||||||
|
* @param dir The plugin directory. The functions makes an internal
|
||||||
|
* copy of string.
|
||||||
|
*
|
||||||
|
* @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);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
int priority;
|
/**
|
||||||
|
* Initializes the BiF items added with AddBifItem(). Internal method
|
||||||
|
* that will be called by the manager at the right time.
|
||||||
|
*/
|
||||||
|
void InitBifs();
|
||||||
|
|
||||||
|
typedef std::list<bif_init_func> bif_init_func_list;
|
||||||
|
|
||||||
|
const char* name;
|
||||||
|
const char* description;
|
||||||
|
const char* base_dir;
|
||||||
|
const char* sopath;
|
||||||
|
int version;
|
||||||
|
int api_version;
|
||||||
|
bool dynamic;
|
||||||
|
|
||||||
|
component_list components;
|
||||||
|
bif_item_list bif_items;
|
||||||
|
bif_init_func_list bif_inits;
|
||||||
};
|
};
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -581,7 +581,7 @@ YYLTYPE GetCurrentLocation()
|
||||||
|
|
||||||
static int load_files(const char* orig_file)
|
static int load_files(const char* orig_file)
|
||||||
{
|
{
|
||||||
int rc = plugin_mgr->TryLoadFile(orig_file);
|
int rc = PLUGIN_HOOK_WITH_RESULT(HOOK_LOAD_FILE, HookLoadFile(orig_file), -1);
|
||||||
|
|
||||||
if ( rc == 1 )
|
if ( rc == 1 )
|
||||||
return 0; // A plugin took care of it, just skip.
|
return 0; // A plugin took care of it, just skip.
|
||||||
|
|
|
@ -213,7 +213,7 @@ extern void add_to_bro_path(const std::string& dir);
|
||||||
|
|
||||||
extern const char* bro_magic_path();
|
extern const char* bro_magic_path();
|
||||||
extern const char* bro_plugin_path();
|
extern const char* bro_plugin_path();
|
||||||
extern const char* bro_prefixes();
|
extern std::string bro_prefixes();
|
||||||
std::string dot_canon(std::string path, std::string file, std::string prefix = "");
|
std::string dot_canon(std::string path, std::string file, std::string prefix = "");
|
||||||
const char* normalize_path(const char* path);
|
const char* normalize_path(const char* path);
|
||||||
void get_script_subpath(const std::string& full_filename, const char** subpath);
|
void get_script_subpath(const std::string& full_filename, const char** subpath);
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue