diff --git a/src/analyzer/protocol/tcp/Plugin.cc b/src/analyzer/protocol/tcp/Plugin.cc index 4c53422cf6..b258135b37 100644 --- a/src/analyzer/protocol/tcp/Plugin.cc +++ b/src/analyzer/protocol/tcp/Plugin.cc @@ -14,7 +14,7 @@ public: { AddComponent(new ::analyzer::Component("TCP", ::analyzer::tcp::TCP_Analyzer::Instantiate)); AddComponent(new ::analyzer::Component("TCPStats", ::analyzer::tcp::TCPStats_Analyzer::Instantiate)); - AddComponent(new ::analyzer::Component("ContentsLine", 0)); + AddComponent(new ::analyzer::Component("CONTENTLINE", 0)); AddComponent(new ::analyzer::Component("Contents", 0)); plugin::Configuration config; diff --git a/src/plugin/Manager.cc b/src/plugin/Manager.cc index 3450006695..4fd895c232 100644 --- a/src/plugin/Manager.cc +++ b/src/plugin/Manager.cc @@ -83,7 +83,7 @@ void Manager::SearchDynamicPlugins(const std::string& dir) if ( name.empty() ) reporter->FatalError("empty plugin magic file %s", magic.c_str()); - if ( dynamic_plugins.find(name) != dynamic_plugins.end() ) + 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; @@ -281,7 +281,7 @@ void Manager::RegisterPlugin(Plugin *plugin) { Manager::PluginsInternal()->push_back(plugin); - if ( current_dir.size() && current_sopath.size() ) + if ( current_dir.size() && current_sopath.size() ) // A dynamic plugin, record its location. plugin->SetPluginLocation(current_dir.c_str(), current_sopath.c_str()); @@ -445,8 +445,18 @@ void Manager::DisableHook(HookType hook, Plugin* plugin) int Manager::HookLoadFile(const string& file) { + HookArgumentList args; + + if ( HavePluginForHook(META_HOOK_PRE) ) + { + args.push_back(HookArgument(file)); + MetaHookPre(HOOK_LOAD_FILE, args); + } + hook_list* l = hooks[HOOK_LOAD_FILE]; + int rc = -1; + for ( hook_list::iterator i = l->begin(); l && i != l->end(); i++ ) { Plugin* p = (*i).second; @@ -454,46 +464,84 @@ int Manager::HookLoadFile(const string& file) int rc = p->HookLoadFile(file); if ( rc >= 0 ) - return rc; + break; } - return -1; + if ( HavePluginForHook(META_HOOK_POST) ) + MetaHookPost(HOOK_LOAD_FILE, args, HookArgument(rc)); + + return rc; } -Val* Manager::HookCallFunction(const Func* func, val_list* args) const +Val* Manager::HookCallFunction(const Func* func, val_list* vargs) const { + HookArgumentList args; + + if ( HavePluginForHook(META_HOOK_PRE) ) + { + args.push_back(HookArgument(func)); + args.push_back(HookArgument(vargs)); + MetaHookPre(HOOK_CALL_FUNCTION, args); + } + hook_list* l = hooks[HOOK_CALL_FUNCTION]; + Val* v = 0; + for ( hook_list::iterator i = l->begin(); l && i != l->end(); i++ ) { Plugin* p = (*i).second; - Val* v = p->HookCallFunction(func, args); + v = p->HookCallFunction(func, vargs); if ( v ) - return v; + break; } - return 0; + if ( HavePluginForHook(META_HOOK_POST) ) + MetaHookPost(HOOK_CALL_FUNCTION, args, HookArgument(v)); + + return v; } bool Manager::HookQueueEvent(Event* event) const { + HookArgumentList args; + + if ( HavePluginForHook(META_HOOK_PRE) ) + { + args.push_back(HookArgument(event)); + MetaHookPre(HOOK_QUEUE_EVENT, args); + } + hook_list* l = hooks[HOOK_QUEUE_EVENT]; + bool result = false; + for ( hook_list::iterator i = l->begin(); l && i != l->end(); i++ ) { Plugin* p = (*i).second; - if ( p->HookQueueEvent(event) ) - return true; + if ( p->HookQueueEvent(event) ) + { + result = true; + break; + } } - return false; + if ( HavePluginForHook(META_HOOK_POST) ) + MetaHookPost(HOOK_QUEUE_EVENT, args, HookArgument(result)); + + return result; } void Manager::HookDrainEvents() const { + HookArgumentList args; + + if ( HavePluginForHook(META_HOOK_PRE) ) + MetaHookPre(HOOK_DRAIN_EVENTS, args); + hook_list* l = hooks[HOOK_DRAIN_EVENTS]; for ( hook_list::iterator i = l->begin(); l && i != l->end(); i++ ) @@ -501,10 +549,22 @@ void Manager::HookDrainEvents() const Plugin* p = (*i).second; p->HookDrainEvents(); } + + if ( HavePluginForHook(META_HOOK_POST) ) + MetaHookPost(HOOK_DRAIN_EVENTS, args, HookArgument()); + } void Manager::HookUpdateNetworkTime(double network_time) const { + HookArgumentList args; + + if ( HavePluginForHook(META_HOOK_PRE) ) + { + args.push_back(network_time); + MetaHookPre(HOOK_UPDATE_NETWORK_TIME, args); + } + hook_list* l = hooks[HOOK_UPDATE_NETWORK_TIME]; for ( hook_list::iterator i = l->begin(); l && i != l->end(); i++ ) @@ -512,4 +572,29 @@ void Manager::HookUpdateNetworkTime(double network_time) const Plugin* p = (*i).second; p->HookUpdateNetworkTime(network_time); } + + if ( HavePluginForHook(META_HOOK_POST) ) + MetaHookPost(HOOK_UPDATE_NETWORK_TIME, args, HookArgument()); + } + +void Manager::MetaHookPre(HookType hook, const HookArgumentList& 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; + p->MetaHookPre(hook, args); + } + } + +void Manager::MetaHookPost(HookType hook, const HookArgumentList& args, HookArgument result) const + { + hook_list* l = hooks[HOOK_CALL_FUNCTION]; + + for ( hook_list::iterator i = l->begin(); l && i != l->end(); i++ ) + { + Plugin* p = (*i).second; + p->MetaHookPost(hook, args, result); + } } diff --git a/src/plugin/Manager.h b/src/plugin/Manager.h index eb4b739963..1f1d3a772d 100644 --- a/src/plugin/Manager.h +++ b/src/plugin/Manager.h @@ -230,6 +230,8 @@ public: private: bool ActivateDynamicPluginInternal(const std::string& name); void UpdateInputFiles(); + void MetaHookPre(HookType hook, const HookArgumentList& args) const; + void MetaHookPost(HookType hook, const HookArgumentList& args, HookArgument result) const; // All found dynamic plugins, mapping their names to base directory. typedef std::map dynamic_plugin_map; diff --git a/src/plugin/Plugin.cc b/src/plugin/Plugin.cc index 90418f9498..b0aac907d9 100644 --- a/src/plugin/Plugin.cc +++ b/src/plugin/Plugin.cc @@ -9,11 +9,12 @@ #include "Component.h" #include "../Desc.h" +#include "../Event.h" using namespace plugin; -const char* hook_name(HookType h) - { +const char* plugin::hook_name(HookType h) +{ static const char* hook_names[int(NUM_HOOKS) + 1] = { // Order must match that of HookType. "LoadFile", @@ -21,6 +22,9 @@ const char* hook_name(HookType h) "QueueEvent", "DrainEvents", "UpdateNetworkTime", + // MetaHooks + "MetaHookPre", + "MetaHookPost", // End marker. "", }; @@ -55,6 +59,69 @@ BifItem::~BifItem() { } +void HookArgument::Describe(ODesc* d) const + { + switch ( type ) { + case BOOL: + d->Add(arg.bool_ ? "true" : "false"); + break; + + case DOUBLE: + d->Add(arg.double_); + break; + + case EVENT: + if ( arg.event ) + { + d->Add(arg.event->Handler()->Name()); + d->Add("("); + describe_vals(arg.event->Args(), d); + d->Add(")"); + } + else + d->Add(""); + break; + + case FUNC: + if ( arg.func ) + d->Add(arg.func->Name()); + else + d->Add(""); + break; + + case INT: + d->Add(arg.int_); + break; + + case STRING: + d->Add(arg_string); + break; + + case VAL: + if ( arg.val ) + arg.val->Describe(d); + + else + d->Add(""); + break; + + case VAL_LIST: + if ( arg.vals ) + { + d->Add("("); + describe_vals(arg.vals, d); + d->Add(")"); + } + else + d->Add(""); + break; + + case VOID: + d->Add(""); + break; + } + } + Plugin::Plugin() { dynamic = false; @@ -218,6 +285,14 @@ void Plugin::HookUpdateNetworkTime(double network_time) { } +void Plugin::MetaHookPre(HookType hook, const HookArgumentList& args) + { + } + +void Plugin::MetaHookPost(HookType hook, const HookArgumentList& args, HookArgument result) + { + } + void Plugin::Describe(ODesc* d) const { d->Add("Plugin: "); diff --git a/src/plugin/Plugin.h b/src/plugin/Plugin.h index 5c3dd73b03..2490a3e8ad 100644 --- a/src/plugin/Plugin.h +++ b/src/plugin/Plugin.h @@ -10,14 +10,14 @@ #include "analyzer/Component.h" #include "file_analysis/Component.h" +#define BRO_PLUGIN_API_VERSION 2 + class ODesc; class Func; class Event; namespace plugin { -#define BRO_PLUGIN_API_VERSION 2 - class Manager; class Component; class Plugin; @@ -33,10 +33,20 @@ enum HookType { HOOK_QUEUE_EVENT, HOOK_DRAIN_EVENTS, HOOK_UPDATE_NETWORK_TIME, + + // Meta hooks. + META_HOOK_PRE, + META_HOOK_POST, + // End marker. NUM_HOOKS, }; +/** + * Converts a hook type into a readable hook name. + */ +extern const char* hook_name(HookType h); + /** * Helper class to capture a plugin's version. A boolean operator evaluates * to true if the version has been set. @@ -59,7 +69,14 @@ public: std::string description; //< A short textual description of the plugin. Mandatory. VersionNumber version; //< THe plugin's version. Optional. - Configuration(); + Configuration() + { + // Note we inline this method here so that when plugins create an instance, + // *their* defaults will be used for the internal fields. + name = ""; + description = ""; + api_version = BRO_PLUGIN_API_VERSION; + } private: friend class Plugin; @@ -67,15 +84,6 @@ private: }; -// 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. */ @@ -126,6 +134,55 @@ private: Type type; }; +/** + * A class encapsulating an event argument to then pass along with a meta hook. + */ +class HookArgument +{ +public: + enum Type { + BOOL, DOUBLE, EVENT, FUNC, INT, STRING, VAL, VAL_LIST, VOID + }; + + HookArgument() { type = VOID; } + HookArgument(bool a) { type = BOOL; arg.bool_ = a; } + HookArgument(double a) { type = DOUBLE; arg.double_ = a; } + HookArgument(const Event* a) { type = EVENT; arg.event = a; } + HookArgument(const Func* a) { type = FUNC; arg.func = a; } + HookArgument(int a) { type = INT; arg.int_ = a; } + HookArgument(const std::string& a) { type = STRING; arg_string = a; } + HookArgument(const Val* a) { type = VAL; arg.val = a; } + HookArgument(const val_list* a) { type = VAL_LIST; arg.vals = a; } + + bool AsBool() const { assert(type == BOOL); return arg.bool_; } + double AsDouble() const { assert(type == DOUBLE); return arg.double_; } + const Event* AsEvent() const { assert(type == EVENT); return arg.event; } + const Func* AsFunc() const { assert(type == FUNC); return arg.func; } + double AsInt() const { assert(type == INT); return arg.int_; } + const std::string& AsString() const { assert(type == STRING); return arg_string; } + const Val* AsVal() const { assert(type == VAL); return arg.val; } + const val_list* AsValList() const { assert(type == VAL_LIST); return arg.vals; } + + Type GetType() const { return type; } + void Describe(ODesc* d) const; + +private: + Type type; + union { + bool bool_; + double double_; + const Event* event; + const Func* func; + int int_; + const Val* val; + const val_list* vals; + } arg; + + std::string arg_string; // Outside union because it has dtor. +}; + +typedef std::list HookArgumentList; + /** * Base class for all plugins. * @@ -439,6 +496,35 @@ protected: */ virtual void HookUpdateNetworkTime(double network_time); + // Meta hooks. + + /** + * A meta hook called just before another hook gets to execute. + * + * hook: The name of the hook about the execute. This will be the + * same as the corresponding method name (e.g., \c HookQueueEvent). + * + * hook: The type of the hook about to execute. + * + * args: A list of the hooks arguments. + */ + virtual void MetaHookPre(HookType hook, const HookArgumentList& args); + + /** + * A meta hook called just after another hook gets to execute. This + * will be called independent of whether there's an implementation + * for the hook. + * + * hook: The type of the hook that finished executing. + * + * args: A list of the hooks arguments. + * + * result: The result that executing the hook returned. If there's no + * implementation for the hook, this will be the default result. If + * the hook doesn't yield a result, this will be of type VOID. + */ + virtual void MetaHookPost(HookType hook, const HookArgumentList& args, HookArgument result); + // Methods that are used internally primarily. /**