diff --git a/scripts/base/packet-protocols/ethernet/main.zeek b/scripts/base/packet-protocols/ethernet/main.zeek index 217780423e..05feb246db 100644 --- a/scripts/base/packet-protocols/ethernet/main.zeek +++ b/scripts/base/packet-protocols/ethernet/main.zeek @@ -1,4 +1,4 @@ -module LL_ETHERNET; +module PacketAnalyzer::Ethernet; 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, $analyzer=PacketAnalyzer::ANALYZER_DEFAULTANALYZER) }; + +const snap_analyzer: PacketAnalyzer::Tag &redef; +const novell_raw_analyzer: PacketAnalyzer::Tag &redef; +const llc_analyzer: PacketAnalyzer::Tag &redef; diff --git a/src/packet_analysis/Manager.cc b/src/packet_analysis/Manager.cc index b17911bcc4..663c85fd6f 100644 --- a/src/packet_analysis/Manager.cc +++ b/src/packet_analysis/Manager.cc @@ -92,6 +92,49 @@ void Manager::DumpDebug() #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(data - packet->data); + } + AnalyzerPtr Manager::InstantiateAnalyzer(const Tag& tag) { Component* c = Lookup(tag); @@ -119,7 +162,7 @@ AnalyzerPtr Manager::InstantiateAnalyzer(const Tag& tag) if ( tag != a->GetAnalyzerTag() ) { 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()); + GetComponentName(tag).c_str(), GetComponentName(a->GetAnalyzerTag()).c_str()); } return a; @@ -131,31 +174,6 @@ AnalyzerPtr Manager::InstantiateAnalyzer(const std::string& name) 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(data - packet->data); - } - void Manager::CustomEncapsulationSkip(Packet* packet, const uint8_t* data) { if ( zeek::detail::encap_hdr_size > 0 ) diff --git a/src/packet_analysis/Manager.h b/src/packet_analysis/Manager.h index da0a74b70b..cbded374e1 100644 --- a/src/packet_analysis/Manager.h +++ b/src/packet_analysis/Manager.h @@ -44,26 +44,22 @@ public: 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 - * null if tag is invalid, the requested analyzer is disabled, or the - * analyzer can't be instantiated. + * @return The analyzer instance or nullptr if no instance is found. */ - 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. * - * @return The new analyzer instance. Returns - * null if the name is not known or if the requested analyzer that is - * disabled. + * @return The analyzer instance or nullptr if no instance is found. */ - AnalyzerPtr InstantiateAnalyzer(const std::string& name); + AnalyzerPtr GetAnalyzer(const std::string& name); /** * Processes a packet by applying the configured packet analyzers. @@ -73,6 +69,26 @@ public: void ProcessPacket(Packet* packet); 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. * It is assumed that an IP header follows. diff --git a/src/packet_analysis/protocol/ethernet/Ethernet.cc b/src/packet_analysis/protocol/ethernet/Ethernet.cc index 7f152ad5bc..cd5c5889b4 100644 --- a/src/packet_analysis/protocol/ethernet/Ethernet.cc +++ b/src/packet_analysis/protocol/ethernet/Ethernet.cc @@ -2,6 +2,7 @@ #include "Ethernet.h" #include "NetVar.h" +#include "Manager.h" 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) { auto end_of_data = packet->GetEndOfData(); @@ -59,22 +80,25 @@ zeek::packet_analysis::AnalyzerResult EthernetAnalyzer::Analyze(Packet* packet, return AnalyzerResult::Failed; } - // In the following we use undefined EtherTypes to signal uncommon - // frame types. This allows specialized analyzers to take over. + // Let specialized analyzers take over for non Ethernet II frames. // 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) - 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 + eth_analyzer = NovellRawAnalyzer; + else + // IEEE 802.2 LLC + eth_analyzer = LLCAnalyzer; - // Novell raw IEEE 802.3 - if ( data[14] == 0xFF && data[15] == 0xFF) - return AnalyzeInnerPacket(packet, data, 1503); + if ( eth_analyzer ) + return eth_analyzer->Analyze(packet, data); - - // IEEE 802.2 LLC - return AnalyzeInnerPacket(packet, data, 1501); + return AnalyzerResult::Terminate; } // Undefined (1500 < EtherType < 1536) diff --git a/src/packet_analysis/protocol/ethernet/Ethernet.h b/src/packet_analysis/protocol/ethernet/Ethernet.h index 22f51b233d..c1f89a6f02 100644 --- a/src/packet_analysis/protocol/ethernet/Ethernet.h +++ b/src/packet_analysis/protocol/ethernet/Ethernet.h @@ -12,12 +12,20 @@ public: EthernetAnalyzer(); ~EthernetAnalyzer() override = default; + void Initialize() override; AnalyzerResult Analyze(Packet* packet, const uint8_t*& data) override; static zeek::packet_analysis::AnalyzerPtr Instantiate() { return std::make_shared(); } + +private: + AnalyzerPtr SNAPAnalyzer = nullptr; + AnalyzerPtr NovellRawAnalyzer = nullptr; + AnalyzerPtr LLCAnalyzer = nullptr; + + AnalyzerPtr LoadAnalyzer(const std::string& name); }; }