mirror of
https://github.com/zeek/zeek.git
synced 2025-10-02 06:38:20 +00:00

This class is a parameter of virtual methods of the Backend API for users to implement and also a parameter to the HookPublishEvent() API. Seems it shouldn't be in detail and instead we should own it. Alternatively, could mark the cluster APIs as not-stable-yet, but I think we can move forward and make it non-detail for 8.0.
441 lines
12 KiB
C++
441 lines
12 KiB
C++
// See the file "COPYING" in the main distribution directory for copyright.
|
|
|
|
#include "zeek/plugin/Plugin.h"
|
|
|
|
#include <cassert>
|
|
|
|
#include "zeek/Conn.h"
|
|
#include "zeek/Desc.h"
|
|
#include "zeek/Event.h"
|
|
#include "zeek/Func.h"
|
|
#include "zeek/Val.h"
|
|
#include "zeek/cluster/Backend.h"
|
|
#include "zeek/input.h"
|
|
#include "zeek/plugin/Component.h"
|
|
#include "zeek/plugin/Manager.h"
|
|
#include "zeek/threading/SerialTypes.h"
|
|
|
|
namespace zeek::plugin {
|
|
|
|
const char* hook_name(HookType h) {
|
|
static constexpr const char* hook_names[int(NUM_HOOKS) + 1] = {
|
|
// Order must match that of HookType.
|
|
"LoadFile",
|
|
"LoadFileExtended",
|
|
"CallFunction",
|
|
"QueueEvent",
|
|
"DrainEvents",
|
|
"UpdateNetworkTime",
|
|
"SetupAnalyzerTree",
|
|
"LogInit",
|
|
"LogWrite",
|
|
"Reporter",
|
|
"UnprocessedPacket",
|
|
"ObjDtor",
|
|
"PublishEvent",
|
|
// MetaHooks
|
|
"MetaHookPre",
|
|
"MetaHookPost",
|
|
// End marker.
|
|
"<end>",
|
|
};
|
|
|
|
return hook_names[int(h)];
|
|
}
|
|
|
|
BifItem::BifItem(const std::string& arg_id, Type arg_type) {
|
|
id = arg_id;
|
|
type = arg_type;
|
|
}
|
|
|
|
BifItem::BifItem(const BifItem& other) {
|
|
id = other.id;
|
|
type = other.type;
|
|
}
|
|
|
|
BifItem& BifItem::operator=(const BifItem& other) {
|
|
if ( this != &other ) {
|
|
id = other.id;
|
|
type = other.type;
|
|
}
|
|
|
|
return *this;
|
|
}
|
|
|
|
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("<null>");
|
|
break;
|
|
|
|
case CONN:
|
|
if ( arg.conn )
|
|
arg.conn->Describe(d);
|
|
break;
|
|
|
|
case FUNC_RESULT:
|
|
if ( func_result.first ) {
|
|
if ( func_result.second )
|
|
func_result.second->Describe(d);
|
|
else
|
|
d->Add("<null>");
|
|
}
|
|
else
|
|
d->Add("<no result>");
|
|
|
|
break;
|
|
|
|
case FRAME:
|
|
if ( arg.frame )
|
|
d->Add("<frame>");
|
|
else
|
|
d->Add("<null>");
|
|
break;
|
|
|
|
case FUNC:
|
|
if ( arg.func )
|
|
d->Add(arg.func->GetName());
|
|
else
|
|
d->Add("<null>");
|
|
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("<null>");
|
|
break;
|
|
|
|
case VAL_LIST:
|
|
if ( arg.vals ) {
|
|
d->Add("(");
|
|
describe_vals(arg.vals, d);
|
|
d->Add(")");
|
|
}
|
|
else
|
|
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;
|
|
|
|
case VOIDP: d->Add("<void ptr>"); break;
|
|
|
|
case WRITER_INFO: {
|
|
d->Add(arg.winfo->path);
|
|
d->Add("(");
|
|
d->Add(arg.winfo->network_time);
|
|
d->Add(",");
|
|
d->Add(arg.winfo->rotation_interval);
|
|
d->Add(",");
|
|
d->Add(arg.winfo->rotation_base);
|
|
|
|
if ( arg.winfo->config.size() > 0 ) {
|
|
bool first = true;
|
|
d->Add("config: {");
|
|
|
|
for ( auto& v : arg.winfo->config ) {
|
|
if ( ! first )
|
|
d->Add(", ");
|
|
|
|
d->Add(v.first);
|
|
d->Add(": ");
|
|
d->Add(v.second);
|
|
first = false;
|
|
}
|
|
|
|
d->Add("}");
|
|
}
|
|
|
|
d->Add(")");
|
|
} break;
|
|
|
|
case THREAD_FIELDS: {
|
|
d->Add("{");
|
|
|
|
for ( int i = 0; i < tfields.first; i++ ) {
|
|
const threading::Field* f = tfields.second[i];
|
|
|
|
if ( i > 0 )
|
|
d->Add(", ");
|
|
|
|
d->Add(f->name);
|
|
d->Add(" (");
|
|
d->Add(f->TypeName());
|
|
d->Add(")");
|
|
}
|
|
|
|
d->Add("}");
|
|
} break;
|
|
|
|
case LOCATION:
|
|
if ( arg.loc ) {
|
|
arg.loc->Describe(d);
|
|
}
|
|
else {
|
|
d->Add("<no location>");
|
|
}
|
|
break;
|
|
|
|
case INPUT_FILE: {
|
|
d->Add("(");
|
|
d->Add(input_file.first);
|
|
d->Add(", ");
|
|
if ( input_file.second )
|
|
d->Add(input_file.second->substr(0, 20)); // cut content off
|
|
else
|
|
d->Add("<no content>");
|
|
|
|
d->Add(")");
|
|
break;
|
|
}
|
|
|
|
case PACKET: d->Add("<packet>"); break;
|
|
|
|
case CLUSTER_BACKEND: {
|
|
d->Add("<cluster backend ");
|
|
d->Add(arg.cluster_backend->Name());
|
|
d->Add(">");
|
|
break;
|
|
}
|
|
|
|
case CLUSTER_EVENT: {
|
|
auto* ce = arg.cluster_event;
|
|
d->Add("<cluster event ");
|
|
d->AddN(ce->HandlerName().data(), static_cast<int>(ce->HandlerName().size()));
|
|
d->Add(", ");
|
|
d->Add(static_cast<uint64_t>(ce->Args().size()));
|
|
d->Add(util::fmt(" argument%s>", ce->Args().size() != 1 ? "s" : ""));
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
Plugin::Plugin() {
|
|
dynamic = false;
|
|
Manager::RegisterPlugin(this);
|
|
}
|
|
|
|
Plugin::~Plugin() { Done(); }
|
|
|
|
void Plugin::DoConfigure() { config = Configure(); }
|
|
|
|
const std::string& Plugin::Name() const { return config.name; }
|
|
|
|
const std::string& Plugin::Description() const { return config.description; }
|
|
|
|
VersionNumber Plugin::Version() const { return config.version; }
|
|
|
|
bool Plugin::DynamicPlugin() const { return dynamic; }
|
|
|
|
const std::string& Plugin::PluginDirectory() const { return base_dir; }
|
|
|
|
const std::string& Plugin::PluginPath() const { return sopath; }
|
|
|
|
void Plugin::SetPluginLocation(const std::string& arg_dir, const std::string& arg_sopath) {
|
|
base_dir = arg_dir;
|
|
sopath = arg_sopath;
|
|
}
|
|
|
|
void Plugin::SetDynamic(bool is_dynamic) { dynamic = is_dynamic; }
|
|
|
|
void Plugin::InitPreScript() {}
|
|
|
|
void Plugin::InitPostScript() {}
|
|
|
|
void Plugin::InitPreExecution() {}
|
|
|
|
Plugin::bif_item_list Plugin::BifItems() const { return bif_items; }
|
|
|
|
void Plugin::Done() {
|
|
for ( component_list::const_iterator i = components.begin(); i != components.end(); i++ )
|
|
delete *i;
|
|
|
|
components.clear();
|
|
}
|
|
|
|
Plugin::component_list Plugin::Components() const { return components; }
|
|
|
|
static bool component_cmp(const Component* a, const Component* b) { return a->Name() < b->Name(); }
|
|
|
|
bool Plugin::LoadZeekFile(const std::string& file) {
|
|
::add_input_file(file.c_str());
|
|
return true;
|
|
}
|
|
|
|
void Plugin::AddBifItem(const std::string& name, BifItem::Type type) {
|
|
BifItem bi(name, (BifItem::Type)type);
|
|
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); }
|
|
|
|
void Plugin::RequestEvent(EventHandlerPtr handler) { plugin_mgr->RequestEvent(handler, this); }
|
|
|
|
void Plugin::RequestObjDtor(Obj* obj) { plugin_mgr->RequestObjDtor(obj, this); }
|
|
|
|
int Plugin::HookLoadFile(const LoadType type, const std::string& file, const std::string& resolved) { return -1; }
|
|
|
|
std::pair<int, std::optional<std::string>> Plugin::HookLoadFileExtended(const LoadType type, const std::string& file,
|
|
const std::string& resolved) {
|
|
return std::make_pair(-1, std::nullopt);
|
|
}
|
|
|
|
std::pair<bool, ValPtr> Plugin::HookFunctionCall(const Func* func, zeek::detail::Frame* parent, Args* args) {
|
|
return {false, nullptr};
|
|
}
|
|
|
|
bool Plugin::HookQueueEvent(Event* event) { return false; }
|
|
|
|
void Plugin::HookDrainEvents() {}
|
|
|
|
void Plugin::HookUpdateNetworkTime(double network_time) {}
|
|
|
|
void Plugin::HookSetupAnalyzerTree(Connection* conn) {}
|
|
|
|
void Plugin::HookObjDtor(void* obj) {}
|
|
|
|
void Plugin::HookLogInit(const std::string& writer, const std::string& instantiating_filter, bool local, bool remote,
|
|
const logging::WriterBackend::WriterInfo& info, int num_fields,
|
|
const threading::Field* const* fields) {}
|
|
|
|
bool Plugin::HookLogWrite(const std::string& writer, const std::string& filter,
|
|
const logging::WriterBackend::WriterInfo& info, int num_fields,
|
|
const threading::Field* const* fields, threading::Value** vals) {
|
|
return true;
|
|
}
|
|
|
|
bool Plugin::HookReporter(const std::string& prefix, const EventHandlerPtr event, const Connection* conn,
|
|
const ValPList* addl, bool location, const zeek::detail::Location* location1,
|
|
const zeek::detail::Location* location2, bool time, const std::string& message) {
|
|
return true;
|
|
}
|
|
|
|
void Plugin::HookUnprocessedPacket(const Packet* packet) {}
|
|
|
|
bool Plugin::HookPublishEvent(zeek::cluster::Backend& backend, const std::string& topic, zeek::cluster::Event& event) {
|
|
return true;
|
|
}
|
|
|
|
void Plugin::MetaHookPre(HookType hook, const HookArgumentList& args) {}
|
|
|
|
void Plugin::MetaHookPost(HookType hook, const HookArgumentList& args, HookArgument result) {}
|
|
|
|
void Plugin::InitializeComponents() {
|
|
for ( component_list::const_iterator i = components.begin(); i != components.end(); i++ )
|
|
(*i)->Initialize();
|
|
}
|
|
|
|
void Plugin::Describe(ODesc* d) const {
|
|
d->Add(config.name);
|
|
|
|
if ( config.description.size() ) {
|
|
d->Add(" - ");
|
|
d->Add(config.description);
|
|
}
|
|
|
|
if ( dynamic ) {
|
|
d->Add(" (dynamic, ");
|
|
|
|
if ( config.version ) {
|
|
d->Add("version ");
|
|
d->Add(config.version.major);
|
|
d->Add(".");
|
|
d->Add(config.version.minor);
|
|
d->Add(".");
|
|
d->Add(config.version.patch);
|
|
d->Add(")");
|
|
}
|
|
else
|
|
d->Add("no version information)");
|
|
}
|
|
|
|
else
|
|
d->Add(" (built-in)");
|
|
|
|
d->Add("\n");
|
|
|
|
if ( d->IsShort() )
|
|
return;
|
|
|
|
for ( Component* component : components ) {
|
|
component->Describe(d);
|
|
d->Add("\n");
|
|
}
|
|
|
|
bif_item_list items = BifItems();
|
|
|
|
for ( const auto& item : items ) {
|
|
const char* type = nullptr;
|
|
|
|
switch ( item.GetType() ) {
|
|
case BifItem::FUNCTION: type = "Function"; break;
|
|
|
|
case BifItem::EVENT: type = "Event"; break;
|
|
|
|
case BifItem::CONSTANT: type = "Constant"; break;
|
|
|
|
case BifItem::GLOBAL: type = "Global"; break;
|
|
|
|
case BifItem::TYPE: type = "Type"; break;
|
|
|
|
default: type = "<unknown>";
|
|
}
|
|
|
|
d->Add(" ");
|
|
d->Add("[");
|
|
d->Add(type);
|
|
d->Add("] ");
|
|
d->Add(item.GetID());
|
|
d->Add("\n");
|
|
}
|
|
|
|
hook_list hooks = EnabledHooks();
|
|
|
|
for ( const auto& [hook, prio] : hooks ) {
|
|
d->Add(" Implements ");
|
|
d->Add(hook_name(hook));
|
|
d->Add(" (priority ");
|
|
d->Add(prio);
|
|
d->Add(")\n");
|
|
}
|
|
}
|
|
|
|
} // namespace zeek::plugin
|