diff --git a/NEWS b/NEWS index bb8e6e3ebf..297c60ee50 100644 --- a/NEWS +++ b/NEWS @@ -106,6 +106,11 @@ Removed Functionality Deprecated Functionality ------------------------ +- The ``plugin::Plugin::HookCallFunction()`` method is deprecated. Note + that compilers will not emit a deprecation warning, but the replacement + method to now use is called ``HookFunctionCall`` and uses ``IntrusivePtr`` + arguments and return value. + - The ``Func::Call(val_list*, ...)`` method is now deprecated. Use operator() instead which takes a ``zeek::Args`` (``std::vector>``). There's also a variadic template for operator() that forwards all arguments diff --git a/src/Discard.cc b/src/Discard.cc index 1984ced575..c5563f1cd8 100644 --- a/src/Discard.cc +++ b/src/Discard.cc @@ -43,7 +43,7 @@ bool Discarder::NextPacket(const IP_Hdr* ip, int len, int caplen) try { - discard_packet = check_ip->operator()(args)->AsBool(); + discard_packet = check_ip->operator()(&args)->AsBool(); } catch ( InterpreterException& e ) @@ -98,7 +98,7 @@ bool Discarder::NextPacket(const IP_Hdr* ip, int len, int caplen) try { - discard_packet = check_tcp->operator()(args)->AsBool(); + discard_packet = check_tcp->operator()(&args)->AsBool(); } catch ( InterpreterException& e ) @@ -122,7 +122,7 @@ bool Discarder::NextPacket(const IP_Hdr* ip, int len, int caplen) try { - discard_packet = check_udp->operator()(args)->AsBool(); + discard_packet = check_udp->operator()(&args)->AsBool(); } catch ( InterpreterException& e ) @@ -142,7 +142,7 @@ bool Discarder::NextPacket(const IP_Hdr* ip, int len, int caplen) try { - discard_packet = check_icmp->operator()(args)->AsBool(); + discard_packet = check_icmp->operator()(&args)->AsBool(); } catch ( InterpreterException& e ) diff --git a/src/Event.cc b/src/Event.cc index 11e34b0117..0f8c3b468b 100644 --- a/src/Event.cc +++ b/src/Event.cc @@ -56,7 +56,7 @@ void Event::Dispatch(bool no_remote) try { - handler->Call(args, no_remote); + handler->Call(&args, no_remote); } catch ( InterpreterException& e ) diff --git a/src/EventHandler.cc b/src/EventHandler.cc index 3be382b561..5e75fa6731 100644 --- a/src/EventHandler.cc +++ b/src/EventHandler.cc @@ -44,7 +44,7 @@ const IntrusivePtr& EventHandler::GetType(bool check_export) return type; } -void EventHandler::Call(const zeek::Args& vl, bool no_remote) +void EventHandler::Call(zeek::Args* vl, bool no_remote) { #ifdef PROFILE_BRO_FUNCTIONS DEBUG_MSG("Event: %s\n", Name()); @@ -59,12 +59,12 @@ void EventHandler::Call(const zeek::Args& vl, bool no_remote) { // Send event in form [name, xs...] where xs represent the arguments. broker::vector xs; - xs.reserve(vl.size()); + xs.reserve(vl->size()); bool valid_args = true; - for ( auto i = 0u; i < vl.size(); ++i ) + for ( auto i = 0u; i < vl->size(); ++i ) { - auto opt_data = bro_broker::val_to_data(vl[i].get()); + auto opt_data = bro_broker::val_to_data((*vl)[i].get()); if ( opt_data ) xs.emplace_back(std::move(*opt_data)); @@ -101,7 +101,7 @@ void EventHandler::Call(const zeek::Args& vl, bool no_remote) local->operator()(vl); } -void EventHandler::NewEvent(const zeek::Args& vl) +void EventHandler::NewEvent(zeek::Args* vl) { if ( ! new_event ) return; @@ -132,8 +132,8 @@ void EventHandler::NewEvent(const zeek::Args& vl) if ( fdefault ) rec->Assign(2, std::move(fdefault)); - if ( i < static_cast(vl.size()) && vl[i] ) - rec->Assign(3, vl[i]); + if ( i < static_cast(vl->size()) && (*vl)[i] ) + rec->Assign(3, (*vl)[i]); vargs->Assign(i, std::move(rec)); } diff --git a/src/EventHandler.h b/src/EventHandler.h index ccbd90e44b..c2a053cac8 100644 --- a/src/EventHandler.h +++ b/src/EventHandler.h @@ -45,7 +45,7 @@ public: auto_publish.erase(topic); } - void Call(const zeek::Args& vl, bool no_remote = false); + void Call(zeek::Args* vl, bool no_remote = false); // Returns true if there is at least one local or remote handler. explicit operator bool() const; @@ -66,7 +66,7 @@ public: bool GenerateAlways() { return generate_always; } private: - void NewEvent(const zeek::Args& vl); // Raise new_event() meta event. + void NewEvent(zeek::Args* vl); // Raise new_event() meta event. std::string name; IntrusivePtr local; diff --git a/src/Expr.cc b/src/Expr.cc index 4aa6bd0f30..4c1492e2d1 100644 --- a/src/Expr.cc +++ b/src/Expr.cc @@ -4133,7 +4133,8 @@ IntrusivePtr CallExpr::Eval(Frame* f) const if ( f ) f->SetCall(this); - ret = funcv->operator()(*v, f); + auto& args = *v; + ret = funcv->operator()(&args, f); if ( f ) f->SetCall(current_call); diff --git a/src/Func.cc b/src/Func.cc index d391310ac3..ec30fcc2b0 100644 --- a/src/Func.cc +++ b/src/Func.cc @@ -214,13 +214,13 @@ void Func::CopyStateInto(Func* other) const other->unique_id = unique_id; } -void Func::CheckPluginResult(bool hooked, const IntrusivePtr& hook_result, +void Func::CheckPluginResult(bool handled, const IntrusivePtr& hook_result, function_flavor flavor) const { // Helper function factoring out this code from BroFunc:Call() for // better readability. - if ( ! hooked ) + if ( ! handled ) { if ( hook_result ) reporter->InternalError("plugin set processed flag to false but actually returned a value"); @@ -297,9 +297,12 @@ bool BroFunc::IsPure() const } Val* Func::Call(val_list* args, Frame* parent) const - { return operator()(zeek::val_list_to_args(*args), parent).release(); }; + { + auto zargs = zeek::val_list_to_args(*args); + return operator()(&zargs, parent).release(); + }; -IntrusivePtr BroFunc::operator()(const zeek::Args& args, Frame* parent) const +IntrusivePtr BroFunc::operator()(zeek::Args* args, Frame* parent) const { #ifdef PROFILE_BRO_FUNCTIONS DEBUG_MSG("Function: %s\n", Name()); @@ -309,13 +312,13 @@ IntrusivePtr BroFunc::operator()(const zeek::Args& args, Frame* parent) con if ( sample_logger ) sample_logger->FunctionSeen(this); - auto [hooked, hook_result] = PLUGIN_HOOK_WITH_RESULT(HOOK_CALL_FUNCTION, - HookCallFunction(this, parent, args), - empty_hook_result); + auto [handled, hook_result] = PLUGIN_HOOK_WITH_RESULT(HOOK_CALL_FUNCTION, + HookCallFunction(this, parent, args), + empty_hook_result); - CheckPluginResult(hooked, hook_result, Flavor()); + CheckPluginResult(handled, hook_result, Flavor()); - if ( hooked ) + if ( handled ) return hook_result; if ( bodies.empty() ) @@ -325,7 +328,7 @@ IntrusivePtr BroFunc::operator()(const zeek::Args& args, Frame* parent) con return Flavor() == FUNC_FLAVOR_HOOK ? val_mgr->True() : nullptr; } - auto f = make_intrusive(frame_size, this, &args); + auto f = make_intrusive(frame_size, this, args); if ( closure ) f->CaptureClosure(closure, outer_ids); @@ -339,12 +342,12 @@ IntrusivePtr BroFunc::operator()(const zeek::Args& args, Frame* parent) con g_frame_stack.push_back(f.get()); // used for backtracing const CallExpr* call_expr = parent ? parent->GetCall() : nullptr; - call_stack.emplace_back(CallInfo{call_expr, this, args}); + call_stack.emplace_back(CallInfo{call_expr, this, *args}); if ( g_trace_state.DoTrace() ) { ODesc d; - DescribeDebug(&d, &args); + DescribeDebug(&d, args); g_trace_state.LogTrace("%s called: %s\n", GetType()->FlavorString().c_str(), d.Description()); @@ -360,16 +363,16 @@ IntrusivePtr BroFunc::operator()(const zeek::Args& args, Frame* parent) con body.stmts->GetLocationInfo()); // Fill in the rest of the frame with the function's arguments. - for ( auto j = 0u; j < args.size(); ++j ) + for ( auto j = 0u; j < args->size(); ++j ) { - Val* arg = args[j].get(); + Val* arg = (*args)[j].get(); if ( f->NthElement(j) != arg ) // Either not yet set, or somebody reassigned the frame slot. f->SetElement(j, arg->Ref()); } - f->Reset(args.size()); + f->Reset(args->size()); try { @@ -607,7 +610,7 @@ bool BuiltinFunc::IsPure() const return is_pure; } -IntrusivePtr BuiltinFunc::operator()(const zeek::Args& args, Frame* parent) const +IntrusivePtr BuiltinFunc::operator()(zeek::Args* args, Frame* parent) const { #ifdef PROFILE_BRO_FUNCTIONS DEBUG_MSG("Function: %s\n", Name()); @@ -617,26 +620,26 @@ IntrusivePtr BuiltinFunc::operator()(const zeek::Args& args, Frame* parent) if ( sample_logger ) sample_logger->FunctionSeen(this); - auto [hooked, hook_result] = PLUGIN_HOOK_WITH_RESULT(HOOK_CALL_FUNCTION, - HookCallFunction(this, parent, args), - empty_hook_result); + auto [handled, hook_result] = PLUGIN_HOOK_WITH_RESULT(HOOK_CALL_FUNCTION, + HookCallFunction(this, parent, args), + empty_hook_result); - CheckPluginResult(hooked, hook_result, FUNC_FLAVOR_FUNCTION); + CheckPluginResult(handled, hook_result, FUNC_FLAVOR_FUNCTION); - if ( hooked ) + if ( handled ) return hook_result; if ( g_trace_state.DoTrace() ) { ODesc d; - DescribeDebug(&d, &args); + DescribeDebug(&d, args); g_trace_state.LogTrace("\tBuiltin Function called: %s\n", d.Description()); } const CallExpr* call_expr = parent ? parent->GetCall() : nullptr; - call_stack.emplace_back(CallInfo{call_expr, this, args}); - auto result = std::move(func(parent, &args).rval); + call_stack.emplace_back(CallInfo{call_expr, this, *args}); + auto result = std::move(func(parent, args).rval); call_stack.pop_back(); if ( result && g_trace_state.DoTrace() ) diff --git a/src/Func.h b/src/Func.h index 848b7154bb..ef2cf34fab 100644 --- a/src/Func.h +++ b/src/Func.h @@ -60,7 +60,7 @@ public: * @param parent the frame from which the function is being called. * @return the return value of the function call. */ - virtual IntrusivePtr operator()(const zeek::Args& args, + virtual IntrusivePtr operator()(zeek::Args* args, Frame* parent = nullptr) const = 0; /** @@ -72,7 +72,10 @@ public: IntrusivePtr>, IntrusivePtr> operator()(Args&&... args) const - { return operator()(zeek::Args{std::forward(args)...}); } + { + auto zargs = zeek::Args{std::forward(args)...}; + return operator()(&zargs); + } // Add a new event handler to an existing function (event). virtual void AddBody(IntrusivePtr new_body, id_list* new_inits, @@ -110,7 +113,7 @@ protected: void CopyStateInto(Func* other) const; // Helper function for checking result of plugin hook. - void CheckPluginResult(bool hooked, const IntrusivePtr& hook_result, + void CheckPluginResult(bool handled, const IntrusivePtr& hook_result, function_flavor flavor) const; std::vector bodies; @@ -129,7 +132,7 @@ public: ~BroFunc() override; bool IsPure() const override; - IntrusivePtr operator()(const zeek::Args& args, Frame* parent) const override; + IntrusivePtr operator()(zeek::Args* args, Frame* parent) const override; /** * Adds adds a closure to the function. Closures are cloned and @@ -225,7 +228,7 @@ public: ~BuiltinFunc() override; bool IsPure() const override; - IntrusivePtr operator()(const zeek::Args& args, Frame* parent) const override; + IntrusivePtr operator()(zeek::Args* args, Frame* parent) const override; built_in_func TheFunc() const { return func; } void Describe(ODesc* d) const override; diff --git a/src/RuleCondition.cc b/src/RuleCondition.cc index ed179f1c85..c66d3a3b3f 100644 --- a/src/RuleCondition.cc +++ b/src/RuleCondition.cc @@ -181,7 +181,7 @@ bool RuleConditionEval::DoMatch(Rule* rule, RuleEndpointState* state, try { - auto val = id->GetVal()->AsFunc()->operator()(args); + auto val = id->GetVal()->AsFunc()->operator()(&args); result = val && val->AsBool(); } diff --git a/src/Val.cc b/src/Val.cc index 858ee40cdc..4fa0733091 100644 --- a/src/Val.cc +++ b/src/Val.cc @@ -1879,7 +1879,7 @@ IntrusivePtr TableVal::Default(const IntrusivePtr& index) try { - result = f->operator()(vl); + result = f->operator()(&vl); } catch ( InterpreterException& e ) @@ -2088,7 +2088,7 @@ void TableVal::CallChangeFunc(const Val* index, vl.emplace_back(old_value); in_change_func = true; - f->operator()(vl); + f->operator()(&vl); } catch ( InterpreterException& e ) { @@ -2545,7 +2545,7 @@ double TableVal::CallExpireFunc(IntrusivePtr idx) vl.emplace_back(std::move(idx)); } - auto result = f->operator()(vl); + auto result = f->operator()(&vl); if ( result ) secs = result->AsInterval(); diff --git a/src/broker/messaging.bif b/src/broker/messaging.bif index 6416fa7d41..14d6c43219 100644 --- a/src/broker/messaging.bif +++ b/src/broker/messaging.bif @@ -188,7 +188,7 @@ function Cluster::publish_rr%(pool: Pool, key: string, ...%): bool topic_func = global_scope()->Find("Cluster::rr_topic")->GetVal()->AsFunc(); zeek::Args vl{{NewRef{}, pool}, {NewRef{}, key}}; - auto topic = topic_func->operator()(vl); + auto topic = topic_func->operator()(&vl); if ( ! topic->AsString()->Len() ) return val_mgr->False(); @@ -225,7 +225,7 @@ function Cluster::publish_hrw%(pool: Pool, key: any, ...%): bool topic_func = global_scope()->Find("Cluster::hrw_topic")->GetVal()->AsFunc(); zeek::Args vl{{NewRef{}, pool}, {NewRef{}, key}}; - auto topic = topic_func->operator()(vl); + auto topic = topic_func->operator()(&vl); if ( ! topic->AsString()->Len() ) return val_mgr->False(); diff --git a/src/input/Manager.cc b/src/input/Manager.cc index d24dd960b3..88b30f098f 100644 --- a/src/input/Manager.cc +++ b/src/input/Manager.cc @@ -1768,7 +1768,7 @@ bool Manager::CallPred(Func* pred_func, const int numvals, ...) const va_end(lP); - auto v = pred_func->operator()(vl); + auto v = pred_func->operator()(&vl); if ( v ) result = v->AsBool(); diff --git a/src/option.bif b/src/option.bif index 14c65c1d50..91d5509c3c 100644 --- a/src/option.bif +++ b/src/option.bif @@ -24,7 +24,7 @@ static bool call_option_handlers_and_set_value(StringVal* name, const IntrusiveP if ( add_loc ) vl.emplace_back(NewRef{}, location); - val = handler_function->operator()(vl); // consumed by next call. + val = handler_function->operator()(&vl); // consumed by next call. if ( ! val ) { diff --git a/src/plugin/Manager.cc b/src/plugin/Manager.cc index 481cfcb14f..09a3bb5d9f 100644 --- a/src/plugin/Manager.cc +++ b/src/plugin/Manager.cc @@ -624,43 +624,35 @@ int Manager::HookLoadFile(const Plugin::LoadType type, const string& file, const std::pair> Manager::HookCallFunction(const Func* func, Frame* parent, - const zeek::Args& vecargs) const + zeek::Args* vecargs) const { HookArgumentList args; - std::optional vargs; + val_list vargs; if ( HavePluginForHook(META_HOOK_PRE) ) { - vargs = val_list(vecargs.size()); + vargs.resize(vecargs->size()); - for ( const auto& v : vecargs ) - vargs->push_back(v.get()); + for ( const auto& v : *vecargs ) + vargs.push_back(v.get()); args.push_back(HookArgument(func)); args.push_back(HookArgument(parent)); - args.push_back(HookArgument(&vargs.value())); + args.push_back(HookArgument(&vargs)); MetaHookPre(HOOK_CALL_FUNCTION, args); } hook_list* l = hooks[HOOK_CALL_FUNCTION]; - std::pair rval{false, nullptr}; + std::pair> rval{false, nullptr}; if ( l ) { - if ( ! vargs ) - { - vargs = val_list(vecargs.size()); - - for ( const auto& v : vecargs ) - vargs->push_back(v.get()); - } - for ( hook_list::iterator i = l->begin(); i != l->end(); ++i ) { Plugin* p = (*i).second; - rval = p->HookCallFunction(func, parent, &vargs.value()); + rval = p->HookFunctionCall(func, parent, vecargs); if ( rval.first ) break; @@ -668,9 +660,10 @@ Manager::HookCallFunction(const Func* func, Frame* parent, } if ( HavePluginForHook(META_HOOK_POST) ) - MetaHookPost(HOOK_CALL_FUNCTION, args, HookArgument(rval)); + MetaHookPost(HOOK_CALL_FUNCTION, args, + HookArgument(std::make_pair(rval.first, rval.second.get()))); - return {rval.first, {AdoptRef{}, rval.second}}; + return rval; } bool Manager::HookQueueEvent(Event* event) const diff --git a/src/plugin/Manager.h b/src/plugin/Manager.h index 514ec347e0..b3080cf733 100644 --- a/src/plugin/Manager.h +++ b/src/plugin/Manager.h @@ -256,7 +256,7 @@ public: * the method returns null. */ std::pair> - HookCallFunction(const Func* func, Frame* parent, const zeek::Args& args) const; + HookCallFunction(const Func* func, Frame* parent, zeek::Args* args) const; /** * Hook that filters the queuing of an event. diff --git a/src/plugin/Plugin.cc b/src/plugin/Plugin.cc index 5538b87b28..262ee2cc64 100644 --- a/src/plugin/Plugin.cc +++ b/src/plugin/Plugin.cc @@ -151,6 +151,17 @@ void HookArgument::Describe(ODesc* d) const d->Add(""); break; + case ARG_LIST: + if ( arg.args) + { + d->Add("("); + describe_vals(*arg.args, d); + d->Add(")"); + } + else + d->Add(""); + break; + case VOID: d->Add(""); break; @@ -364,6 +375,26 @@ int Plugin::HookLoadFile(const LoadType type, const std::string& file, const std return -1; } +std::pair> +Plugin::HookFunctionCall(const Func* func, Frame* parent, + zeek::Args* args) + { + val_list vlargs(args->size()); + + for ( auto& v : *args ) + vlargs.push_back(v.release()); + +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Wdeprecated-declarations" + auto [handled, result] = HookCallFunction(func, parent, &vlargs); +#pragma GCC diagnostic pop + + for ( auto i = 0u; i < args->size(); ++i ) + (*args)[i] = {AdoptRef{}, vlargs[i]}; + + return {handled, {AdoptRef{}, result}}; + } + std::pair Plugin::HookCallFunction(const Func* func, Frame *parent, val_list* args) { std::pair result(false, NULL); diff --git a/src/plugin/Plugin.h b/src/plugin/Plugin.h index b218c693d7..096b796429 100644 --- a/src/plugin/Plugin.h +++ b/src/plugin/Plugin.h @@ -8,6 +8,7 @@ #include "zeek-config.h" #include "logging/WriterBackend.h" +#include "ZeekArgs.h" // Increase this when making incompatible changes to the plugin API. Note // that the constant is never used in C code. It's picked up on by CMake. @@ -177,7 +178,8 @@ public: */ enum Type { BOOL, DOUBLE, EVENT, FRAME, FUNC, FUNC_RESULT, INT, STRING, VAL, - VAL_LIST, VOID, VOIDP, WRITER_INFO, CONN, THREAD_FIELDS, LOCATION + VAL_LIST, VOID, VOIDP, WRITER_INFO, CONN, THREAD_FIELDS, LOCATION, + ARG_LIST }; /** @@ -260,6 +262,11 @@ public: */ explicit HookArgument(const Location* location) { type = LOCATION; arg.loc = location; } + /** + * Constructor with a zeek::Args argument. + */ + explicit HookArgument(const zeek::Args* args) { type = ARG_LIST; arg.args = args; } + /** * Returns the value for a boolen argument. The argument's type must * match accordingly. @@ -338,6 +345,11 @@ public: */ const val_list* AsValList() const { assert(type == VAL_LIST); return arg.vals; } + /** + * Returns the value as a zeek::Args. + */ + const zeek::Args* AsArgList() const { assert(type == ARG_LIST); return arg.args; } + /** * Returns the value for a vod pointer argument. The argument's type * must match accordingly. @@ -368,6 +380,7 @@ private: int int_; const Val* val; const val_list* vals; + const zeek::Args* args; const void* voidp; const logging::WriterBackend::WriterInfo* winfo; const Location* loc; @@ -664,12 +677,15 @@ protected: * in place as long as it ensures matching types and correct reference * counting. * - * @return If the plugin handled the call, a std::pair with the - * processed flag set to true, and a value set on the object with - * a+1 reference count containing the result value to pass back to the - * interpreter. If the plugin did not handle the call, it must - * return a pair with the processed flag set to 'false'. + * @return If the plugin handled the call, a pair with the first member + * set to true, and a Val representing the result value to pass back to the + * interpreter. If the plugin did not handle the call, it must return a + * pair with the first member set to 'false' and null result value. */ + virtual std::pair> + HookFunctionCall(const Func* func, Frame* parent, zeek::Args* args); + + [[deprecated("Remove in v4.1. Use HookFunctionCall()")]] virtual std::pair HookCallFunction(const Func* func, Frame *parent, val_list* args); /** diff --git a/testing/btest/Baseline/plugins.func-hook/output b/testing/btest/Baseline/plugins.func-hook/output new file mode 100644 index 0000000000..21e27b43c0 --- /dev/null +++ b/testing/btest/Baseline/plugins.func-hook/output @@ -0,0 +1,4 @@ +1590206064.237264 MetaHookPre CallFunction(foo, , (1, 2, 3, yo)) +1590206064.237264 | HookFunctionCall foo(1, 2, 3, yo) +1590206064.237264 MetaHookPost CallFunction(foo, , (1, 2, 3, yo)) -> +foo, 42, 2, 3, yo diff --git a/testing/btest/Baseline/plugins.legacy-func-hook/output b/testing/btest/Baseline/plugins.legacy-func-hook/output new file mode 100644 index 0000000000..1d00ed4d5d --- /dev/null +++ b/testing/btest/Baseline/plugins.legacy-func-hook/output @@ -0,0 +1,4 @@ +1590205948.002795 MetaHookPre CallFunction(foo, , (1, 2, 3, yo)) +1590205948.002795 | HookCallFunction foo(1, 2, 3, yo) +1590205948.002795 MetaHookPost CallFunction(foo, , (1, 2, 3, yo)) -> +foo, 13, 2, 3, yo diff --git a/testing/btest/plugins/func-hook-plugin/.btest-ignore b/testing/btest/plugins/func-hook-plugin/.btest-ignore new file mode 100644 index 0000000000..e69de29bb2 diff --git a/testing/btest/plugins/func-hook-plugin/src/Plugin.cc b/testing/btest/plugins/func-hook-plugin/src/Plugin.cc new file mode 100644 index 0000000000..f1b089e65e --- /dev/null +++ b/testing/btest/plugins/func-hook-plugin/src/Plugin.cc @@ -0,0 +1,86 @@ + +#include "Plugin.h" + +#include +#include +#include +#include +#include +#include + +namespace plugin { namespace Demo_Hooks { Plugin plugin; } } + +using namespace plugin::Demo_Hooks; + +plugin::Configuration Plugin::Configure() + { + EnableHook(HOOK_CALL_FUNCTION); + EnableHook(META_HOOK_PRE); + EnableHook(META_HOOK_POST); + + plugin::Configuration config; + config.name = "Demo::Hooks"; + config.description = "Exercises all plugin hooks"; + config.version.major = 1; + config.version.minor = 0; + config.version.patch = 0; + return config; + } + +static void describe_hook_args(const plugin::HookArgumentList& args, ODesc* d) + { + bool first = true; + + for ( plugin::HookArgumentList::const_iterator i = args.begin(); i != args.end(); i++ ) + { + if ( ! first ) + d->Add(", "); + + i->Describe(d); + first = false; + } + } + +std::pair> Plugin::HookFunctionCall(const Func* func, + Frame* frame, + zeek::Args* args) + { + ODesc d; + d.SetShort(); + HookArgument(func).Describe(&d); + HookArgument(args).Describe(&d); + fprintf(stderr, "%.6f %-15s %s\n", network_time, "| HookFunctionCall", + d.Description()); + + if ( streq(func->Name(), "foo") ) + { + auto& vl = *args; + vl[0] = val_mgr->Count(42); + } + + return {}; + } + +void Plugin::MetaHookPre(HookType hook, const HookArgumentList& args) + { + ODesc d; + d.SetShort(); + describe_hook_args(args, &d); + fprintf(stderr, "%.6f %-15s %s(%s)\n", network_time, " MetaHookPre", + hook_name(hook), d.Description()); + } + +void Plugin::MetaHookPost(HookType hook, const HookArgumentList& args, HookArgument result) + { + ODesc d1; + d1.SetShort(); + describe_hook_args(args, &d1); + + ODesc d2; + d2.SetShort(); + result.Describe(&d2); + + fprintf(stderr, "%.6f %-15s %s(%s) -> %s\n", network_time, " MetaHookPost", + hook_name(hook), d1.Description(), + d2.Description()); + } diff --git a/testing/btest/plugins/func-hook-plugin/src/Plugin.h b/testing/btest/plugins/func-hook-plugin/src/Plugin.h new file mode 100644 index 0000000000..c480466e9e --- /dev/null +++ b/testing/btest/plugins/func-hook-plugin/src/Plugin.h @@ -0,0 +1,27 @@ + +#pragma once + +#include + +namespace plugin { +namespace Demo_Hooks { + +class Plugin : public ::plugin::Plugin +{ +protected: + + std::pair> HookFunctionCall(const Func* func, + Frame* frame, + zeek::Args* args) override; + + void MetaHookPre(HookType hook, const HookArgumentList& args) override; + void MetaHookPost(HookType hook, const HookArgumentList& args, HookArgument result) override; + + // Overridden from plugin::Plugin. + plugin::Configuration Configure() override; +}; + +extern Plugin plugin; + +} +} diff --git a/testing/btest/plugins/func-hook.zeek b/testing/btest/plugins/func-hook.zeek new file mode 100644 index 0000000000..5a9d2c6e48 --- /dev/null +++ b/testing/btest/plugins/func-hook.zeek @@ -0,0 +1,17 @@ +# @TEST-EXEC: ${DIST}/aux/zeek-aux/plugin-support/init-plugin -u . Demo Hooks +# @TEST-EXEC: cp -r %DIR/func-hook-plugin/* . +# @TEST-EXEC: ./configure --zeek-dist=${DIST} && make +# @TEST-EXEC: ZEEK_PLUGIN_ACTIVATE="Demo::Hooks" ZEEK_PLUGIN_PATH=`pwd` zeek -b %INPUT 2>&1 | grep foo >output +# @TEST-EXEC: btest-diff output + +@unload base/misc/version + +function foo(a: count, b: count, c: count, s: string) + { + print "foo", a, b, c, s; + } + +event zeek_init() + { + foo(1, 2, 3, "yo"); + } diff --git a/testing/btest/plugins/legacy-func-hook-plugin/.btest-ignore b/testing/btest/plugins/legacy-func-hook-plugin/.btest-ignore new file mode 100644 index 0000000000..e69de29bb2 diff --git a/testing/btest/plugins/legacy-func-hook-plugin/src/Plugin.cc b/testing/btest/plugins/legacy-func-hook-plugin/src/Plugin.cc new file mode 100644 index 0000000000..c4f06fc651 --- /dev/null +++ b/testing/btest/plugins/legacy-func-hook-plugin/src/Plugin.cc @@ -0,0 +1,105 @@ + +#include "Plugin.h" + +#include +#include +#include +#include +#include +#include + +namespace plugin { namespace Demo_Hooks { Plugin plugin; } } + +using namespace plugin::Demo_Hooks; + +plugin::Configuration Plugin::Configure() + { + EnableHook(HOOK_CALL_FUNCTION); + EnableHook(META_HOOK_PRE); + EnableHook(META_HOOK_POST); + + plugin::Configuration config; + config.name = "Demo::Hooks"; + config.description = "Exercises all plugin hooks"; + config.version.major = 1; + config.version.minor = 0; + config.version.patch = 0; + return config; + } + +static void describe_hook_args(const plugin::HookArgumentList& args, ODesc* d) + { + bool first = true; + + for ( plugin::HookArgumentList::const_iterator i = args.begin(); i != args.end(); i++ ) + { + if ( ! first ) + d->Add(", "); + + i->Describe(d); + first = false; + } + } + +std::pair Plugin::HookCallFunction(const Func* func, Frame* frame, val_list* args) + { + ODesc d; + d.SetShort(); + HookArgument(func).Describe(&d); + HookArgument(args).Describe(&d); + fprintf(stderr, "%.6f %-15s %s\n", network_time, "| HookCallFunction", + d.Description()); + + if ( streq(func->Name(), "foo") ) + { + auto& vl = *args; + Unref(vl[0]); + vl[0] = val_mgr->Count(13).release(); + } + + return {}; + } + +/* std::pair> Plugin::HookFunctionCall(const Func* func, */ +/* Frame* frame, */ +/* zeek::Args* args) */ +/* { */ +/* ODesc d; */ +/* d.SetShort(); */ +/* HookArgument(func).Describe(&d); */ +/* HookArgument(args).Describe(&d); */ +/* fprintf(stderr, "%.6f %-15s %s\n", network_time, "| HookFunctionCall", */ +/* d.Description()); */ + +/* if ( streq(func->Name(), "foo") ) */ +/* { */ +/* auto& vl = *args; */ +/* vl[0] = val_mgr->Count(42); */ +/* } */ + +/* return {}; */ +/* } */ + +void Plugin::MetaHookPre(HookType hook, const HookArgumentList& args) + { + ODesc d; + d.SetShort(); + describe_hook_args(args, &d); + fprintf(stderr, "%.6f %-15s %s(%s)\n", network_time, " MetaHookPre", + hook_name(hook), d.Description()); + } + +void Plugin::MetaHookPost(HookType hook, const HookArgumentList& args, HookArgument result) + { + ODesc d1; + d1.SetShort(); + describe_hook_args(args, &d1); + + ODesc d2; + d2.SetShort(); + result.Describe(&d2); + + fprintf(stderr, "%.6f %-15s %s(%s) -> %s\n", network_time, " MetaHookPost", + hook_name(hook), d1.Description(), + d2.Description()); + } diff --git a/testing/btest/plugins/legacy-func-hook-plugin/src/Plugin.h b/testing/btest/plugins/legacy-func-hook-plugin/src/Plugin.h new file mode 100644 index 0000000000..305192b31e --- /dev/null +++ b/testing/btest/plugins/legacy-func-hook-plugin/src/Plugin.h @@ -0,0 +1,28 @@ + +#pragma once + +#include + +namespace plugin { +namespace Demo_Hooks { + +class Plugin : public ::plugin::Plugin +{ +protected: + std::pair HookCallFunction(const Func* func, Frame* frame, val_list* args) override; + + /* std::pair> HookFunctionCall(const Func* func, */ + /* Frame* frame, */ + /* zeek::Args* args) override; */ + + void MetaHookPre(HookType hook, const HookArgumentList& args) override; + void MetaHookPost(HookType hook, const HookArgumentList& args, HookArgument result) override; + + // Overridden from plugin::Plugin. + plugin::Configuration Configure() override; +}; + +extern Plugin plugin; + +} +} diff --git a/testing/btest/plugins/legacy-func-hook.zeek b/testing/btest/plugins/legacy-func-hook.zeek new file mode 100644 index 0000000000..75e6301d6f --- /dev/null +++ b/testing/btest/plugins/legacy-func-hook.zeek @@ -0,0 +1,17 @@ +# @TEST-EXEC: ${DIST}/aux/zeek-aux/plugin-support/init-plugin -u . Demo Hooks +# @TEST-EXEC: cp -r %DIR/legacy-func-hook-plugin/* . +# @TEST-EXEC: ./configure --zeek-dist=${DIST} && make +# @TEST-EXEC: ZEEK_PLUGIN_ACTIVATE="Demo::Hooks" ZEEK_PLUGIN_PATH=`pwd` zeek -b %INPUT 2>&1 | grep foo >output +# @TEST-EXEC: btest-diff output + +@unload base/misc/version + +function foo(a: count, b: count, c: count, s: string) + { + print "foo", a, b, c, s; + } + +event zeek_init() + { + foo(1, 2, 3, "yo"); + }