From 9feda100b993b8f1e5cbb8e41bdfa99ba7c540ab Mon Sep 17 00:00:00 2001 From: Jan Grashoefer Date: Wed, 19 Aug 2020 16:36:09 +0200 Subject: [PATCH] Move dispatching into packet analyzers. WIP that updates only the Ethernet analyzer. --- scripts/base/packet-protocols/__load__.zeek | 20 ++++---- .../base/packet-protocols/ethernet/main.zeek | 14 +++--- src/packet_analysis/Analyzer.cc | 21 +++++++- src/packet_analysis/Analyzer.h | 15 +++++- src/packet_analysis/Manager.cc | 48 +++++-------------- src/packet_analysis/Manager.h | 12 ++++- src/packet_analysis/protocol/CMakeLists.txt | 30 ++++++------ .../protocol/ethernet/Ethernet.cc | 19 ++++---- .../protocol/ethernet/Ethernet.h | 2 +- src/packet_analysis/protocol/ipv4/IPv4.cc | 4 +- src/packet_analysis/protocol/ipv4/IPv4.h | 2 +- src/packet_analysis/protocol/ipv6/IPv6.cc | 4 +- src/packet_analysis/protocol/ipv6/IPv6.h | 2 +- 13 files changed, 105 insertions(+), 88 deletions(-) diff --git a/scripts/base/packet-protocols/__load__.zeek b/scripts/base/packet-protocols/__load__.zeek index 60c804f2fd..c64d5442a4 100644 --- a/scripts/base/packet-protocols/__load__.zeek +++ b/scripts/base/packet-protocols/__load__.zeek @@ -1,11 +1,11 @@ -@load base/packet-protocols/default +#@load base/packet-protocols/default @load base/packet-protocols/ethernet -@load base/packet-protocols/fddi -@load base/packet-protocols/ieee802_11 -@load base/packet-protocols/ieee802_11_radio -@load base/packet-protocols/linux_sll -@load base/packet-protocols/nflog -@load base/packet-protocols/null -@load base/packet-protocols/ppp_serial -@load base/packet-protocols/pppoe -@load base/packet-protocols/vlan +#@load base/packet-protocols/fddi +#@load base/packet-protocols/ieee802_11 +#@load base/packet-protocols/ieee802_11_radio +#@load base/packet-protocols/linux_sll +#@load base/packet-protocols/nflog +#@load base/packet-protocols/null +#@load base/packet-protocols/ppp_serial +#@load base/packet-protocols/pppoe +#@load base/packet-protocols/vlan diff --git a/scripts/base/packet-protocols/ethernet/main.zeek b/scripts/base/packet-protocols/ethernet/main.zeek index ca11767466..b7a242efb0 100644 --- a/scripts/base/packet-protocols/ethernet/main.zeek +++ b/scripts/base/packet-protocols/ethernet/main.zeek @@ -4,13 +4,13 @@ const DLT_EN10MB : count = 1; redef PacketAnalyzer::config_map += { PacketAnalyzer::ConfigEntry($identifier=DLT_EN10MB, $analyzer=PacketAnalyzer::ANALYZER_ETHERNET), - PacketAnalyzer::ConfigEntry($parent=PacketAnalyzer::ANALYZER_ETHERNET, $identifier=0x8847, $analyzer=PacketAnalyzer::ANALYZER_MPLS), + #PacketAnalyzer::ConfigEntry($parent=PacketAnalyzer::ANALYZER_ETHERNET, $identifier=0x8847, $analyzer=PacketAnalyzer::ANALYZER_MPLS), PacketAnalyzer::ConfigEntry($parent=PacketAnalyzer::ANALYZER_ETHERNET, $identifier=0x0800, $analyzer=PacketAnalyzer::ANALYZER_IPV4), PacketAnalyzer::ConfigEntry($parent=PacketAnalyzer::ANALYZER_ETHERNET, $identifier=0x86DD, $analyzer=PacketAnalyzer::ANALYZER_IPV6), - PacketAnalyzer::ConfigEntry($parent=PacketAnalyzer::ANALYZER_ETHERNET, $identifier=0x0806, $analyzer=PacketAnalyzer::ANALYZER_ARP), - PacketAnalyzer::ConfigEntry($parent=PacketAnalyzer::ANALYZER_ETHERNET, $identifier=0x8035, $analyzer=PacketAnalyzer::ANALYZER_ARP), - 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=0x9100, $analyzer=PacketAnalyzer::ANALYZER_VLAN), - PacketAnalyzer::ConfigEntry($parent=PacketAnalyzer::ANALYZER_ETHERNET, $identifier=0x8864, $analyzer=PacketAnalyzer::ANALYZER_PPPOE) + #PacketAnalyzer::ConfigEntry($parent=PacketAnalyzer::ANALYZER_ETHERNET, $identifier=0x0806, $analyzer=PacketAnalyzer::ANALYZER_ARP), + #PacketAnalyzer::ConfigEntry($parent=PacketAnalyzer::ANALYZER_ETHERNET, $identifier=0x8035, $analyzer=PacketAnalyzer::ANALYZER_ARP), + #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=0x9100, $analyzer=PacketAnalyzer::ANALYZER_VLAN), + #PacketAnalyzer::ConfigEntry($parent=PacketAnalyzer::ANALYZER_ETHERNET, $identifier=0x8864, $analyzer=PacketAnalyzer::ANALYZER_PPPOE) }; diff --git a/src/packet_analysis/Analyzer.cc b/src/packet_analysis/Analyzer.cc index c045a9302f..6e40e270cd 100644 --- a/src/packet_analysis/Analyzer.cc +++ b/src/packet_analysis/Analyzer.cc @@ -44,4 +44,23 @@ bool Analyzer::IsAnalyzer(const char* name) return packet_mgr->GetComponentName(tag).compare(name) == 0; } -} +AnalyzerResult Analyzer::AnalyzeInnerPacket(Packet* packet, + const uint8_t*& data, uint32_t identifier) const + { + auto inner_analyzer = packet_mgr->Dispatch(identifier); + + 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.", + GetAnalyzerName(), identifier); + packet->Weird("no_suitable_analyzer_found"); + return AnalyzerResult::Failed; + } + + DBG_LOG(DBG_PACKET_ANALYSIS, "Analysis in %s succeeded, next layer identifier is %#x.", + GetAnalyzerName(), identifier); + return inner_analyzer->Analyze(packet, data); + } + +} \ No newline at end of file diff --git a/src/packet_analysis/Analyzer.h b/src/packet_analysis/Analyzer.h index e6b974aefc..be6e47f5b5 100644 --- a/src/packet_analysis/Analyzer.h +++ b/src/packet_analysis/Analyzer.h @@ -68,18 +68,29 @@ public: * protocol, the data reference should be updated to point to that payload. * * @param packet The packet to analyze. - * * @param data Reference to the payload pointer into the raw packet. * * @return A tuple of analysis result and identifier. The result indicates * how to proceed. If analysis can continue, the identifier determines the * encapsulated protocol. */ - virtual AnalysisResultTuple Analyze(Packet* packet, const uint8_t*& data) = 0; + virtual AnalyzerResult Analyze(Packet* packet, const uint8_t*& data) = 0; protected: friend class Manager; + /** + * Triggers analysis of the encapsulated packet. The encapsulated protocol + * is determined using the given identifier. + * + * @param packet The packet to analyze. + * @param data Reference to the payload pointer into the raw packet. + * @param identifier The identifier of the encapsulated protocol. + * + * @return The outcome of the analysis. + */ + AnalyzerResult AnalyzeInnerPacket(Packet* packet, const uint8_t*& data, + uint32_t identifier) const; private: Tag tag; diff --git a/src/packet_analysis/Manager.cc b/src/packet_analysis/Manager.cc index a535b93b8d..35d52c9244 100644 --- a/src/packet_analysis/Manager.cc +++ b/src/packet_analysis/Manager.cc @@ -147,44 +147,22 @@ void Manager::ProcessPacket(Packet* packet) DBG_LOG(DBG_PACKET_ANALYSIS, "Analyzing packet %ld, ts=%.3f...", ++counter, packet->time); #endif - // Dispatch and analyze layers - AnalyzerResult result = AnalyzerResult::Continue; - uint32_t next_layer_id = packet->link_type; + // Start packet analysis const uint8_t* data = packet->data; - do + + auto root_analyzer = Dispatch(packet->link_type); + if ( root_analyzer == nullptr ) { - auto current_analyzer = Dispatch(next_layer_id); + 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); - // Analyzer not found - if ( current_analyzer == nullptr ) - { - DBG_LOG(DBG_PACKET_ANALYSIS, "Could not find analyzer for identifier %#x", next_layer_id); - packet->Weird("no_suitable_analyzer_found"); - break; - } - - // Analyze this layer and get identifier of next layer protocol - std::tie(result, next_layer_id) = current_analyzer->Analyze(packet, data); - -#ifdef DEBUG - switch ( result ) - { - case AnalyzerResult::Continue: - DBG_LOG(DBG_PACKET_ANALYSIS, "Analysis in %s succeeded, next layer identifier is %#x.", - current_analyzer->GetAnalyzerName(), next_layer_id); - break; - case AnalyzerResult::Terminate: - DBG_LOG(DBG_PACKET_ANALYSIS, "Done, last found layer identifier was %#x.", next_layer_id); - break; - case AnalyzerResult::Failed: - DBG_LOG(DBG_PACKET_ANALYSIS, "Analysis failed in %s", current_analyzer->GetAnalyzerName()); - } -#endif - - } while ( result == AnalyzerResult::Continue ); - - if ( result == AnalyzerResult::Terminate ) - CustomEncapsulationSkip(packet, data); + if (result == AnalyzerResult::Terminate) + CustomEncapsulationSkip(packet, data); + } // Processing finished, reset analyzer set state for next packet current_state = root_dispatcher; diff --git a/src/packet_analysis/Manager.h b/src/packet_analysis/Manager.h index f576952228..4ad9f76b11 100644 --- a/src/packet_analysis/Manager.h +++ b/src/packet_analysis/Manager.h @@ -87,6 +87,16 @@ 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: /** @@ -99,8 +109,6 @@ private: */ void CustomEncapsulationSkip(Packet* packet, const uint8_t* data); - AnalyzerPtr Dispatch(uint32_t identifier); - DispatcherPtr GetDispatcher(Config& configuration, const std::string& dispatcher_name); std::map analyzers; diff --git a/src/packet_analysis/protocol/CMakeLists.txt b/src/packet_analysis/protocol/CMakeLists.txt index fbcef0f2c9..dc3327460d 100644 --- a/src/packet_analysis/protocol/CMakeLists.txt +++ b/src/packet_analysis/protocol/CMakeLists.txt @@ -1,18 +1,18 @@ -add_subdirectory(default) - -add_subdirectory(wrapper) -add_subdirectory(null) +#add_subdirectory(default) +# +#add_subdirectory(wrapper) +#add_subdirectory(null) add_subdirectory(ethernet) -add_subdirectory(vlan) -add_subdirectory(pppoe) -add_subdirectory(ppp_serial) -add_subdirectory(ieee802_11) -add_subdirectory(ieee802_11_radio) -add_subdirectory(fddi) -add_subdirectory(nflog) -add_subdirectory(mpls) -add_subdirectory(linux_sll) - -add_subdirectory(arp) +#add_subdirectory(vlan) +#add_subdirectory(pppoe) +#add_subdirectory(ppp_serial) +#add_subdirectory(ieee802_11) +#add_subdirectory(ieee802_11_radio) +#add_subdirectory(fddi) +#add_subdirectory(nflog) +#add_subdirectory(mpls) +#add_subdirectory(linux_sll) +# +#add_subdirectory(arp) add_subdirectory(ipv4) add_subdirectory(ipv6) diff --git a/src/packet_analysis/protocol/ethernet/Ethernet.cc b/src/packet_analysis/protocol/ethernet/Ethernet.cc index 198d2912ee..7f152ad5bc 100644 --- a/src/packet_analysis/protocol/ethernet/Ethernet.cc +++ b/src/packet_analysis/protocol/ethernet/Ethernet.cc @@ -10,7 +10,7 @@ EthernetAnalyzer::EthernetAnalyzer() { } -zeek::packet_analysis::AnalysisResultTuple 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(); @@ -19,7 +19,7 @@ zeek::packet_analysis::AnalysisResultTuple EthernetAnalyzer::Analyze(Packet* pac if ( data + 16 >= end_of_data ) { packet->Weird("truncated_ethernet_frame"); - return { AnalyzerResult::Failed, 0 }; + return AnalyzerResult::Failed; } // Skip past Cisco FabricPath to encapsulated ethernet frame. @@ -30,7 +30,7 @@ zeek::packet_analysis::AnalysisResultTuple EthernetAnalyzer::Analyze(Packet* pac if ( data + cfplen + 14 >= end_of_data ) { packet->Weird("truncated_link_header_cfp"); - return { AnalyzerResult::Failed, 0 }; + return AnalyzerResult::Failed; } data += cfplen; @@ -47,7 +47,7 @@ zeek::packet_analysis::AnalysisResultTuple EthernetAnalyzer::Analyze(Packet* pac if ( protocol >= 1536 ) { data += 14; - return { AnalyzerResult::Continue, protocol }; + return AnalyzeInnerPacket(packet, data, protocol); } // Other ethernet frame types @@ -56,27 +56,28 @@ zeek::packet_analysis::AnalysisResultTuple EthernetAnalyzer::Analyze(Packet* pac if ( data + 16 >= end_of_data ) { packet->Weird("truncated_ethernet_frame"); - return { AnalyzerResult::Failed, 0 }; + return AnalyzerResult::Failed; } // In the following we use undefined EtherTypes to signal uncommon // frame types. This allows specialized analyzers to take over. // Note that pdata remains at the start of the ethernet frame. + //TODO: Lookup the analyzers on startup // IEEE 802.2 SNAP if ( data[14] == 0xAA && data[15] == 0xAA) - return { AnalyzerResult::Continue, 1502 }; + return AnalyzeInnerPacket(packet, data, 1502); // Novell raw IEEE 802.3 if ( data[14] == 0xFF && data[15] == 0xFF) - return { AnalyzerResult::Continue, 1503 }; + return AnalyzeInnerPacket(packet, data, 1503); // IEEE 802.2 LLC - return { AnalyzerResult::Continue, 1501 }; + return AnalyzeInnerPacket(packet, data, 1501); } // Undefined (1500 < EtherType < 1536) packet->Weird("undefined_ether_type"); - return { AnalyzerResult::Failed, protocol }; + return AnalyzerResult::Failed; } diff --git a/src/packet_analysis/protocol/ethernet/Ethernet.h b/src/packet_analysis/protocol/ethernet/Ethernet.h index d6779ede58..22f51b233d 100644 --- a/src/packet_analysis/protocol/ethernet/Ethernet.h +++ b/src/packet_analysis/protocol/ethernet/Ethernet.h @@ -12,7 +12,7 @@ public: EthernetAnalyzer(); ~EthernetAnalyzer() 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() { diff --git a/src/packet_analysis/protocol/ipv4/IPv4.cc b/src/packet_analysis/protocol/ipv4/IPv4.cc index ad199f97f8..57aef8eb25 100644 --- a/src/packet_analysis/protocol/ipv4/IPv4.cc +++ b/src/packet_analysis/protocol/ipv4/IPv4.cc @@ -9,10 +9,10 @@ IPv4Analyzer::IPv4Analyzer() { } -zeek::packet_analysis::AnalysisResultTuple IPv4Analyzer::Analyze(Packet* packet, const uint8_t*& data) +zeek::packet_analysis::AnalyzerResult IPv4Analyzer::Analyze(Packet* packet, const uint8_t*& data) { packet->l3_proto = L3_IPV4; // Leave packet analyzer land - return { AnalyzerResult::Terminate, 0 }; + return AnalyzerResult::Terminate; } diff --git a/src/packet_analysis/protocol/ipv4/IPv4.h b/src/packet_analysis/protocol/ipv4/IPv4.h index 37026cabd9..984ad4e532 100644 --- a/src/packet_analysis/protocol/ipv4/IPv4.h +++ b/src/packet_analysis/protocol/ipv4/IPv4.h @@ -12,7 +12,7 @@ public: IPv4Analyzer(); ~IPv4Analyzer() 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() { diff --git a/src/packet_analysis/protocol/ipv6/IPv6.cc b/src/packet_analysis/protocol/ipv6/IPv6.cc index 9380a1fe85..903dfd1607 100644 --- a/src/packet_analysis/protocol/ipv6/IPv6.cc +++ b/src/packet_analysis/protocol/ipv6/IPv6.cc @@ -9,10 +9,10 @@ IPv6Analyzer::IPv6Analyzer() { } -zeek::packet_analysis::AnalysisResultTuple IPv6Analyzer::Analyze(Packet* packet, const uint8_t*& data) +zeek::packet_analysis::AnalyzerResult IPv6Analyzer::Analyze(Packet* packet, const uint8_t*& data) { packet->l3_proto = L3_IPV6; // Leave packet analyzer land - return { AnalyzerResult::Terminate, 0 }; + return AnalyzerResult::Terminate; } diff --git a/src/packet_analysis/protocol/ipv6/IPv6.h b/src/packet_analysis/protocol/ipv6/IPv6.h index f7ad9fdc74..ffff59a668 100644 --- a/src/packet_analysis/protocol/ipv6/IPv6.h +++ b/src/packet_analysis/protocol/ipv6/IPv6.h @@ -12,7 +12,7 @@ public: IPv6Analyzer(); ~IPv6Analyzer() override = default; - AnalysisResultTuple Analyze(Packet* packet, const uint8_t*& data) override; + AnalyzerResult Analyze(Packet* packet, const uint8_t*& data) override; static AnalyzerPtr Instantiate() {