mirror of
https://github.com/zeek/zeek.git
synced 2025-10-05 16:18:19 +00:00
Merge ProtocolAnalyzerSet into Manager, remove AnalyzerSet base class
This commit is contained in:
parent
1e0e8e35af
commit
1c3ded7dd5
6 changed files with 142 additions and 222 deletions
|
@ -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;
|
|
||||||
};
|
|
||||||
|
|
||||||
}
|
|
|
@ -10,7 +10,6 @@ add_subdirectory(dispatchers)
|
||||||
|
|
||||||
set(llanalyzer_SRCS
|
set(llanalyzer_SRCS
|
||||||
Analyzer.cc
|
Analyzer.cc
|
||||||
ProtocolAnalyzerSet.cc
|
|
||||||
Manager.cc
|
Manager.cc
|
||||||
Component.cc
|
Component.cc
|
||||||
Tag.cc
|
Tag.cc
|
||||||
|
|
|
@ -1,13 +1,15 @@
|
||||||
// See the file "COPYING" in the main distribution directory for copyright.
|
// See the file "COPYING" in the main distribution directory for copyright.
|
||||||
|
|
||||||
|
#include "Manager.h"
|
||||||
|
|
||||||
#include <list>
|
#include <list>
|
||||||
#include <pcap.h>
|
#include <pcap.h>
|
||||||
|
|
||||||
#include "Config.h"
|
#include "Config.h"
|
||||||
#include "Manager.h"
|
|
||||||
#include "NetVar.h"
|
#include "NetVar.h"
|
||||||
#include "ProtocolAnalyzerSet.h"
|
|
||||||
#include "plugin/Manager.h"
|
#include "plugin/Manager.h"
|
||||||
|
#include "Analyzer.h"
|
||||||
|
#include "dispatchers/VectorDispatcher.h"
|
||||||
|
|
||||||
using namespace zeek::packet_analysis;
|
using namespace zeek::packet_analysis;
|
||||||
|
|
||||||
|
@ -18,7 +20,17 @@ Manager::Manager()
|
||||||
|
|
||||||
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()
|
void Manager::InitPostScript()
|
||||||
|
@ -43,7 +55,38 @@ void Manager::InitPostScript()
|
||||||
configuration.AddMapping(parent_name, identifier, Lookup(analyzer)->Name());
|
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()
|
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");
|
DBG_LOG(DBG_PACKET_ANALYSIS, " %s (%s)", current->Name().c_str(), IsEnabled(current->Tag()) ? "enabled" : "disabled");
|
||||||
}
|
}
|
||||||
|
|
||||||
// Dump Analyzer Set
|
DBG_LOG(DBG_PACKET_ANALYSIS, "ProtocolAnalyzerSet FSM:");
|
||||||
if (analyzer_set)
|
for ( const auto& current : dispatchers )
|
||||||
analyzer_set->DumpDebug();
|
{
|
||||||
|
DBG_LOG(DBG_PACKET_ANALYSIS, " Dispatcher (%p): %s", current.second, current.first.c_str());
|
||||||
|
current.second->DumpDebug();
|
||||||
|
}
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -204,15 +250,12 @@ void Manager::ProcessPacket(Packet* packet)
|
||||||
DBG_LOG(DBG_PACKET_ANALYSIS, "Analyzing packet %ld, ts=%.3f...", ++counter, packet->time);
|
DBG_LOG(DBG_PACKET_ANALYSIS, "Analyzing packet %ld, ts=%.3f...", ++counter, packet->time);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
if ( ! analyzer_set )
|
|
||||||
return;
|
|
||||||
|
|
||||||
// Dispatch and analyze layers
|
// Dispatch and analyze layers
|
||||||
AnalyzerResult result = AnalyzerResult::Continue;
|
AnalyzerResult result = AnalyzerResult::Continue;
|
||||||
identifier_t next_layer_id = packet->link_type;
|
identifier_t next_layer_id = packet->link_type;
|
||||||
do
|
do
|
||||||
{
|
{
|
||||||
auto current_analyzer = analyzer_set->Dispatch(next_layer_id);
|
auto current_analyzer = Dispatch(next_layer_id);
|
||||||
|
|
||||||
// Analyzer not found
|
// Analyzer not found
|
||||||
if ( current_analyzer == nullptr )
|
if ( current_analyzer == nullptr )
|
||||||
|
@ -246,7 +289,7 @@ void Manager::ProcessPacket(Packet* packet)
|
||||||
CustomEncapsulationSkip(packet);
|
CustomEncapsulationSkip(packet);
|
||||||
|
|
||||||
// Processing finished, reset analyzer set state for next packet
|
// Processing finished, reset analyzer set state for next packet
|
||||||
analyzer_set->Reset();
|
Reset();
|
||||||
}
|
}
|
||||||
|
|
||||||
void Manager::CustomEncapsulationSkip(Packet* packet)
|
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<std::reference_wrapper<DispatcherConfig>> 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;
|
||||||
|
}
|
||||||
|
|
|
@ -5,19 +5,18 @@
|
||||||
#include <queue>
|
#include <queue>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
|
||||||
|
#include "Config.h"
|
||||||
#include "Tag.h"
|
#include "Tag.h"
|
||||||
#include "Analyzer.h"
|
|
||||||
#include "Component.h"
|
#include "Component.h"
|
||||||
#include "AnalyzerSet.h"
|
|
||||||
#include "plugin/ComponentManager.h"
|
#include "plugin/ComponentManager.h"
|
||||||
#include "iosource/Packet.h"
|
#include "iosource/Packet.h"
|
||||||
|
#include "Dict.h"
|
||||||
#include "../Dict.h"
|
#include "net_util.h"
|
||||||
#include "../net_util.h"
|
|
||||||
|
|
||||||
namespace zeek::packet_analysis {
|
namespace zeek::packet_analysis {
|
||||||
|
|
||||||
class AnalyzerSet;
|
class Analyzer;
|
||||||
|
class Dispatcher;
|
||||||
|
|
||||||
class Manager : public plugin::ComponentManager<Tag, Component> {
|
class Manager : public plugin::ComponentManager<Tag, Component> {
|
||||||
public:
|
public:
|
||||||
|
@ -148,7 +147,8 @@ public:
|
||||||
*/
|
*/
|
||||||
void ProcessPacket(Packet* packet);
|
void ProcessPacket(Packet* packet);
|
||||||
|
|
||||||
protected:
|
private:
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Skips a fixed amount of packet data that is defined by encap_hdr_size.
|
* Skips a fixed amount of packet data that is defined by encap_hdr_size.
|
||||||
* It is assumed that an IP header follows.
|
* It is assumed that an IP header follows.
|
||||||
|
@ -157,9 +157,18 @@ protected:
|
||||||
*/
|
*/
|
||||||
void CustomEncapsulationSkip(Packet* packet);
|
void CustomEncapsulationSkip(Packet* packet);
|
||||||
|
|
||||||
private:
|
Analyzer* Dispatch(identifier_t identifier);
|
||||||
AnalyzerSet* analyzer_set = nullptr;
|
|
||||||
|
|
||||||
|
void Reset();
|
||||||
|
|
||||||
|
Dispatcher* GetDispatcher(Config& configuration, const std::string& dispatcher_name);
|
||||||
|
|
||||||
|
std::map<std::string, Analyzer*> analyzers;
|
||||||
|
std::map<std::string, Dispatcher*> dispatchers;
|
||||||
|
Dispatcher* root_dispatcher = nullptr;
|
||||||
|
Dispatcher* default_dispatcher = nullptr;
|
||||||
|
Dispatcher* current_state = nullptr;
|
||||||
|
Analyzer* default_analyzer = nullptr;
|
||||||
};
|
};
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -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<std::reference_wrapper<DispatcherConfig>> 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;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
|
@ -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<std::string, Analyzer*> analyzers;
|
|
||||||
std::map<std::string, Dispatcher*> 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);
|
|
||||||
};
|
|
||||||
|
|
||||||
}
|
|
Loading…
Add table
Add a link
Reference in a new issue