Deprecate Plugin::HookCallFunction(), replace with HookFunctionCall()

This also changes the argument type of Func::operator() to zeek::Args*
to allow plugins to be able to alter function arguments in place as
was previously documented.
This commit is contained in:
Jon Siwek 2020-05-22 21:01:38 -07:00
parent 46c5dea733
commit 272db640aa
27 changed files with 417 additions and 77 deletions

5
NEWS
View file

@ -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<IntrusivePtr<Val>>``).
There's also a variadic template for operator() that forwards all arguments

View file

@ -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 )

View file

@ -56,7 +56,7 @@ void Event::Dispatch(bool no_remote)
try
{
handler->Call(args, no_remote);
handler->Call(&args, no_remote);
}
catch ( InterpreterException& e )

View file

@ -44,7 +44,7 @@ const IntrusivePtr<FuncType>& 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<int>(vl.size()) && vl[i] )
rec->Assign(3, vl[i]);
if ( i < static_cast<int>(vl->size()) && (*vl)[i] )
rec->Assign(3, (*vl)[i]);
vargs->Assign(i, std::move(rec));
}

View file

@ -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<Func> local;

View file

@ -4133,7 +4133,8 @@ IntrusivePtr<Val> 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);

View file

@ -214,13 +214,13 @@ void Func::CopyStateInto(Func* other) const
other->unique_id = unique_id;
}
void Func::CheckPluginResult(bool hooked, const IntrusivePtr<Val>& hook_result,
void Func::CheckPluginResult(bool handled, const IntrusivePtr<Val>& 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<Val> BroFunc::operator()(const zeek::Args& args, Frame* parent) const
IntrusivePtr<Val> BroFunc::operator()(zeek::Args* args, Frame* parent) const
{
#ifdef PROFILE_BRO_FUNCTIONS
DEBUG_MSG("Function: %s\n", Name());
@ -309,13 +312,13 @@ IntrusivePtr<Val> 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,
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<Val> BroFunc::operator()(const zeek::Args& args, Frame* parent) con
return Flavor() == FUNC_FLAVOR_HOOK ? val_mgr->True() : nullptr;
}
auto f = make_intrusive<Frame>(frame_size, this, &args);
auto f = make_intrusive<Frame>(frame_size, this, args);
if ( closure )
f->CaptureClosure(closure, outer_ids);
@ -339,12 +342,12 @@ IntrusivePtr<Val> 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<Val> 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<Val> BuiltinFunc::operator()(const zeek::Args& args, Frame* parent) const
IntrusivePtr<Val> BuiltinFunc::operator()(zeek::Args* args, Frame* parent) const
{
#ifdef PROFILE_BRO_FUNCTIONS
DEBUG_MSG("Function: %s\n", Name());
@ -617,26 +620,26 @@ IntrusivePtr<Val> 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,
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() )

View file

@ -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<Val> operator()(const zeek::Args& args,
virtual IntrusivePtr<Val> operator()(zeek::Args* args,
Frame* parent = nullptr) const = 0;
/**
@ -72,7 +72,10 @@ public:
IntrusivePtr<Val>>,
IntrusivePtr<Val>>
operator()(Args&&... args) const
{ return operator()(zeek::Args{std::forward<Args>(args)...}); }
{
auto zargs = zeek::Args{std::forward<Args>(args)...};
return operator()(&zargs);
}
// Add a new event handler to an existing function (event).
virtual void AddBody(IntrusivePtr<Stmt> 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<Val>& hook_result,
void CheckPluginResult(bool handled, const IntrusivePtr<Val>& hook_result,
function_flavor flavor) const;
std::vector<Body> bodies;
@ -129,7 +132,7 @@ public:
~BroFunc() override;
bool IsPure() const override;
IntrusivePtr<Val> operator()(const zeek::Args& args, Frame* parent) const override;
IntrusivePtr<Val> 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<Val> operator()(const zeek::Args& args, Frame* parent) const override;
IntrusivePtr<Val> operator()(zeek::Args* args, Frame* parent) const override;
built_in_func TheFunc() const { return func; }
void Describe(ODesc* d) const override;

View file

@ -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();
}

View file

@ -1879,7 +1879,7 @@ IntrusivePtr<Val> TableVal::Default(const IntrusivePtr<Val>& 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<ListVal> idx)
vl.emplace_back(std::move(idx));
}
auto result = f->operator()(vl);
auto result = f->operator()(&vl);
if ( result )
secs = result->AsInterval();

View file

@ -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();

View file

@ -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();

View file

@ -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 )
{

View file

@ -624,43 +624,35 @@ int Manager::HookLoadFile(const Plugin::LoadType type, const string& file, const
std::pair<bool, IntrusivePtr<Val>>
Manager::HookCallFunction(const Func* func, Frame* parent,
const zeek::Args& vecargs) const
zeek::Args* vecargs) const
{
HookArgumentList args;
std::optional<val_list> 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<bool, Val*> rval{false, nullptr};
std::pair<bool, IntrusivePtr<Val>> 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

View file

@ -256,7 +256,7 @@ public:
* the method returns null.
*/
std::pair<bool, IntrusivePtr<Val>>
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.

View file

@ -151,6 +151,17 @@ void HookArgument::Describe(ODesc* d) const
d->Add("<null>");
break;
case ARG_LIST:
if ( arg.args)
{
d->Add("(");
describe_vals(*arg.args, d);
d->Add(")");
}
else
d->Add("<null>");
break;
case VOID:
d->Add("<void>");
break;
@ -364,6 +375,26 @@ int Plugin::HookLoadFile(const LoadType type, const std::string& file, const std
return -1;
}
std::pair<bool, IntrusivePtr<Val>>
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<bool, Val*> Plugin::HookCallFunction(const Func* func, Frame *parent, val_list* args)
{
std::pair<bool, Val*> result(false, NULL);

View file

@ -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<bool, Val*> 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<bool, IntrusivePtr<Val>>
HookFunctionCall(const Func* func, Frame* parent, zeek::Args* args);
[[deprecated("Remove in v4.1. Use HookFunctionCall()")]]
virtual std::pair<bool, Val*> HookCallFunction(const Func* func, Frame *parent, val_list* args);
/**

View file

@ -0,0 +1,4 @@
1590206064.237264 MetaHookPre CallFunction(foo, <frame>, (1, 2, 3, yo))
1590206064.237264 | HookFunctionCall foo(1, 2, 3, yo)
1590206064.237264 MetaHookPost CallFunction(foo, <frame>, (1, 2, 3, yo)) -> <no result>
foo, 42, 2, 3, yo

View file

@ -0,0 +1,4 @@
1590205948.002795 MetaHookPre CallFunction(foo, <frame>, (1, 2, 3, yo))
1590205948.002795 | HookCallFunction foo(1, 2, 3, yo)
1590205948.002795 MetaHookPost CallFunction(foo, <frame>, (1, 2, 3, yo)) -> <no result>
foo, 13, 2, 3, yo

View file

@ -0,0 +1,86 @@
#include "Plugin.h"
#include <Val.h>
#include <Func.h>
#include <Event.h>
#include <Conn.h>
#include <Desc.h>
#include <threading/Formatter.h>
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<bool, IntrusivePtr<Val>> 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());
}

View file

@ -0,0 +1,27 @@
#pragma once
#include <plugin/Plugin.h>
namespace plugin {
namespace Demo_Hooks {
class Plugin : public ::plugin::Plugin
{
protected:
std::pair<bool, IntrusivePtr<Val>> 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;
}
}

View file

@ -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");
}

View file

@ -0,0 +1,105 @@
#include "Plugin.h"
#include <Val.h>
#include <Func.h>
#include <Event.h>
#include <Conn.h>
#include <Desc.h>
#include <threading/Formatter.h>
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<bool, Val*> 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<bool, IntrusivePtr<Val>> 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());
}

View file

@ -0,0 +1,28 @@
#pragma once
#include <plugin/Plugin.h>
namespace plugin {
namespace Demo_Hooks {
class Plugin : public ::plugin::Plugin
{
protected:
std::pair<bool, Val*> HookCallFunction(const Func* func, Frame* frame, val_list* args) override;
/* std::pair<bool, IntrusivePtr<Val>> 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;
}
}

View file

@ -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");
}