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 )
|
||||
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()
|
||||
|
@ -231,6 +240,22 @@ bool Manager::UnregisterAnalyzerForPort(EnumVal* val, PortVal* 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
|
||||
// checks for protocols, but this part might need to stay like this.
|
||||
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)
|
||||
{
|
||||
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
|
||||
// checks for protocols, but this part might need to stay like this.
|
||||
packet_analysis::AnalyzerPtr analyzer;
|
||||
|
|
|
@ -335,6 +335,8 @@ public:
|
|||
{ return vxlan_ports; }
|
||||
|
||||
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;
|
||||
|
||||
|
@ -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_queue = std::priority_queue<ScheduledAnalyzer*,
|
||||
std::vector<ScheduledAnalyzer*>,
|
||||
ScheduledAnalyzer::Comparator>;
|
||||
|
||||
bool initialized = false;
|
||||
protocol_analyzers pending_analyzers_for_ports;
|
||||
|
||||
conns_map conns;
|
||||
conns_queue conns_by_timeout;
|
||||
std::vector<uint16_t> vxlan_ports;
|
||||
|
|
|
@ -87,8 +87,8 @@ int perftools_profile = 0;
|
|||
#endif
|
||||
|
||||
zeek::ValManager* zeek::val_mgr = nullptr;
|
||||
zeek::analyzer::Manager* zeek::analyzer_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::detail::RuleMatcher* zeek::detail::rule_matcher = nullptr;
|
||||
|
@ -253,8 +253,8 @@ static void done_with_network()
|
|||
|
||||
run_state::terminating = true;
|
||||
|
||||
analyzer_mgr->Done();
|
||||
packet_mgr->Done();
|
||||
analyzer_mgr->Done();
|
||||
timer_mgr->Expire();
|
||||
dns_mgr->Flush();
|
||||
event_mgr.Drain();
|
||||
|
@ -324,8 +324,8 @@ static void terminate_bro()
|
|||
plugin_mgr->FinishPlugins();
|
||||
|
||||
delete zeekygen_mgr;
|
||||
delete analyzer_mgr;
|
||||
delete packet_mgr;
|
||||
delete analyzer_mgr;
|
||||
delete file_mgr;
|
||||
// broker_mgr, timer_mgr, and supervisor are deleted via iosource_mgr
|
||||
delete iosource_mgr;
|
||||
|
@ -577,8 +577,8 @@ SetupResult setup(int argc, char** argv, Options* zopts)
|
|||
|
||||
iosource_mgr = new iosource::Manager();
|
||||
event_registry = new EventRegistry();
|
||||
analyzer_mgr = new analyzer::Manager();
|
||||
packet_mgr = new packet_analysis::Manager();
|
||||
analyzer_mgr = new analyzer::Manager();
|
||||
log_mgr = new logging::Manager();
|
||||
input_mgr = new input::Manager();
|
||||
file_mgr = new file_analysis::Manager();
|
||||
|
@ -708,8 +708,8 @@ SetupResult setup(int argc, char** argv, Options* zopts)
|
|||
exit(success ? 0 : 1);
|
||||
}
|
||||
|
||||
analyzer_mgr->InitPostScript();
|
||||
packet_mgr->InitPostScript();
|
||||
analyzer_mgr->InitPostScript();
|
||||
file_mgr->InitPostScript();
|
||||
dns_mgr->InitPostScript();
|
||||
|
||||
|
@ -916,8 +916,8 @@ SetupResult setup(int argc, char** argv, Options* zopts)
|
|||
reporter->FatalError("errors occurred while initializing");
|
||||
|
||||
run_state::detail::zeek_init_done = true;
|
||||
analyzer_mgr->DumpDebug();
|
||||
packet_mgr->DumpDebug();
|
||||
analyzer_mgr->DumpDebug();
|
||||
|
||||
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=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 "analyzer/Component.h"
|
||||
#include "analyzer/Manager.h"
|
||||
|
||||
#include "Foo.h"
|
||||
|
||||
|
@ -20,3 +21,13 @@ zeek::plugin::Configuration Plugin::Configure()
|
|||
config.version.patch = 0;
|
||||
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:
|
||||
// Overridden from zeek::plugin::Plugin.
|
||||
zeek::plugin::Configuration Configure() override;
|
||||
|
||||
void InitPostScript() override;
|
||||
};
|
||||
|
||||
extern Plugin plugin;
|
||||
|
|
|
@ -4,6 +4,8 @@
|
|||
# @TEST-EXEC: ZEEK_PLUGIN_PATH=`pwd` zeek -NN Demo::Foo >>output
|
||||
# @TEST-EXEC: echo === >>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
|
||||
|
||||
event foo_message(c: connection, data: string)
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue