Bring back default packet analysis.

Default analyzers can be configured per packet analyzer by omitting the
identifier in the ConfigEntry.
This commit is contained in:
Jan Grashoefer 2020-08-21 18:11:05 +02:00 committed by Tim Wojtulewicz
parent d4ff5a236c
commit 462b1fe3a2
9 changed files with 81 additions and 21 deletions

View file

@ -5357,8 +5357,9 @@ export {
parent : PacketAnalyzer::Tag &optional; parent : PacketAnalyzer::Tag &optional;
# A numeric identifier, which can be found in the packet data, that denotes the # A numeric identifier, which can be found in the packet data, that denotes the
# encapsulated protocol. # encapsulated protocol. This field is optional. If it is not included, the
identifier : count; # configured child analyzer will be used as default analyzer.
identifier : count &optional;
# The analyzer that corresponds to the above identifier. # The analyzer that corresponds to the above identifier.
analyzer : PacketAnalyzer::Tag; analyzer : PacketAnalyzer::Tag;

View file

@ -1,4 +1,4 @@
#@load base/packet-protocols/default @load base/packet-protocols/default
@load base/packet-protocols/ethernet @load base/packet-protocols/ethernet
#@load base/packet-protocols/fddi #@load base/packet-protocols/fddi
#@load base/packet-protocols/ieee802_11 #@load base/packet-protocols/ieee802_11

View file

@ -1,6 +1,7 @@
module LL_DEFAULT; module LL_DEFAULT;
redef PacketAnalyzer::config_map += { redef PacketAnalyzer::config_map += {
PacketAnalyzer::ConfigEntry($analyzer=PacketAnalyzer::ANALYZER_DEFAULTANALYZER),
PacketAnalyzer::ConfigEntry($parent=PacketAnalyzer::ANALYZER_DEFAULTANALYZER, $identifier=4, $analyzer=PacketAnalyzer::ANALYZER_IPV4), PacketAnalyzer::ConfigEntry($parent=PacketAnalyzer::ANALYZER_DEFAULTANALYZER, $identifier=4, $analyzer=PacketAnalyzer::ANALYZER_IPV4),
PacketAnalyzer::ConfigEntry($parent=PacketAnalyzer::ANALYZER_DEFAULTANALYZER, $identifier=6, $analyzer=PacketAnalyzer::ANALYZER_IPV6) PacketAnalyzer::ConfigEntry($parent=PacketAnalyzer::ANALYZER_DEFAULTANALYZER, $identifier=6, $analyzer=PacketAnalyzer::ANALYZER_IPV6)
}; };

View file

@ -12,5 +12,6 @@ redef PacketAnalyzer::config_map += {
#PacketAnalyzer::ConfigEntry($parent=PacketAnalyzer::ANALYZER_ETHERNET, $identifier=0x8100, $analyzer=PacketAnalyzer::ANALYZER_VLAN), #PacketAnalyzer::ConfigEntry($parent=PacketAnalyzer::ANALYZER_ETHERNET, $identifier=0x8100, $analyzer=PacketAnalyzer::ANALYZER_VLAN),
#PacketAnalyzer::ConfigEntry($parent=PacketAnalyzer::ANALYZER_ETHERNET, $identifier=0x88A8, $analyzer=PacketAnalyzer::ANALYZER_VLAN), #PacketAnalyzer::ConfigEntry($parent=PacketAnalyzer::ANALYZER_ETHERNET, $identifier=0x88A8, $analyzer=PacketAnalyzer::ANALYZER_VLAN),
#PacketAnalyzer::ConfigEntry($parent=PacketAnalyzer::ANALYZER_ETHERNET, $identifier=0x9100, $analyzer=PacketAnalyzer::ANALYZER_VLAN), #PacketAnalyzer::ConfigEntry($parent=PacketAnalyzer::ANALYZER_ETHERNET, $identifier=0x9100, $analyzer=PacketAnalyzer::ANALYZER_VLAN),
#PacketAnalyzer::ConfigEntry($parent=PacketAnalyzer::ANALYZER_ETHERNET, $identifier=0x8864, $analyzer=PacketAnalyzer::ANALYZER_PPPOE) #PacketAnalyzer::ConfigEntry($parent=PacketAnalyzer::ANALYZER_ETHERNET, $identifier=0x8864, $analyzer=PacketAnalyzer::ANALYZER_PPPOE),
PacketAnalyzer::ConfigEntry($parent=PacketAnalyzer::ANALYZER_ETHERNET, $analyzer=PacketAnalyzer::ANALYZER_DEFAULTANALYZER)
}; };

View file

@ -47,14 +47,24 @@ bool Analyzer::RegisterAnalyzerMapping(uint32_t identifier, AnalyzerPtr analyzer
return dispatcher.Register(identifier, std::move(analyzer)); return dispatcher.Register(identifier, std::move(analyzer));
} }
void Analyzer::RegisterDefaultAnalyzer(AnalyzerPtr default_analyzer)
{
this->default_analyzer = std::move(default_analyzer);
}
AnalyzerPtr Analyzer::Lookup(uint32_t identifier) const
{
return dispatcher.Lookup(identifier);
}
AnalyzerResult Analyzer::AnalyzeInnerPacket(Packet* packet, AnalyzerResult Analyzer::AnalyzeInnerPacket(Packet* packet,
const uint8_t*& data, uint32_t identifier) const const uint8_t*& data, uint32_t identifier) const
{ {
auto inner_analyzer = dispatcher.Lookup(identifier); auto inner_analyzer = Lookup(identifier);
inner_analyzer = inner_analyzer ? inner_analyzer : default_analyzer;
if ( inner_analyzer == nullptr ) if ( inner_analyzer == nullptr )
{ {
//TODO: Handle default analysis here
DBG_LOG(DBG_PACKET_ANALYSIS, "Analysis in %s failed, could not find analyzer for identifier %#x.", DBG_LOG(DBG_PACKET_ANALYSIS, "Analysis in %s failed, could not find analyzer for identifier %#x.",
GetAnalyzerName(), identifier); GetAnalyzerName(), identifier);
packet->Weird("no_suitable_analyzer_found"); packet->Weird("no_suitable_analyzer_found");

View file

@ -74,10 +74,17 @@ public:
* *
* @param identifier The identifier an analyzer should be called for. * @param identifier The identifier an analyzer should be called for.
* @param analyzer The analyzer that should be called. * @param analyzer The analyzer that should be called.
* @return True if the registration was successfull. * @return True if the registration was successful.
*/ */
bool RegisterAnalyzerMapping(uint32_t identifier, AnalyzerPtr analyzer); bool RegisterAnalyzerMapping(uint32_t identifier, AnalyzerPtr analyzer);
/**
* Registers a default analyzer.
*
* @param default_analyzer The analyzer to use as default.
*/
void RegisterDefaultAnalyzer(AnalyzerPtr default_analyzer);
/** /**
* Analyzes the given packet. The data reference points to the part of the * Analyzes the given packet. The data reference points to the part of the
* raw packet to be analyzed. If the analyzed protocol encapsulates another * raw packet to be analyzed. If the analyzed protocol encapsulates another
@ -95,6 +102,16 @@ public:
protected: protected:
friend class Manager; friend class Manager;
/**
* Looks up the analyzer for the encapsulated protocol based on the given
* identifier.
*
* @param identifier Identifier for the encapsulated protocol.
* @return The analyzer registered for the given identifier. Returns a
* nullptr if no analyzer is registered.
*/
AnalyzerPtr Lookup(uint32_t identifier) const;
/** /**
* Triggers analysis of the encapsulated packet. The encapsulated protocol * Triggers analysis of the encapsulated packet. The encapsulated protocol
* is determined using the given identifier. * is determined using the given identifier.
@ -105,12 +122,13 @@ protected:
* *
* @return The outcome of the analysis. * @return The outcome of the analysis.
*/ */
AnalyzerResult AnalyzeInnerPacket(Packet* packet, const uint8_t*& data, virtual AnalyzerResult AnalyzeInnerPacket(Packet* packet, const uint8_t*& data,
uint32_t identifier) const; uint32_t identifier) const;
private: private:
Tag tag; Tag tag;
Dispatcher dispatcher; Dispatcher dispatcher;
AnalyzerPtr default_analyzer = nullptr;
void Init(const Tag& tag); void Init(const Tag& tag);
}; };

View file

@ -36,9 +36,9 @@ void Manager::InitPostScript()
auto* rv = mapping_val->At(i)->AsRecordVal(); auto* rv = mapping_val->At(i)->AsRecordVal();
//TODO: Make that field a string for usability reasons //TODO: Make that field a string for usability reasons
//TODO: Check error handling when fields are omitted //TODO: Check error handling when fields are omitted
auto& parent_tag = rv->GetField("parent"); auto& parent_val = rv->GetField("parent");
std::string parent_name = parent_tag ? Lookup(parent_tag->AsEnumVal())->Name() : "ROOT"; std::string parent_name = parent_val ? Lookup(parent_val->AsEnumVal())->Name() : "ROOT";
auto identifier = rv->GetField("identifier")->AsCount(); auto& identifier_val = rv->GetField("identifier");
auto analyzer_tag = rv->GetField("analyzer")->AsEnumVal(); auto analyzer_tag = rv->GetField("analyzer")->AsEnumVal();
auto analyzer_name = Lookup(analyzer_tag)->Name(); auto analyzer_name = Lookup(analyzer_tag)->Name();
@ -50,7 +50,11 @@ void Manager::InitPostScript()
if ( parent_name == "ROOT" ) if ( parent_name == "ROOT" )
{ {
root_dispatcher.Register(identifier, analyzers[analyzer_name]); if ( identifier_val )
root_dispatcher.Register(identifier_val->AsCount(),
analyzers[analyzer_name]);
else
default_analyzer = analyzers[analyzer_name];
continue; continue;
} }
@ -61,15 +65,13 @@ void Manager::InitPostScript()
} }
auto& parent_analyzer = analyzers[parent_name]; auto& parent_analyzer = analyzers[parent_name];
parent_analyzer->RegisterAnalyzerMapping(identifier, analyzers[analyzer_name]); if ( identifier_val )
parent_analyzer->RegisterAnalyzerMapping(identifier_val->AsCount(),
analyzers[analyzer_name]);
else
parent_analyzer->RegisterDefaultAnalyzer(analyzers[analyzer_name]);
} }
// 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 // Initialize all analyzers
for ( auto& [name, analyzer] : analyzers ) for ( auto& [name, analyzer] : analyzers )
analyzer->Initialize(); analyzer->Initialize();
@ -139,7 +141,12 @@ void Manager::ProcessPacket(Packet* packet)
const uint8_t* data = packet->data; const uint8_t* data = packet->data;
auto root_analyzer = root_dispatcher.Lookup(packet->link_type); auto root_analyzer = root_dispatcher.Lookup(packet->link_type);
auto analyzer = root_analyzer == nullptr ? default_analyzer : root_analyzer; auto analyzer = root_analyzer ? root_analyzer : default_analyzer;
if ( !analyzer )
{
reporter->InternalWarning("No analyzer for link type %#x", packet->link_type);
return;
}
auto result = analyzer->Analyze(packet, data); auto result = analyzer->Analyze(packet, data);
if (result == AnalyzerResult::Terminate) if (result == AnalyzerResult::Terminate)

