From 1c3ded7dd53e864d89052a166f0904a27b555b7e Mon Sep 17 00:00:00 2001 From: Tim Wojtulewicz Date: Mon, 13 Jul 2020 17:14:12 -0400 Subject: [PATCH] Merge ProtocolAnalyzerSet into Manager, remove AnalyzerSet base class --- src/packet_analysis/AnalyzerSet.h | 24 ---- src/packet_analysis/CMakeLists.txt | 1 - src/packet_analysis/Manager.cc | 136 ++++++++++++++++++-- src/packet_analysis/Manager.h | 27 ++-- src/packet_analysis/ProtocolAnalyzerSet.cc | 137 --------------------- src/packet_analysis/ProtocolAnalyzerSet.h | 39 ------ 6 files changed, 142 insertions(+), 222 deletions(-) delete mode 100644 src/packet_analysis/AnalyzerSet.h delete mode 100644 src/packet_analysis/ProtocolAnalyzerSet.cc delete mode 100644 src/packet_analysis/ProtocolAnalyzerSet.h diff --git a/src/packet_analysis/AnalyzerSet.h b/src/packet_analysis/AnalyzerSet.h deleted file mode 100644 index 5e9c538ce2..0000000000 --- a/src/packet_analysis/AnalyzerSet.h +++ /dev/null @@ -1,24 +0,0 @@ -// See the file "COPYING" in the main distribution directory for copyright. - -#pragma once - -#include "Analyzer.h" -#include "Defines.h" - -namespace zeek::packet_analysis { - -class Analyzer; - -class AnalyzerSet { -public: - virtual ~AnalyzerSet() = default; - virtual Analyzer* Dispatch(identifier_t identifier) = 0; - virtual void Reset() = 0; - -protected: - friend class Manager; - - virtual void DumpDebug() const = 0; -}; - -} diff --git a/src/packet_analysis/CMakeLists.txt b/src/packet_analysis/CMakeLists.txt index 6a5fa16708..88023b8fa2 100644 --- a/src/packet_analysis/CMakeLists.txt +++ b/src/packet_analysis/CMakeLists.txt @@ -10,7 +10,6 @@ add_subdirectory(dispatchers) set(llanalyzer_SRCS Analyzer.cc - ProtocolAnalyzerSet.cc Manager.cc Component.cc Tag.cc diff --git a/src/packet_analysis/Manager.cc b/src/packet_analysis/Manager.cc index 8b0ff3bbb7..f9e1f6e9c7 100644 --- a/src/packet_analysis/Manager.cc +++ b/src/packet_analysis/Manager.cc @@ -1,13 +1,15 @@ // See the file "COPYING" in the main distribution directory for copyright. +#include "Manager.h" + #include #include #include "Config.h" -#include "Manager.h" #include "NetVar.h" -#include "ProtocolAnalyzerSet.h" #include "plugin/Manager.h" +#include "Analyzer.h" +#include "dispatchers/VectorDispatcher.h" using namespace zeek::packet_analysis; @@ -18,7 +20,17 @@ Manager::Manager() Manager::~Manager() { - delete analyzer_set; + bool delete_default = default_analyzer != nullptr; + for ( const auto& current : analyzers ) + { + if ( current.second == default_analyzer ) + delete_default = false; + + delete current.second; + } + + if ( delete_default ) + delete default_analyzer; } void Manager::InitPostScript() @@ -43,7 +55,38 @@ void Manager::InitPostScript() configuration.AddMapping(parent_name, identifier, Lookup(analyzer)->Name()); } - analyzer_set = new ProtocolAnalyzerSet(configuration, "DefaultAnalyzer"); + // Instantiate objects for all analyzers + for ( const auto& current_dispatcher_config : configuration.GetDispatchers() ) + { + for ( const auto& current_mapping : current_dispatcher_config.GetMappings() ) + { + // Check if already instantiated + if ( analyzers.count(current_mapping.second) != 0 ) + continue; + + // Check if analyzer exists + if ( Analyzer* newAnalyzer = InstantiateAnalyzer(current_mapping.second) ) + analyzers.emplace(current_mapping.second, newAnalyzer); + } + } + + // Generate Dispatchers, starting at root + root_dispatcher = GetDispatcher(configuration, "ROOT"); + if ( root_dispatcher == nullptr ) + reporter->InternalError("No dispatching configuration for ROOT of packet_analysis set."); + + // Set up default analysis + auto it = analyzers.find("DefaultAnalyzer"); + if ( it != analyzers.end() ) + default_analyzer = it->second; + else + default_analyzer = InstantiateAnalyzer("DefaultAnalyzer"); + + default_dispatcher = nullptr; + if ( default_analyzer != nullptr ) + default_dispatcher = GetDispatcher(configuration, "DefaultAnalyzer"); + + current_state = root_dispatcher; } void Manager::Done() @@ -59,9 +102,12 @@ void Manager::DumpDebug() DBG_LOG(DBG_PACKET_ANALYSIS, " %s (%s)", current->Name().c_str(), IsEnabled(current->Tag()) ? "enabled" : "disabled"); } - // Dump Analyzer Set - if (analyzer_set) - analyzer_set->DumpDebug(); + DBG_LOG(DBG_PACKET_ANALYSIS, "ProtocolAnalyzerSet FSM:"); + for ( const auto& current : dispatchers ) + { + DBG_LOG(DBG_PACKET_ANALYSIS, " Dispatcher (%p): %s", current.second, current.first.c_str()); + current.second->DumpDebug(); + } #endif } @@ -204,15 +250,12 @@ void Manager::ProcessPacket(Packet* packet) DBG_LOG(DBG_PACKET_ANALYSIS, "Analyzing packet %ld, ts=%.3f...", ++counter, packet->time); #endif - if ( ! analyzer_set ) - return; - // Dispatch and analyze layers AnalyzerResult result = AnalyzerResult::Continue; identifier_t next_layer_id = packet->link_type; do { - auto current_analyzer = analyzer_set->Dispatch(next_layer_id); + auto current_analyzer = Dispatch(next_layer_id); // Analyzer not found if ( current_analyzer == nullptr ) @@ -246,7 +289,7 @@ void Manager::ProcessPacket(Packet* packet) CustomEncapsulationSkip(packet); // Processing finished, reset analyzer set state for next packet - analyzer_set->Reset(); + Reset(); } void Manager::CustomEncapsulationSkip(Packet* packet) @@ -283,3 +326,72 @@ void Manager::CustomEncapsulationSkip(Packet* packet) } } } + +Analyzer* Manager::Dispatch(identifier_t identifier) + { + // Because leaf nodes (aka no more dispatching) can still have an existing analyzer that returns more identifiers, + // current_state needs to be checked to be not null. In this case there would have been an analyzer dispatched + // in the last layer, but no dispatcher for it (end of FSM) + const Value* result = nullptr; + if ( current_state ) + result = current_state->Lookup(identifier); + + if ( result == nullptr ) + { + if ( current_state != default_dispatcher ) + { + // Switch to default analysis once + current_state = default_dispatcher; + return default_analyzer; + } + return nullptr; + } + else + { + current_state = result->dispatcher; + return result->analyzer; + } + } + +void Manager::Reset() + { + current_state = root_dispatcher; + } + +Dispatcher* Manager::GetDispatcher(Config& configuration, const std::string& dispatcher_name) + { + // Is it already created? + if ( dispatchers.count(dispatcher_name) != 0 ) + return dispatchers[dispatcher_name]; + + // Create new dispatcher from config + std::optional> dispatcher_config = + configuration.GetDispatcherConfig(dispatcher_name); + + if ( ! dispatcher_config ) + // No such dispatcher found, this is therefore implicitly a leaf + return nullptr; + + const auto& mappings = dispatcher_config->get().GetMappings(); + + Dispatcher* dispatcher = new VectorDispatcher(); + dispatchers.emplace(dispatcher_name, dispatcher); + + for ( const auto& current_mapping : mappings ) + { + // No analyzer with this name. Report warning and ignore. + if ( analyzers.count(current_mapping.second) == 0 ) + { + reporter->InternalWarning("No analyzer %s found for dispatching identifier %#x of %s, ignoring.", + current_mapping.second.c_str(), + current_mapping.first, + dispatcher_name.c_str()); + continue; + } + + dispatcher->Register(current_mapping.first, analyzers.at(current_mapping.second), + GetDispatcher(configuration, current_mapping.second)); + } + + return dispatcher; + } diff --git a/src/packet_analysis/Manager.h b/src/packet_analysis/Manager.h index f5130e1b2a..a23849bbb0 100644 --- a/src/packet_analysis/Manager.h +++ b/src/packet_analysis/Manager.h @@ -5,19 +5,18 @@ #include #include +#include "Config.h" #include "Tag.h" -#include "Analyzer.h" #include "Component.h" -#include "AnalyzerSet.h" #include "plugin/ComponentManager.h" #include "iosource/Packet.h" - -#include "../Dict.h" -#include "../net_util.h" +#include "Dict.h" +#include "net_util.h" namespace zeek::packet_analysis { -class AnalyzerSet; +class Analyzer; +class Dispatcher; class Manager : public plugin::ComponentManager { public: @@ -148,7 +147,8 @@ public: */ void ProcessPacket(Packet* packet); -protected: +private: + /** * Skips a fixed amount of packet data that is defined by encap_hdr_size. * It is assumed that an IP header follows. @@ -157,9 +157,18 @@ protected: */ void CustomEncapsulationSkip(Packet* packet); -private: - AnalyzerSet* analyzer_set = nullptr; + Analyzer* Dispatch(identifier_t identifier); + void Reset(); + + Dispatcher* GetDispatcher(Config& configuration, const std::string& dispatcher_name); + + std::map analyzers; + std::map dispatchers; + Dispatcher* root_dispatcher = nullptr; + Dispatcher* default_dispatcher = nullptr; + Dispatcher* current_state = nullptr; + Analyzer* default_analyzer = nullptr; }; } diff --git a/src/packet_analysis/ProtocolAnalyzerSet.cc b/src/packet_analysis/ProtocolAnalyzerSet.cc deleted file mode 100644 index 21a3eac1f6..0000000000 --- a/src/packet_analysis/ProtocolAnalyzerSet.cc +++ /dev/null @@ -1,137 +0,0 @@ -// See the file "COPYING" in the main distribution directory for copyright. - -#include "ProtocolAnalyzerSet.h" - -namespace zeek::packet_analysis { - -ProtocolAnalyzerSet::ProtocolAnalyzerSet(Config& configuration, const std::string& default_analyzer_name) - { - // Instantiate objects for all analyzers - for ( const auto& current_dispatcher_config : configuration.GetDispatchers() ) - { - for ( const auto& current_mapping : current_dispatcher_config.GetMappings() ) - { - // Check if already instantiated - if ( analyzers.count(current_mapping.second) != 0 ) - continue; - - // Check if analyzer exists - if ( Analyzer* newAnalyzer = packet_mgr->InstantiateAnalyzer(current_mapping.second) ) - analyzers.emplace(current_mapping.second, newAnalyzer); - } - } - - // Generate Dispatchers, starting at root - root_dispatcher = GetDispatcher(configuration, "ROOT"); - if ( root_dispatcher == nullptr ) - reporter->InternalError("No dispatching configuration for ROOT of packet_analysis set."); - - // Set up default analysis - auto it = analyzers.find(default_analyzer_name); - if ( it != analyzers.end() ) - default_analyzer = it->second; - else - default_analyzer = packet_mgr->InstantiateAnalyzer(default_analyzer_name); - - default_dispatcher = nullptr; - if ( default_analyzer != nullptr ) - default_dispatcher = GetDispatcher(configuration, default_analyzer_name); - - current_state = root_dispatcher; - } - -ProtocolAnalyzerSet::~ProtocolAnalyzerSet() - { - bool delete_default = default_analyzer != nullptr; - for ( const auto& current : analyzers ) - { - if ( current.second == default_analyzer ) - delete_default = false; - - delete current.second; - } - - if ( delete_default ) - delete default_analyzer; - } - -Analyzer* ProtocolAnalyzerSet::Dispatch(identifier_t identifier) - { - // Because leaf nodes (aka no more dispatching) can still have an existing analyzer that returns more identifiers, - // current_state needs to be checked to be not null. In this case there would have been an analyzer dispatched - // in the last layer, but no dispatcher for it (end of FSM) - const Value* result = nullptr; - if ( current_state ) - result = current_state->Lookup(identifier); - - if ( result == nullptr ) - { - if ( current_state != default_dispatcher ) - { - // Switch to default analysis once - current_state = default_dispatcher; - return default_analyzer; - } - return nullptr; - } - else - { - current_state = result->dispatcher; - return result->analyzer; - } - } - -void ProtocolAnalyzerSet::Reset() - { - current_state = root_dispatcher; - } - -void ProtocolAnalyzerSet::DumpDebug() const - { -#ifdef DEBUG - DBG_LOG(DBG_PACKET_ANALYSIS, "ProtocolAnalyzerSet FSM:"); - for ( const auto& current : dispatchers ) - { - DBG_LOG(DBG_PACKET_ANALYSIS, " Dispatcher (%p): %s", current.second, current.first.c_str()); - current.second->DumpDebug(); - } -#endif - } - -Dispatcher* ProtocolAnalyzerSet::GetDispatcher(Config& configuration, const std::string& dispatcher_name) - { - // Is it already created? - if ( dispatchers.count(dispatcher_name) != 0 ) - return dispatchers[dispatcher_name]; - - // Create new dispatcher from config - std::optional> dispatcher_config = configuration.GetDispatcherConfig(dispatcher_name); - if ( ! dispatcher_config ) - // No such dispatcher found, this is therefore implicitly a leaf - return nullptr; - - const auto& mappings = dispatcher_config->get().GetMappings(); - - Dispatcher* dispatcher = new dispatcher_impl(); - dispatchers.emplace(dispatcher_name, dispatcher); - - for ( const auto& current_mapping : mappings ) - { - // No analyzer with this name. Report warning and ignore. - if ( analyzers.count(current_mapping.second) == 0 ) - { - reporter->InternalWarning("No analyzer %s found for dispatching identifier %#x of %s, ignoring.", - current_mapping.second.c_str(), - current_mapping.first, - dispatcher_name.c_str()); - continue; - } - - dispatcher->Register(current_mapping.first, analyzers.at(current_mapping.second), - GetDispatcher(configuration, current_mapping.second)); - } - - return dispatcher; - } - -} diff --git a/src/packet_analysis/ProtocolAnalyzerSet.h b/src/packet_analysis/ProtocolAnalyzerSet.h deleted file mode 100644 index bde05e73f9..0000000000 --- a/src/packet_analysis/ProtocolAnalyzerSet.h +++ /dev/null @@ -1,39 +0,0 @@ -// See the file "COPYING" in the main distribution directory for copyright. - -#pragma once - -#include "AnalyzerSet.h" -#include "Config.h" -#include "dispatchers/Dispatcher.h" -#include "dispatchers/UniversalDispatcher.h" -#include "dispatchers/VectorDispatcher.h" - -namespace zeek::packet_analysis { - -class ProtocolAnalyzerSet : public AnalyzerSet { - -public: - explicit ProtocolAnalyzerSet(Config& configuration, const std::string& default_analyzer_name); - ~ProtocolAnalyzerSet() override; - - Analyzer* Dispatch(identifier_t identifier) override; - void Reset() override; - -protected: - void DumpDebug() const override; - -private: - using dispatcher_impl = VectorDispatcher; - //using dispatcher_impl = UniversalDispatcher; - - std::map analyzers; - std::map dispatchers; - Dispatcher* root_dispatcher = nullptr; - Dispatcher* default_dispatcher = nullptr; - Dispatcher* current_state = nullptr; - Analyzer* default_analyzer = nullptr; - - Dispatcher* GetDispatcher(Config& configuration, const std::string& dispatcher_name); -}; - -}