mirror of
https://github.com/zeek/zeek.git
synced 2025-10-04 07:38:19 +00:00
Further simplified the packet analysis API.
This is still WIP and includes the following changes: * Dispatchers are now part of analyzers (moving dispatching logic from the manager to the analyzers) * All available analyzers are instantiated on start up * Removal of configuration class
This commit is contained in:
parent
9feda100b9
commit
d4ff5a236c
12 changed files with 104 additions and 340 deletions
|
@ -1,6 +1,5 @@
|
|||
// See the file "COPYING" in the main distribution directory for copyright.
|
||||
|
||||
#include <algorithm>
|
||||
#include "Analyzer.h"
|
||||
|
||||
namespace zeek::packet_analysis {
|
||||
|
@ -20,7 +19,6 @@ Analyzer::Analyzer(const Tag& tag)
|
|||
Init(tag);
|
||||
}
|
||||
|
||||
/* PRIVATE */
|
||||
void Analyzer::Init(const Tag& _tag)
|
||||
{
|
||||
tag = _tag;
|
||||
|
@ -41,13 +39,18 @@ const char* Analyzer::GetAnalyzerName() const
|
|||
bool Analyzer::IsAnalyzer(const char* name)
|
||||
{
|
||||
assert(tag);
|
||||
return packet_mgr->GetComponentName(tag).compare(name) == 0;
|
||||
return packet_mgr->GetComponentName(tag) == name;
|
||||
}
|
||||
|
||||
bool Analyzer::RegisterAnalyzerMapping(uint32_t identifier, AnalyzerPtr analyzer)
|
||||
{
|
||||
return dispatcher.Register(identifier, std::move(analyzer));
|
||||
}
|
||||
|
||||
AnalyzerResult Analyzer::AnalyzeInnerPacket(Packet* packet,
|
||||
const uint8_t*& data, uint32_t identifier) const
|
||||
{
|
||||
auto inner_analyzer = packet_mgr->Dispatch(identifier);
|
||||
auto inner_analyzer = dispatcher.Lookup(identifier);
|
||||
|
||||
if ( inner_analyzer == nullptr )
|
||||
{
|
||||
|
|
|
@ -10,9 +10,9 @@ namespace zeek::packet_analysis {
|
|||
/**
|
||||
* Result of packet analysis.
|
||||
*/
|
||||
//TODO: Replace with bool?
|
||||
enum class AnalyzerResult {
|
||||
Failed, // Analysis failed
|
||||
Continue, // Analysis succeeded and an encapsulated protocol was determined
|
||||
Terminate // Analysis succeeded and there is no further analysis to do
|
||||
};
|
||||
|
||||
|
@ -41,6 +41,13 @@ public:
|
|||
*/
|
||||
virtual ~Analyzer() = default;
|
||||
|
||||
/**
|
||||
* Initialize the analyzer. This method is called after the configuration
|
||||
* was read. Derived classes can override this method to implement custom
|
||||
* initialization.
|
||||
*/
|
||||
virtual void Initialize() { };
|
||||
|
||||
/**
|
||||
* Returns the tag associated with the analyzer's type.
|
||||
*/
|
||||
|
@ -62,6 +69,15 @@ public:
|
|||
*/
|
||||
bool IsAnalyzer(const char* name);
|
||||
|
||||
/**
|
||||
* Registers an analyzer to be dispatched for the given identifier.
|
||||
*
|
||||
* @param identifier The identifier an analyzer should be called for.
|
||||
* @param analyzer The analyzer that should be called.
|
||||
* @return True if the registration was successfull.
|
||||
*/
|
||||
bool RegisterAnalyzerMapping(uint32_t identifier, AnalyzerPtr analyzer);
|
||||
|
||||
/**
|
||||
* Analyzes the given packet. The data reference points to the part of the
|
||||
* raw packet to be analyzed. If the analyzed protocol encapsulates another
|
||||
|
@ -91,8 +107,10 @@ protected:
|
|||
*/
|
||||
AnalyzerResult AnalyzeInnerPacket(Packet* packet, const uint8_t*& data,
|
||||
uint32_t identifier) const;
|
||||
|
||||
private:
|
||||
Tag tag;
|
||||
Dispatcher dispatcher;
|
||||
|
||||
void Init(const Tag& tag);
|
||||
};
|
||||
|
|
|
@ -13,7 +13,6 @@ set(llanalyzer_SRCS
|
|||
Manager.cc
|
||||
Component.cc
|
||||
Tag.cc
|
||||
Config.cc
|
||||
)
|
||||
|
||||
bro_add_subdir_library(llanalyzer ${llanalyzer_SRCS})
|
||||
|
|
|
@ -1,87 +0,0 @@
|
|||
// See the file "COPYING" in the main distribution directory for copyright.
|
||||
|
||||
#include "Config.h"
|
||||
#include "Reporter.h"
|
||||
#include "DebugLogger.h"
|
||||
|
||||
namespace zeek::packet_analysis {
|
||||
|
||||
// ##############################
|
||||
// ####### DispatcherConfig #####
|
||||
// ##############################
|
||||
const std::string& DispatcherConfig::GetName() const
|
||||
{
|
||||
return name;
|
||||
}
|
||||
|
||||
const std::map<uint32_t, std::string>& DispatcherConfig::GetMappings() const
|
||||
{
|
||||
return mappings;
|
||||
}
|
||||
|
||||
void DispatcherConfig::AddMapping(uint32_t identifier,
|
||||
const std::string& analyzer_name)
|
||||
{
|
||||
DBG_LOG(DBG_PACKET_ANALYSIS, "Adding configuration mapping: %s -> %#x -> %s",
|
||||
name.c_str(), identifier, analyzer_name.c_str());
|
||||
|
||||
if ( mappings.count(identifier) )
|
||||
reporter->InternalError("Invalid config, identifier %#x already exists "
|
||||
"for dispatcher set %s.",
|
||||
identifier, name.c_str());
|
||||
|
||||
mappings.emplace(identifier, analyzer_name);
|
||||
}
|
||||
|
||||
bool DispatcherConfig::operator==(const DispatcherConfig& rhs) const
|
||||
{
|
||||
return name == rhs.name;
|
||||
}
|
||||
|
||||
bool DispatcherConfig::operator!=(const DispatcherConfig& rhs) const
|
||||
{
|
||||
return ! (rhs == *this);
|
||||
}
|
||||
|
||||
// ##############################
|
||||
// ########### Config ###########
|
||||
// ##############################
|
||||
std::optional<std::reference_wrapper<DispatcherConfig>>
|
||||
Config::GetDispatcherConfig(const std::string& name)
|
||||
{
|
||||
auto it = std::find_if(
|
||||
dispatchers.begin(), dispatchers.end(),
|
||||
[&](const DispatcherConfig& conf) {
|
||||
return conf.GetName() == name;
|
||||
});
|
||||
|
||||
if ( it == dispatchers.end() )
|
||||
return {};
|
||||
else
|
||||
return {std::ref(*it)};
|
||||
}
|
||||
|
||||
const std::vector<DispatcherConfig>& Config::GetDispatchers() const
|
||||
{
|
||||
return dispatchers;
|
||||
}
|
||||
|
||||
DispatcherConfig& Config::AddDispatcherConfig(const std::string& name)
|
||||
{
|
||||
return dispatchers.emplace_back(name);
|
||||
}
|
||||
|
||||
void Config::AddMapping(const std::string& name, uint32_t identifier,
|
||||
const std::string& analyzer_name)
|
||||
{
|
||||
// Create dispatcher config if it does not exist yet
|
||||
std::optional<std::reference_wrapper<DispatcherConfig>> dispatch_config =
|
||||
GetDispatcherConfig(name);
|
||||
|
||||
if ( ! dispatch_config )
|
||||
AddDispatcherConfig(name).AddMapping(identifier, analyzer_name);
|
||||
else
|
||||
dispatch_config->get().AddMapping(identifier, analyzer_name);
|
||||
}
|
||||
|
||||
} // namespace packet_analysis
|
|
@ -1,42 +0,0 @@
|
|||
// See the file "COPYING" in the main distribution directory for copyright.
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <algorithm>
|
||||
#include <map>
|
||||
#include <string>
|
||||
#include <utility>
|
||||
#include <vector>
|
||||
|
||||
namespace zeek::packet_analysis {
|
||||
|
||||
class DispatcherConfig {
|
||||
public:
|
||||
explicit DispatcherConfig(const std::string name) : name(std::move(name)) { }
|
||||
|
||||
const std::string& GetName() const;
|
||||
const std::map<uint32_t, std::string>& GetMappings() const;
|
||||
|
||||
void AddMapping(uint32_t identifier, const std::string& analyzer_name);
|
||||
|
||||
bool operator==(const DispatcherConfig& rhs) const;
|
||||
bool operator!=(const DispatcherConfig& rhs) const;
|
||||
|
||||
private:
|
||||
const std::string name;
|
||||
std::map<uint32_t, std::string> mappings;
|
||||
};
|
||||
|
||||
class Config {
|
||||
|
||||
public:
|
||||
const std::vector<DispatcherConfig>& GetDispatchers() const;
|
||||
std::optional<std::reference_wrapper<DispatcherConfig>> GetDispatcherConfig(const std::string& name);
|
||||
DispatcherConfig& AddDispatcherConfig(const std::string& name);
|
||||
void AddMapping(const std::string& name, uint32_t identifier, const std::string& analyzer_name);
|
||||
|
||||
private:
|
||||
std::vector<DispatcherConfig> dispatchers;
|
||||
};
|
||||
|
||||
}
|
|
@ -3,6 +3,8 @@
|
|||
#include <algorithm>
|
||||
|
||||
#include "Dispatcher.h"
|
||||
#include "Analyzer.h"
|
||||
#include "DebugLogger.h"
|
||||
|
||||
namespace zeek::packet_analysis {
|
||||
|
||||
|
@ -11,12 +13,12 @@ Dispatcher::~Dispatcher()
|
|||
FreeValues();
|
||||
}
|
||||
|
||||
bool Dispatcher::Register(uint32_t identifier, AnalyzerPtr analyzer, DispatcherPtr dispatcher)
|
||||
bool Dispatcher::Register(uint32_t identifier, AnalyzerPtr analyzer)
|
||||
{
|
||||
// If the table has size 1 and the entry is nullptr, there was nothing added yet. Just add it.
|
||||
if ( table.size() == 1 && table[0] == nullptr )
|
||||
{
|
||||
table[0] = std::make_shared<Value>(analyzer, dispatcher);
|
||||
table[0] = analyzer;
|
||||
lowest_identifier = identifier;
|
||||
return true;
|
||||
}
|
||||
|
@ -48,7 +50,7 @@ bool Dispatcher::Register(uint32_t identifier, AnalyzerPtr analyzer, DispatcherP
|
|||
int64_t index = identifier - lowest_identifier;
|
||||
if ( table[index] == nullptr )
|
||||
{
|
||||
table[index] = std::make_shared<Value>(analyzer, dispatcher);
|
||||
table[index] = analyzer;
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@ -65,19 +67,19 @@ void Dispatcher::Register(const register_map& data)
|
|||
});
|
||||
|
||||
// Register lowest first in order to do shifting only once
|
||||
Register(lowest_new->first, lowest_new->second.first, lowest_new->second.second);
|
||||
Register(lowest_new->first, lowest_new->second);
|
||||
for ( auto i = data.begin(); i != data.end(); i++ )
|
||||
{
|
||||
// Already added if i == lowest_new
|
||||
if ( i == lowest_new )
|
||||
continue;
|
||||
|
||||
if ( ! Register(i->first, i->second.first, i->second.second) )
|
||||
if ( ! Register(i->first, i->second) )
|
||||
throw std::invalid_argument("Analyzer already registered!");
|
||||
}
|
||||
}
|
||||
|
||||
ValuePtr Dispatcher::Lookup(uint32_t identifier) const
|
||||
AnalyzerPtr Dispatcher::Lookup(uint32_t identifier) const
|
||||
{
|
||||
int64_t index = identifier - lowest_identifier;
|
||||
if ( index >= 0 && index < static_cast<int64_t>(table.size()) && table[index] != nullptr )
|
||||
|
@ -88,7 +90,7 @@ ValuePtr Dispatcher::Lookup(uint32_t identifier) const
|
|||
|
||||
size_t Dispatcher::Size() const
|
||||
{
|
||||
return std::count_if(table.begin(), table.end(), [](ValuePtr v) { return v != nullptr; });
|
||||
return std::count_if(table.begin(), table.end(), [](AnalyzerPtr a) { return a != nullptr; });
|
||||
}
|
||||
|
||||
void Dispatcher::Clear()
|
||||
|
@ -111,7 +113,7 @@ void Dispatcher::DumpDebug() const
|
|||
for ( size_t i = 0; i < table.size(); i++ )
|
||||
{
|
||||
if ( table[i] != nullptr )
|
||||
DBG_LOG(DBG_PACKET_ANALYSIS, " %#8lx => %s, %p", i+lowest_identifier, table[i]->analyzer->GetAnalyzerName(), table[i]->dispatcher.get());
|
||||
DBG_LOG(DBG_PACKET_ANALYSIS, " %#8lx => %s", i+lowest_identifier, table[i]->GetAnalyzerName());
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
|
|
@ -2,43 +2,31 @@
|
|||
|
||||
#pragma once
|
||||
|
||||
#include <utility>
|
||||
#include <memory>
|
||||
#include <map>
|
||||
#include <cstdint>
|
||||
#include <vector>
|
||||
#include "Analyzer.h"
|
||||
|
||||
namespace zeek::packet_analysis {
|
||||
|
||||
class Dispatcher; // Forward decl for Value
|
||||
using DispatcherPtr = std::shared_ptr<Dispatcher>;
|
||||
class Analyzer; // Forward declaration for Value
|
||||
using AnalyzerPtr = std::shared_ptr<zeek::packet_analysis::Analyzer>;
|
||||
|
||||
using register_pair = std::pair<uint32_t, std::pair<AnalyzerPtr, DispatcherPtr>>;
|
||||
using register_map = std::map<uint32_t, std::pair<AnalyzerPtr, DispatcherPtr>>;
|
||||
|
||||
class Value {
|
||||
public:
|
||||
AnalyzerPtr analyzer;
|
||||
DispatcherPtr dispatcher;
|
||||
|
||||
Value(AnalyzerPtr analyzer, DispatcherPtr dispatcher)
|
||||
: analyzer(analyzer), dispatcher(dispatcher)
|
||||
{
|
||||
}
|
||||
};
|
||||
|
||||
using ValuePtr = std::shared_ptr<Value>;
|
||||
using register_pair = std::pair<uint32_t, AnalyzerPtr>;
|
||||
using register_map = std::map<uint32_t, AnalyzerPtr>;
|
||||
|
||||
class Dispatcher {
|
||||
public:
|
||||
Dispatcher()
|
||||
: table(std::vector<ValuePtr>(1, nullptr))
|
||||
: table(std::vector<AnalyzerPtr>(1, nullptr))
|
||||
{ }
|
||||
|
||||
~Dispatcher();
|
||||
|
||||
bool Register(uint32_t identifier, AnalyzerPtr analyzer, DispatcherPtr dispatcher);
|
||||
bool Register(uint32_t identifier, AnalyzerPtr analyzer);
|
||||
void Register(const register_map& data);
|
||||
|
||||
ValuePtr Lookup(uint32_t identifier) const;
|
||||
AnalyzerPtr Lookup(uint32_t identifier) const;
|
||||
|
||||
size_t Size() const;
|
||||
void Clear();
|
||||
|
@ -46,7 +34,7 @@ public:
|
|||
|
||||
private:
|
||||
uint32_t lowest_identifier = 0;
|
||||
std::vector<ValuePtr> table;
|
||||
std::vector<AnalyzerPtr> table;
|
||||
|
||||
void FreeValues();
|
||||
|
||||
|
|
|
@ -2,12 +2,7 @@
|
|||
|
||||
#include "Manager.h"
|
||||
|
||||
#include <list>
|
||||
#include <pcap.h>
|
||||
|
||||
#include "Config.h"
|
||||
#include "NetVar.h"
|
||||
#include "plugin/Manager.h"
|
||||
#include "Analyzer.h"
|
||||
#include "Dispatcher.h"
|
||||
|
||||
|
@ -18,13 +13,17 @@ Manager::Manager()
|
|||
{
|
||||
}
|
||||
|
||||
Manager::~Manager()
|
||||
{
|
||||
}
|
||||
|
||||
void Manager::InitPostScript()
|
||||
{
|
||||
auto analyzer_mapping = zeek::id::find("PacketAnalyzer::config_map");
|
||||
// Instantiate objects for all available analyzers
|
||||
for ( const auto& analyzerComponent : GetComponents() )
|
||||
{
|
||||
if ( AnalyzerPtr newAnalyzer = InstantiateAnalyzer(analyzerComponent->Tag()) )
|
||||
analyzers.emplace(analyzerComponent->Name(), newAnalyzer);
|
||||
}
|
||||
|
||||
// Read in analyzer map and create dispatchers
|
||||
auto& analyzer_mapping = zeek::id::find("PacketAnalyzer::config_map");
|
||||
if ( ! analyzer_mapping )
|
||||
return;
|
||||
|
||||
|
@ -32,50 +31,48 @@ void Manager::InitPostScript()
|
|||
if ( mapping_val->Size() == 0 )
|
||||
return;
|
||||
|
||||
Config configuration;
|
||||
for (unsigned int i = 0; i < mapping_val->Size(); i++)
|
||||
{
|
||||
auto* rv = mapping_val->At(i)->AsRecordVal();
|
||||
auto parent = rv->GetField("parent");
|
||||
std::string parent_name = parent ? Lookup(parent->AsEnumVal())->Name() : "ROOT";
|
||||
//TODO: Make that field a string for usability reasons
|
||||
//TODO: Check error handling when fields are omitted
|
||||
auto& parent_tag = rv->GetField("parent");
|
||||
std::string parent_name = parent_tag ? Lookup(parent_tag->AsEnumVal())->Name() : "ROOT";
|
||||
auto identifier = rv->GetField("identifier")->AsCount();
|
||||
auto analyzer = rv->GetField("analyzer")->AsEnumVal();
|
||||
auto analyzer_tag = rv->GetField("analyzer")->AsEnumVal();
|
||||
auto analyzer_name = Lookup(analyzer_tag)->Name();
|
||||
|
||||
configuration.AddMapping(parent_name, identifier, Lookup(analyzer)->Name());
|
||||
}
|
||||
|
||||
// Instantiate objects for all analyzers
|
||||
for ( const auto& current_dispatcher_config : configuration.GetDispatchers() )
|
||||
if ( analyzers.find(analyzer_name) == analyzers.end() )
|
||||
{
|
||||
for ( const auto& current_mapping : current_dispatcher_config.GetMappings() )
|
||||
{
|
||||
// Check if already instantiated
|
||||
if ( analyzers.count(current_mapping.second) != 0 )
|
||||
reporter->InternalWarning("Mapped analyzer %s not found.", analyzer_name.c_str());
|
||||
continue;
|
||||
|
||||
// Check if analyzer exists
|
||||
if ( AnalyzerPtr 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.");
|
||||
if ( parent_name == "ROOT" )
|
||||
{
|
||||
root_dispatcher.Register(identifier, analyzers[analyzer_name]);
|
||||
continue;
|
||||
}
|
||||
|
||||
// Set up default analysis
|
||||
auto it = analyzers.find("DefaultAnalyzer");
|
||||
if ( it != analyzers.end() )
|
||||
default_analyzer = it->second;
|
||||
else
|
||||
default_analyzer = InstantiateAnalyzer("DefaultAnalyzer");
|
||||
if ( analyzers.find(parent_name) == analyzers.end() )
|
||||
{
|
||||
reporter->InternalWarning("Parent analyzer %s not found.", parent_name.c_str());
|
||||
continue;
|
||||
}
|
||||
|
||||
default_dispatcher = nullptr;
|
||||
if ( default_analyzer != nullptr )
|
||||
default_dispatcher = GetDispatcher(configuration, "DefaultAnalyzer");
|
||||
auto& parent_analyzer = analyzers[parent_name];
|
||||
parent_analyzer->RegisterAnalyzerMapping(identifier, analyzers[analyzer_name]);
|
||||
}
|
||||
|
||||
current_state = root_dispatcher;
|
||||
// Set default analyzer
|
||||
auto da_it = analyzers.find("DefaultAnalyzer");
|
||||
if ( da_it == analyzers.end() )
|
||||
reporter->InternalError("DefaultAnalyzer not found.");
|
||||
default_analyzer = da_it->second;
|
||||
|
||||
// Initialize all analyzers
|
||||
for ( auto& [name, analyzer] : analyzers )
|
||||
analyzer->Initialize();
|
||||
}
|
||||
|
||||
void Manager::Done()
|
||||
|
@ -90,13 +87,6 @@ void Manager::DumpDebug()
|
|||
{
|
||||
DBG_LOG(DBG_PACKET_ANALYSIS, " %s", current->Name().c_str());
|
||||
}
|
||||
|
||||
DBG_LOG(DBG_PACKET_ANALYSIS, "ProtocolAnalyzerSet FSM:");
|
||||
for ( const auto& current : dispatchers )
|
||||
{
|
||||
DBG_LOG(DBG_PACKET_ANALYSIS, " Dispatcher (%p): %s", current.second.get(), current.first.c_str());
|
||||
current.second->DumpDebug();
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
|
@ -128,7 +118,6 @@ AnalyzerPtr Manager::InstantiateAnalyzer(const Tag& tag)
|
|||
{
|
||||
reporter->InternalError("Mismatch of requested analyzer %s and instantiated analyzer %s. This usually means that the plugin author made a mistake.",
|
||||
GetComponentName(tag).c_str(), GetComponentName(a->GetAnalyzerTag()).c_str());
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
return a;
|
||||
|
@ -146,29 +135,18 @@ void Manager::ProcessPacket(Packet* packet)
|
|||
static size_t counter = 0;
|
||||
DBG_LOG(DBG_PACKET_ANALYSIS, "Analyzing packet %ld, ts=%.3f...", ++counter, packet->time);
|
||||
#endif
|
||||
|
||||
// Start packet analysis
|
||||
const uint8_t* data = packet->data;
|
||||
|
||||
auto root_analyzer = Dispatch(packet->link_type);
|
||||
if ( root_analyzer == nullptr )
|
||||
{
|
||||
DBG_LOG(DBG_PACKET_ANALYSIS, "No analyzer for link type: %#x.", packet->link_type);
|
||||
packet->Weird("no_suitable_analyzer_found");
|
||||
}
|
||||
else
|
||||
{
|
||||
auto result = root_analyzer->Analyze(packet, data);
|
||||
auto root_analyzer = root_dispatcher.Lookup(packet->link_type);
|
||||
auto analyzer = root_analyzer == nullptr ? default_analyzer : root_analyzer;
|
||||
|
||||
auto result = analyzer->Analyze(packet, data);
|
||||
if (result == AnalyzerResult::Terminate)
|
||||
CustomEncapsulationSkip(packet, data);
|
||||
}
|
||||
|
||||
// Processing finished, reset analyzer set state for next packet
|
||||
current_state = root_dispatcher;
|
||||
|
||||
// Calculate header size after processing packet layers.
|
||||
packet->hdr_size = data - packet->data;
|
||||
packet->hdr_size = static_cast<uint32_t>(data - packet->data);
|
||||
}
|
||||
|
||||
void Manager::CustomEncapsulationSkip(Packet* packet, const uint8_t* data)
|
||||
|
@ -203,67 +181,3 @@ void Manager::CustomEncapsulationSkip(Packet* packet, const uint8_t* data)
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
AnalyzerPtr Manager::Dispatch(uint32_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)
|
||||
ValuePtr 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;
|
||||
}
|
||||
}
|
||||
|
||||
DispatcherPtr 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();
|
||||
|
||||
DispatcherPtr dispatcher = std::make_shared<Dispatcher>();
|
||||
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;
|
||||
}
|
||||
|
|
|
@ -2,23 +2,16 @@
|
|||
|
||||
#pragma once
|
||||
|
||||
#include <queue>
|
||||
#include <vector>
|
||||
|
||||
#include "Config.h"
|
||||
#include "Tag.h"
|
||||
#include "Component.h"
|
||||
#include "plugin/ComponentManager.h"
|
||||
#include "iosource/Packet.h"
|
||||
#include "Dict.h"
|
||||
#include "net_util.h"
|
||||
#include "Dispatcher.h"
|
||||
|
||||
namespace zeek::packet_analysis {
|
||||
|
||||
class Analyzer;
|
||||
class Dispatcher;
|
||||
using AnalyzerPtr = std::shared_ptr<Analyzer>;
|
||||
using DispatcherPtr = std::shared_ptr<Dispatcher>;
|
||||
|
||||
class Manager : public plugin::ComponentManager<Tag, Component> {
|
||||
public:
|
||||
|
@ -30,7 +23,7 @@ public:
|
|||
/**
|
||||
* Destructor.
|
||||
*/
|
||||
~Manager();
|
||||
~Manager() = default;
|
||||
|
||||
/**
|
||||
* Second-stage initialization of the manager. This is called late
|
||||
|
@ -50,14 +43,6 @@ public:
|
|||
*/
|
||||
void DumpDebug(); // Called after zeek_init() events.
|
||||
|
||||
/**
|
||||
* Returns the tag associated with an analyer name, or the tag
|
||||
* associated with an error if no such analyzer exists.
|
||||
*
|
||||
* @param name The canonical analyzer name to check.
|
||||
*/
|
||||
Tag GetAnalyzerTag(const char* name);
|
||||
|
||||
/**
|
||||
* Instantiates a new analyzer instance.
|
||||
*
|
||||
|
@ -87,18 +72,7 @@ public:
|
|||
*/
|
||||
void ProcessPacket(Packet* packet);
|
||||
|
||||
/**
|
||||
* Looks up a packet analyzer by identifier considering the context
|
||||
* as given by current_state.
|
||||
*
|
||||
* @param identifier The identifier to look up.
|
||||
*
|
||||
* @return The analyzer corresponding to the identifier.
|
||||
*/
|
||||
AnalyzerPtr Dispatch(uint32_t identifier);
|
||||
|
||||
private:
|
||||
|
||||
/**
|
||||
* Skips a fixed amount of packet data that is defined by encap_hdr_size.
|
||||
* It is assumed that an IP header follows.
|
||||
|
@ -109,13 +83,8 @@ private:
|
|||
*/
|
||||
void CustomEncapsulationSkip(Packet* packet, const uint8_t* data);
|
||||
|
||||
DispatcherPtr GetDispatcher(Config& configuration, const std::string& dispatcher_name);
|
||||
|
||||
std::map<std::string, AnalyzerPtr> analyzers;
|
||||
std::map<std::string, DispatcherPtr> dispatchers;
|
||||
DispatcherPtr root_dispatcher = nullptr;
|
||||
DispatcherPtr default_dispatcher = nullptr;
|
||||
DispatcherPtr current_state = nullptr;
|
||||
Dispatcher root_dispatcher;
|
||||
AnalyzerPtr default_analyzer = nullptr;
|
||||
};
|
||||
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
#add_subdirectory(default)
|
||||
#
|
||||
add_subdirectory(default)
|
||||
|
||||
#add_subdirectory(wrapper)
|
||||
#add_subdirectory(null)
|
||||
add_subdirectory(ethernet)
|
||||
|
|
|
@ -10,17 +10,17 @@ DefaultAnalyzer::DefaultAnalyzer()
|
|||
{
|
||||
}
|
||||
|
||||
zeek::packet_analysis::AnalysisResultTuple DefaultAnalyzer::Analyze(Packet* packet, const uint8_t*& data)
|
||||
zeek::packet_analysis::AnalyzerResult DefaultAnalyzer::Analyze(Packet* packet, const uint8_t*& data)
|
||||
{
|
||||
// Assume we're pointing at IP. Just figure out which version.
|
||||
if ( data + sizeof(struct ip) >= packet->GetEndOfData() )
|
||||
{
|
||||
packet->Weird("packet_analyzer_truncated_header");
|
||||
return { AnalyzerResult::Failed, 0 };
|
||||
return AnalyzerResult::Failed;
|
||||
}
|
||||
|
||||
auto ip = (const struct ip *)data;
|
||||
uint32_t protocol = ip->ip_v;
|
||||
|
||||
return { AnalyzerResult::Continue, protocol };
|
||||
return AnalyzeInnerPacket(packet, data, protocol);
|
||||
}
|
||||
|
|
|
@ -12,7 +12,7 @@ public:
|
|||
DefaultAnalyzer();
|
||||
~DefaultAnalyzer() override = default;
|
||||
|
||||
AnalysisResultTuple Analyze(Packet* packet, const uint8_t*& data) override;
|
||||
AnalyzerResult Analyze(Packet* packet, const uint8_t*& data) override;
|
||||
|
||||
static zeek::packet_analysis::AnalyzerPtr Instantiate()
|
||||
{
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue