mirror of
https://github.com/zeek/zeek.git
synced 2025-10-02 06:38:20 +00:00
Fix registration of protocol analyzers from inside plugins.
With the recent packet manager work, it broke to register a protocol analyzer for a specific port from inside a plugin's initialization code. That's because that registration now depends on the packet manager being set up, which isn't case at that time a plugin's `InitPostInit()` runs. This fix contains two parts: - Initialize the packet manager before the analyzer manager, so that the latter's `InitPostScript()` can rely on the former being ready. - Change the analyzer manager to (only) record port registrations happening before it's fully initialized. Its `InitPostScript()` then performs the actual registrations, knowing it can use the packet manager now. This comes with a `cmake/` to add a missing include directory.
This commit is contained in:
parent
6e3d2d4516
commit
a7343ee019
9 changed files with 59 additions and 7 deletions
2
cmake
2
cmake
|
@ -1 +1 @@
|
||||||
Subproject commit 9d762b4cacf299a2e54e0f7f258868ee217f1d36
|
Subproject commit 4d1990f0e4c273cf51ec52278add6ff256f9c889
|
|
@ -86,6 +86,15 @@ void Manager::InitPostScript()
|
||||||
|
|
||||||
for ( auto i = 0; i < port_list->Length(); ++i )
|
for ( auto i = 0; i < port_list->Length(); ++i )
|
||||||
vxlan_ports.emplace_back(port_list->Idx(i)->AsPortVal()->Port());
|
vxlan_ports.emplace_back(port_list->Idx(i)->AsPortVal()->Port());
|
||||||
|
|
||||||
|
for ( const auto& p : pending_analyzers_for_ports ) {
|
||||||
|
if ( ! RegisterAnalyzerForPort(p) )
|
||||||
|
reporter->Warning("cannot register analyzer for port %u", std::get<2>(p));
|
||||||
|
}
|
||||||
|
|
||||||
|
pending_analyzers_for_ports.clear();
|
||||||
|
|
||||||
|
initialized = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
void Manager::DumpDebug()
|
void Manager::DumpDebug()
|
||||||
|
@ -231,6 +240,22 @@ bool Manager::UnregisterAnalyzerForPort(EnumVal* val, PortVal* port)
|
||||||
|
|
||||||
bool Manager::RegisterAnalyzerForPort(const Tag& tag, TransportProto proto, uint32_t port)
|
bool Manager::RegisterAnalyzerForPort(const Tag& tag, TransportProto proto, uint32_t port)
|
||||||
{
|
{
|
||||||
|
if ( initialized )
|
||||||
|
return RegisterAnalyzerForPort(std::make_tuple(tag, proto, port));
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// Cannot register these before PostScriptInit() has run because we
|
||||||
|
// depend on packet analyis having been set up. That also means we don't have
|
||||||
|
// a reliable return value, for now we just assume it's working.
|
||||||
|
pending_analyzers_for_ports.emplace(tag, proto, port);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
bool Manager::RegisterAnalyzerForPort(const std::tuple<Tag, TransportProto, uint32_t>& p)
|
||||||
|
{
|
||||||
|
const auto& [tag, proto, port] = p;
|
||||||
|
|
||||||
// TODO: this class is becoming more generic and removing a lot of the
|
// TODO: this class is becoming more generic and removing a lot of the
|
||||||
// checks for protocols, but this part might need to stay like this.
|
// checks for protocols, but this part might need to stay like this.
|
||||||
packet_analysis::AnalyzerPtr analyzer;
|
packet_analysis::AnalyzerPtr analyzer;
|
||||||
|
@ -249,6 +274,9 @@ bool Manager::RegisterAnalyzerForPort(const Tag& tag, TransportProto proto, uint
|
||||||
|
|
||||||
bool Manager::UnregisterAnalyzerForPort(const Tag& tag, TransportProto proto, uint32_t port)
|
bool Manager::UnregisterAnalyzerForPort(const Tag& tag, TransportProto proto, uint32_t port)
|
||||||
{
|
{
|
||||||
|
if ( auto i = pending_analyzers_for_ports.find(std::make_tuple(tag, proto, port)); i != pending_analyzers_for_ports.end() )
|
||||||
|
pending_analyzers_for_ports.erase(i);
|
||||||
|
|
||||||
// TODO: this class is becoming more generic and removing a lot of the
|
// TODO: this class is becoming more generic and removing a lot of the
|
||||||
// checks for protocols, but this part might need to stay like this.
|
// checks for protocols, but this part might need to stay like this.
|
||||||
packet_analysis::AnalyzerPtr analyzer;
|
packet_analysis::AnalyzerPtr analyzer;
|
||||||
|
|
|
@ -335,6 +335,8 @@ public:
|
||||||
{ return vxlan_ports; }
|
{ return vxlan_ports; }
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
// Internal version that must be used only once InitPostScript has completed.
|
||||||
|
bool RegisterAnalyzerForPort(const std::tuple<Tag, TransportProto, uint32_t>& p);
|
||||||
|
|
||||||
friend class packet_analysis::IP::IPBasedAnalyzer;
|
friend class packet_analysis::IP::IPBasedAnalyzer;
|
||||||
|
|
||||||
|
@ -372,11 +374,16 @@ private:
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
using protocol_analyzers = std::set<std::tuple<Tag, TransportProto, uint32_t>>;
|
||||||
using conns_map = std::multimap<ConnIndex, ScheduledAnalyzer*>;
|
using conns_map = std::multimap<ConnIndex, ScheduledAnalyzer*>;
|
||||||
using conns_queue = std::priority_queue<ScheduledAnalyzer*,
|
using conns_queue = std::priority_queue<ScheduledAnalyzer*,
|
||||||
std::vector<ScheduledAnalyzer*>,
|
std::vector<ScheduledAnalyzer*>,
|
||||||
ScheduledAnalyzer::Comparator>;
|
ScheduledAnalyzer::Comparator>;
|
||||||
|
|
||||||
|
bool initialized = false;
|
||||||
|
protocol_analyzers pending_analyzers_for_ports;
|
||||||
|
|
||||||
conns_map conns;
|
conns_map conns;
|
||||||
conns_queue conns_by_timeout;
|
conns_queue conns_by_timeout;
|
||||||
std::vector<uint16_t> vxlan_ports;
|
std::vector<uint16_t> vxlan_ports;
|
||||||
|
|
|
@ -87,8 +87,8 @@ int perftools_profile = 0;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
zeek::ValManager* zeek::val_mgr = nullptr;
|
zeek::ValManager* zeek::val_mgr = nullptr;
|
||||||
zeek::analyzer::Manager* zeek::analyzer_mgr = nullptr;
|
|
||||||
zeek::packet_analysis::Manager* zeek::packet_mgr = nullptr;
|
zeek::packet_analysis::Manager* zeek::packet_mgr = nullptr;
|
||||||
|
zeek::analyzer::Manager* zeek::analyzer_mgr = nullptr;
|
||||||
zeek::plugin::Manager* zeek::plugin_mgr = nullptr;
|
zeek::plugin::Manager* zeek::plugin_mgr = nullptr;
|
||||||
|
|
||||||
zeek::detail::RuleMatcher* zeek::detail::rule_matcher = nullptr;
|
zeek::detail::RuleMatcher* zeek::detail::rule_matcher = nullptr;
|
||||||
|
@ -253,8 +253,8 @@ static void done_with_network()
|
||||||
|
|
||||||
run_state::terminating = true;
|
run_state::terminating = true;
|
||||||
|
|
||||||
analyzer_mgr->Done();
|
|
||||||
packet_mgr->Done();
|
packet_mgr->Done();
|
||||||
|
analyzer_mgr->Done();
|
||||||
timer_mgr->Expire();
|
timer_mgr->Expire();
|
||||||
dns_mgr->Flush();
|
dns_mgr->Flush();
|
||||||
event_mgr.Drain();
|
event_mgr.Drain();
|
||||||
|
@ -324,8 +324,8 @@ static void terminate_bro()
|
||||||
plugin_mgr->FinishPlugins();
|
plugin_mgr->FinishPlugins();
|
||||||
|
|
||||||
delete zeekygen_mgr;
|
delete zeekygen_mgr;
|
||||||
delete analyzer_mgr;
|
|
||||||
delete packet_mgr;
|
delete packet_mgr;
|
||||||
|
delete analyzer_mgr;
|
||||||
delete file_mgr;
|
delete file_mgr;
|
||||||
// broker_mgr, timer_mgr, and supervisor are deleted via iosource_mgr
|
// broker_mgr, timer_mgr, and supervisor are deleted via iosource_mgr
|
||||||
delete iosource_mgr;
|
delete iosource_mgr;
|
||||||
|
@ -577,8 +577,8 @@ SetupResult setup(int argc, char** argv, Options* zopts)
|
||||||
|
|
||||||
iosource_mgr = new iosource::Manager();
|
iosource_mgr = new iosource::Manager();
|
||||||
event_registry = new EventRegistry();
|
event_registry = new EventRegistry();
|
||||||
analyzer_mgr = new analyzer::Manager();
|
|
||||||
packet_mgr = new packet_analysis::Manager();
|
packet_mgr = new packet_analysis::Manager();
|
||||||
|
analyzer_mgr = new analyzer::Manager();
|
||||||
log_mgr = new logging::Manager();
|
log_mgr = new logging::Manager();
|
||||||
input_mgr = new input::Manager();
|
input_mgr = new input::Manager();
|
||||||
file_mgr = new file_analysis::Manager();
|
file_mgr = new file_analysis::Manager();
|
||||||
|
@ -708,8 +708,8 @@ SetupResult setup(int argc, char** argv, Options* zopts)
|
||||||
exit(success ? 0 : 1);
|
exit(success ? 0 : 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
analyzer_mgr->InitPostScript();
|
|
||||||
packet_mgr->InitPostScript();
|
packet_mgr->InitPostScript();
|
||||||
|
analyzer_mgr->InitPostScript();
|
||||||
file_mgr->InitPostScript();
|
file_mgr->InitPostScript();
|
||||||
dns_mgr->InitPostScript();
|
dns_mgr->InitPostScript();
|
||||||
|
|
||||||
|
@ -916,8 +916,8 @@ SetupResult setup(int argc, char** argv, Options* zopts)
|
||||||
reporter->FatalError("errors occurred while initializing");
|
reporter->FatalError("errors occurred while initializing");
|
||||||
|
|
||||||
run_state::detail::zeek_init_done = true;
|
run_state::detail::zeek_init_done = true;
|
||||||
analyzer_mgr->DumpDebug();
|
|
||||||
packet_mgr->DumpDebug();
|
packet_mgr->DumpDebug();
|
||||||
|
analyzer_mgr->DumpDebug();
|
||||||
|
|
||||||
run_state::detail::have_pending_timers = ! run_state::reading_traces && timer_mgr->Size() > 0;
|
run_state::detail::have_pending_timers = ! run_state::reading_traces && timer_mgr->Size() > 0;
|
||||||
|
|
||||||
|
|
|
@ -5,3 +5,5 @@ Demo::Foo - A Foo test analyzer (dynamic, version 1.0.0)
|
||||||
|
|
||||||
===
|
===
|
||||||
foo_message, [orig_h=::1, orig_p=37927/tcp, resp_h=::1, resp_p=4242/tcp], Hello, Foo!\x0a
|
foo_message, [orig_h=::1, orig_p=37927/tcp, resp_h=::1, resp_p=4242/tcp], Hello, Foo!\x0a
|
||||||
|
===
|
||||||
|
foo_message, [orig_h=::1, orig_p=37927/tcp, resp_h=::1, resp_p=4243/tcp], Hello, Foo!\x0a
|
||||||
|
|
BIN
testing/btest/Traces/port4243.trace
Normal file
BIN
testing/btest/Traces/port4243.trace
Normal file
Binary file not shown.
|
@ -1,6 +1,7 @@
|
||||||
|
|
||||||
#include "Plugin.h"
|
#include "Plugin.h"
|
||||||
#include "analyzer/Component.h"
|
#include "analyzer/Component.h"
|
||||||
|
#include "analyzer/Manager.h"
|
||||||
|
|
||||||
#include "Foo.h"
|
#include "Foo.h"
|
||||||
|
|
||||||
|
@ -20,3 +21,13 @@ zeek::plugin::Configuration Plugin::Configure()
|
||||||
config.version.patch = 0;
|
config.version.patch = 0;
|
||||||
return config;
|
return config;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void Plugin::InitPostScript()
|
||||||
|
{
|
||||||
|
auto tag = ::zeek::analyzer_mgr->GetAnalyzerTag("Foo");
|
||||||
|
if ( ! tag )
|
||||||
|
::zeek::reporter->FatalError("cannot get analyzer Tag");
|
||||||
|
|
||||||
|
zeek::analyzer_mgr->RegisterAnalyzerForPort(tag, TransportProto::TRANSPORT_TCP, 4243);
|
||||||
|
}
|
||||||
|
|
|
@ -10,6 +10,8 @@ class Plugin : public zeek::plugin::Plugin
|
||||||
protected:
|
protected:
|
||||||
// Overridden from zeek::plugin::Plugin.
|
// Overridden from zeek::plugin::Plugin.
|
||||||
zeek::plugin::Configuration Configure() override;
|
zeek::plugin::Configuration Configure() override;
|
||||||
|
|
||||||
|
void InitPostScript() override;
|
||||||
};
|
};
|
||||||
|
|
||||||
extern Plugin plugin;
|
extern Plugin plugin;
|
||||||
|
|
|
@ -4,6 +4,8 @@
|
||||||
# @TEST-EXEC: ZEEK_PLUGIN_PATH=`pwd` zeek -NN Demo::Foo >>output
|
# @TEST-EXEC: ZEEK_PLUGIN_PATH=`pwd` zeek -NN Demo::Foo >>output
|
||||||
# @TEST-EXEC: echo === >>output
|
# @TEST-EXEC: echo === >>output
|
||||||
# @TEST-EXEC: ZEEK_PLUGIN_PATH=`pwd` zeek -r $TRACES/port4242.trace %INPUT >>output
|
# @TEST-EXEC: ZEEK_PLUGIN_PATH=`pwd` zeek -r $TRACES/port4242.trace %INPUT >>output
|
||||||
|
# @TEST-EXEC: echo === >>output
|
||||||
|
# @TEST-EXEC: ZEEK_PLUGIN_PATH=`pwd` zeek -r $TRACES/port4243.trace %INPUT >>output
|
||||||
# @TEST-EXEC: TEST_DIFF_CANONIFIER= btest-diff output
|
# @TEST-EXEC: TEST_DIFF_CANONIFIER= btest-diff output
|
||||||
|
|
||||||
event foo_message(c: connection, data: string)
|
event foo_message(c: connection, data: string)
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue