Remove magic identifiers from Ethernet analyzer.

This commit is contained in:
Jan Grashoefer 2020-08-24 14:42:16 +02:00 committed by Tim Wojtulewicz
parent 462b1fe3a2
commit cbdaa53f85
5 changed files with 119 additions and 49 deletions

View file

@ -1,4 +1,4 @@
module LL_ETHERNET; module PacketAnalyzer::Ethernet;
const DLT_EN10MB : count = 1; const DLT_EN10MB : count = 1;
@ -15,3 +15,7 @@ redef PacketAnalyzer::config_map += {
#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) PacketAnalyzer::ConfigEntry($parent=PacketAnalyzer::ANALYZER_ETHERNET, $analyzer=PacketAnalyzer::ANALYZER_DEFAULTANALYZER)
}; };
const snap_analyzer: PacketAnalyzer::Tag &redef;
const novell_raw_analyzer: PacketAnalyzer::Tag &redef;
const llc_analyzer: PacketAnalyzer::Tag &redef;

View file

@ -92,6 +92,49 @@ void Manager::DumpDebug()
#endif #endif
} }
AnalyzerPtr Manager::GetAnalyzer(EnumVal *val)
{
auto analyzer_comp = Lookup(val);
if ( ! analyzer_comp )
return nullptr;
return GetAnalyzer(analyzer_comp->Name());
}
AnalyzerPtr Manager::GetAnalyzer(const std::string& name)
{
auto analyzer_it = analyzers.find(name);
if ( analyzer_it == analyzers.end() )
return nullptr;
return analyzer_it->second;
}
void Manager::ProcessPacket(Packet* packet)
{
#ifdef DEBUG
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 = root_dispatcher.Lookup(packet->link_type);
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);
if (result == AnalyzerResult::Terminate)
CustomEncapsulationSkip(packet, data);
// Calculate header size after processing packet layers.
packet->hdr_size = static_cast<uint32_t>(data - packet->data);
}
AnalyzerPtr Manager::InstantiateAnalyzer(const Tag& tag) AnalyzerPtr Manager::InstantiateAnalyzer(const Tag& tag)
{ {
Component* c = Lookup(tag); Component* c = Lookup(tag);
@ -131,31 +174,6 @@ AnalyzerPtr Manager::InstantiateAnalyzer(const std::string& name)
return tag ? InstantiateAnalyzer(tag) : nullptr; return tag ? InstantiateAnalyzer(tag) : nullptr;
} }
void Manager::ProcessPacket(Packet* packet)
{
#ifdef DEBUG
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 = root_dispatcher.Lookup(packet->link_type);
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);
if (result == AnalyzerResult::Terminate)
CustomEncapsulationSkip(packet, data);
// Calculate header size after processing packet layers.
packet->hdr_size = static_cast<uint32_t>(data - packet->data);
}
void Manager::CustomEncapsulationSkip(Packet* packet, const uint8_t* data) void Manager::CustomEncapsulationSkip(Packet* packet, const uint8_t* data)
{ {
if ( zeek::detail::encap_hdr_size > 0 ) if ( zeek::detail::encap_hdr_size > 0 )

View file

@ -44,26 +44,22 @@ public:
void DumpDebug(); // Called after zeek_init() events. void DumpDebug(); // Called after zeek_init() events.
/** /**
* Instantiates a new analyzer instance. * Looks up an analyzer instance.
* *
* @param tag The analyzer's tag. * @param val The analyzer's tag value.
* *
* @return The new analyzer instance. Returns * @return The analyzer instance or nullptr if no instance is found.
* null if tag is invalid, the requested analyzer is disabled, or the
* analyzer can't be instantiated.
*/ */
AnalyzerPtr InstantiateAnalyzer(const Tag& tag); AnalyzerPtr GetAnalyzer(EnumVal *val);
/** /**
* Instantiates a new analyzer. * Looks up an analyzer instance.
* *
* @param name The name of the analyzer. * @param name The name of the analyzer.
* *
* @return The new analyzer instance. Returns * @return The analyzer instance or nullptr if no instance is found.
* null if the name is not known or if the requested analyzer that is
* disabled.
*/ */
AnalyzerPtr InstantiateAnalyzer(const std::string& name); AnalyzerPtr GetAnalyzer(const std::string& name);
/** /**
* Processes a packet by applying the configured packet analyzers. * Processes a packet by applying the configured packet analyzers.
@ -73,6 +69,26 @@ public:
void ProcessPacket(Packet* packet); void ProcessPacket(Packet* packet);
private: private:
/**
* Instantiates a new analyzer instance.
*
* @param tag The analyzer's tag.
*
* @return The new analyzer instance. Returns null if tag is invalid, the
* requested analyzer is disabled, or the analyzer can't be instantiated.
*/
AnalyzerPtr InstantiateAnalyzer(const Tag& tag);
/**
* Instantiates a new analyzer.
*
* @param name The name of the analyzer.
*
* @return The new analyzer instance. Returns null if the name is not known
* or if the requested analyzer that is disabled.
*/
AnalyzerPtr InstantiateAnalyzer(const std::string& name);
/** /**
* 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.

View file

@ -2,6 +2,7 @@
#include "Ethernet.h" #include "Ethernet.h"
#include "NetVar.h" #include "NetVar.h"
#include "Manager.h"
using namespace zeek::packet_analysis::Ethernet; using namespace zeek::packet_analysis::Ethernet;
@ -10,6 +11,26 @@ EthernetAnalyzer::EthernetAnalyzer()
{ {
} }
void EthernetAnalyzer::Initialize()
{
SNAPAnalyzer = LoadAnalyzer("PacketAnalyzer::Ethernet::snap_analyzer");
NovellRawAnalyzer = LoadAnalyzer("PacketAnalyzer::Ethernet::novell_raw_analyzer");
LLCAnalyzer = LoadAnalyzer("PacketAnalyzer::Ethernet::llc_analyzer");
}
zeek::packet_analysis::AnalyzerPtr EthernetAnalyzer::LoadAnalyzer(const std::string &name)
{
auto& analyzer = zeek::id::find(name);
if ( ! analyzer )
return nullptr;
auto& analyzer_val = analyzer->GetVal();
if ( ! analyzer_val )
return nullptr;
return packet_mgr->GetAnalyzer(analyzer_val->AsEnumVal());
}
zeek::packet_analysis::AnalyzerResult EthernetAnalyzer::Analyze(Packet* packet, const uint8_t*& data) zeek::packet_analysis::AnalyzerResult EthernetAnalyzer::Analyze(Packet* packet, const uint8_t*& data)
{ {
auto end_of_data = packet->GetEndOfData(); auto end_of_data = packet->GetEndOfData();
@ -59,22 +80,25 @@ zeek::packet_analysis::AnalyzerResult EthernetAnalyzer::Analyze(Packet* packet,
return AnalyzerResult::Failed; return AnalyzerResult::Failed;
} }
// In the following we use undefined EtherTypes to signal uncommon // Let specialized analyzers take over for non Ethernet II frames.
// frame types. This allows specialized analyzers to take over.
// Note that pdata remains at the start of the ethernet frame. // Note that pdata remains at the start of the ethernet frame.
//TODO: Lookup the analyzers on startup
// IEEE 802.2 SNAP AnalyzerPtr eth_analyzer = nullptr;
if ( data[14] == 0xAA && data[15] == 0xAA) if ( data[14] == 0xAA && data[15] == 0xAA)
return AnalyzeInnerPacket(packet, data, 1502); // IEEE 802.2 SNAP
eth_analyzer = SNAPAnalyzer;
else if ( data[14] == 0xFF && data[15] == 0xFF)
// Novell raw IEEE 802.3 // Novell raw IEEE 802.3
if ( data[14] == 0xFF && data[15] == 0xFF) eth_analyzer = NovellRawAnalyzer;
return AnalyzeInnerPacket(packet, data, 1503); else
// IEEE 802.2 LLC // IEEE 802.2 LLC
return AnalyzeInnerPacket(packet, data, 1501); eth_analyzer = LLCAnalyzer;
if ( eth_analyzer )
return eth_analyzer->Analyze(packet, data);
return AnalyzerResult::Terminate;
} }
// Undefined (1500 < EtherType < 1536) // Undefined (1500 < EtherType < 1536)

View file

@ -12,12 +12,20 @@ public:
EthernetAnalyzer(); EthernetAnalyzer();
~EthernetAnalyzer() override = default; ~EthernetAnalyzer() override = default;
void Initialize() override;
AnalyzerResult Analyze(Packet* packet, const uint8_t*& data) override; AnalyzerResult Analyze(Packet* packet, const uint8_t*& data) override;
static zeek::packet_analysis::AnalyzerPtr Instantiate() static zeek::packet_analysis::AnalyzerPtr Instantiate()
{ {
return std::make_shared<EthernetAnalyzer>(); return std::make_shared<EthernetAnalyzer>();
} }
private:
AnalyzerPtr SNAPAnalyzer = nullptr;
AnalyzerPtr NovellRawAnalyzer = nullptr;
AnalyzerPtr LLCAnalyzer = nullptr;
AnalyzerPtr LoadAnalyzer(const std::string& name);
}; };
} }