View file

@ -24,3 +24,21 @@ zeek::packet_analysis::AnalyzerResult DefaultAnalyzer::Analyze(Packet* packet, c
return AnalyzeInnerPacket(packet, data, protocol); return AnalyzeInnerPacket(packet, data, protocol);
} }
zeek::packet_analysis::AnalyzerResult DefaultAnalyzer::AnalyzeInnerPacket(Packet* packet,
const uint8_t*& data, uint32_t identifier) const
{
auto inner_analyzer = Lookup(identifier);
if ( inner_analyzer == nullptr )
{
DBG_LOG(DBG_PACKET_ANALYSIS, "Default analysis in %s failed, could not find analyzer for identifier %#x.",
GetAnalyzerName(), identifier);
packet->Weird("no_suitable_analyzer_found");
return AnalyzerResult::Failed;
}
DBG_LOG(DBG_PACKET_ANALYSIS, "Default analysis in %s succeeded, next layer identifier is %#x.",
GetAnalyzerName(), identifier);
return inner_analyzer->Analyze(packet, data);
}

View file

@ -18,6 +18,10 @@ public:
{ {
return std::make_shared<DefaultAnalyzer>(); return std::make_shared<DefaultAnalyzer>();
} }
protected:
AnalyzerResult AnalyzeInnerPacket(Packet* packet, const uint8_t*& data,
uint32_t identifier) const override;
}; };
} }