Move dispatching into packet analyzers.

WIP that updates only the Ethernet analyzer.
This commit is contained in:
Jan Grashoefer 2020-08-19 16:36:09 +02:00 committed by Tim Wojtulewicz
parent 96d0e11bb8
commit 9feda100b9
13 changed files with 105 additions and 88 deletions

View file

@ -1,11 +1,11 @@
@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
@load base/packet-protocols/ieee802_11_radio #@load base/packet-protocols/ieee802_11_radio
@load base/packet-protocols/linux_sll #@load base/packet-protocols/linux_sll
@load base/packet-protocols/nflog #@load base/packet-protocols/nflog
@load base/packet-protocols/null #@load base/packet-protocols/null
@load base/packet-protocols/ppp_serial #@load base/packet-protocols/ppp_serial
@load base/packet-protocols/pppoe #@load base/packet-protocols/pppoe
@load base/packet-protocols/vlan #@load base/packet-protocols/vlan

View file

@ -4,13 +4,13 @@ const DLT_EN10MB : count = 1;
redef PacketAnalyzer::config_map += { redef PacketAnalyzer::config_map += {
PacketAnalyzer::ConfigEntry($identifier=DLT_EN10MB, $analyzer=PacketAnalyzer::ANALYZER_ETHERNET), 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=0x0800, $analyzer=PacketAnalyzer::ANALYZER_IPV4),
PacketAnalyzer::ConfigEntry($parent=PacketAnalyzer::ANALYZER_ETHERNET, $identifier=0x86DD, $analyzer=PacketAnalyzer::ANALYZER_IPV6), 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=0x0806, $analyzer=PacketAnalyzer::ANALYZER_ARP),
PacketAnalyzer::ConfigEntry($parent=PacketAnalyzer::ANALYZER_ETHERNET, $identifier=0x8035, $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=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)
}; };

View file

@ -44,4 +44,23 @@ bool Analyzer::IsAnalyzer(const char* name)
return packet_mgr->GetComponentName(tag).compare(name) == 0; 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);
}
} }

View file

@ -68,18 +68,29 @@ public:
* protocol, the data reference should be updated to point to that payload. * protocol, the data reference should be updated to point to that payload.
* *
* @param packet The packet to analyze. * @param packet The packet to analyze.
*
* @param data Reference to the payload pointer into the raw packet. * @param data Reference to the payload pointer into the raw packet.
* *
* @return A tuple of analysis result and identifier. The result indicates * @return A tuple of analysis result and identifier. The result indicates
* how to proceed. If analysis can continue, the identifier determines the * how to proceed. If analysis can continue, the identifier determines the
* encapsulated protocol. * encapsulated protocol.
*/ */
virtual AnalysisResultTuple Analyze(Packet* packet, const uint8_t*& data) = 0; virtual AnalyzerResult Analyze(Packet* packet, const uint8_t*& data) = 0;
protected: protected:
friend class Manager; 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: private:
Tag tag; Tag tag;

View file

@ -147,44 +147,22 @@ void Manager::ProcessPacket(Packet* packet)
DBG_LOG(DBG_PACKET_ANALYSIS, "Analyzing packet %ld, ts=%.3f...", ++counter, packet->time); DBG_LOG(DBG_PACKET_ANALYSIS, "Analyzing packet %ld, ts=%.3f...", ++counter, packet->time);
#endif #endif
// Dispatch and analyze layers // Start packet analysis
AnalyzerResult result = AnalyzerResult::Continue;
uint32_t next_layer_id = packet->link_type;
const uint8_t* data = packet->data; 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 (result == AnalyzerResult::Terminate)
if ( current_analyzer == nullptr ) CustomEncapsulationSkip(packet, data);
{ }
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);
// Processing finished, reset analyzer set state for next packet // Processing finished, reset analyzer set state for next packet
current_state = root_dispatcher; current_state = root_dispatcher;

View file

@ -87,6 +87,16 @@ public:
*/ */
void ProcessPacket(Packet* packet); 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: private:
/** /**
@ -99,8 +109,6 @@ private:
*/ */
void CustomEncapsulationSkip(Packet* packet, const uint8_t* data); void CustomEncapsulationSkip(Packet* packet, const uint8_t* data);
AnalyzerPtr Dispatch(uint32_t identifier);
DispatcherPtr GetDispatcher(Config& configuration, const std::string& dispatcher_name); DispatcherPtr GetDispatcher(Config& configuration, const std::string& dispatcher_name);
std::map<std::string, AnalyzerPtr> analyzers; std::map<std::string, AnalyzerPtr> analyzers;

View file

@ -1,18 +1,18 @@
add_subdirectory(default) #add_subdirectory(default)
#
add_subdirectory(wrapper) #add_subdirectory(wrapper)
add_subdirectory(null) #add_subdirectory(null)
add_subdirectory(ethernet) add_subdirectory(ethernet)
add_subdirectory(vlan) #add_subdirectory(vlan)
add_subdirectory(pppoe) #add_subdirectory(pppoe)
add_subdirectory(ppp_serial) #add_subdirectory(ppp_serial)
add_subdirectory(ieee802_11) #add_subdirectory(ieee802_11)
add_subdirectory(ieee802_11_radio) #add_subdirectory(ieee802_11_radio)
add_subdirectory(fddi) #add_subdirectory(fddi)
add_subdirectory(nflog) #add_subdirectory(nflog)
add_subdirectory(mpls) #add_subdirectory(mpls)
add_subdirectory(linux_sll) #add_subdirectory(linux_sll)
#
add_subdirectory(arp) #add_subdirectory(arp)
add_subdirectory(ipv4) add_subdirectory(ipv4)
add_subdirectory(ipv6) add_subdirectory(ipv6)

View file

@ -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(); auto end_of_data = packet->GetEndOfData();
@ -19,7 +19,7 @@ zeek::packet_analysis::AnalysisResultTuple EthernetAnalyzer::Analyze(Packet* pac
if ( data + 16 >= end_of_data ) if ( data + 16 >= end_of_data )
{ {
packet->Weird("truncated_ethernet_frame"); packet->Weird("truncated_ethernet_frame");
return { AnalyzerResult::Failed, 0 }; return AnalyzerResult::Failed;
} }
// Skip past Cisco FabricPath to encapsulated ethernet frame. // 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 ) if ( data + cfplen + 14 >= end_of_data )
{ {
packet->Weird("truncated_link_header_cfp"); packet->Weird("truncated_link_header_cfp");
return { AnalyzerResult::Failed, 0 }; return AnalyzerResult::Failed;
} }
data += cfplen; data += cfplen;
@ -47,7 +47,7 @@ zeek::packet_analysis::AnalysisResultTuple EthernetAnalyzer::Analyze(Packet* pac
if ( protocol >= 1536 ) if ( protocol >= 1536 )
{ {
data += 14; data += 14;
return { AnalyzerResult::Continue, protocol }; return AnalyzeInnerPacket(packet, data, protocol);
} }
// Other ethernet frame types // Other ethernet frame types
@ -56,27 +56,28 @@ zeek::packet_analysis::AnalysisResultTuple EthernetAnalyzer::Analyze(Packet* pac
if ( data + 16 >= end_of_data ) if ( data + 16 >= end_of_data )
{ {
packet->Weird("truncated_ethernet_frame"); packet->Weird("truncated_ethernet_frame");
return { AnalyzerResult::Failed, 0 }; return AnalyzerResult::Failed;
} }
// In the following we use undefined EtherTypes to signal uncommon // In the following we use undefined EtherTypes to signal uncommon
// frame types. This allows specialized analyzers to take over. // 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 // IEEE 802.2 SNAP
if ( data[14] == 0xAA && data[15] == 0xAA) if ( data[14] == 0xAA && data[15] == 0xAA)
return { AnalyzerResult::Continue, 1502 }; return AnalyzeInnerPacket(packet, data, 1502);
// Novell raw IEEE 802.3 // Novell raw IEEE 802.3
if ( data[14] == 0xFF && data[15] == 0xFF) if ( data[14] == 0xFF && data[15] == 0xFF)
return { AnalyzerResult::Continue, 1503 }; return AnalyzeInnerPacket(packet, data, 1503);
// IEEE 802.2 LLC // IEEE 802.2 LLC
return { AnalyzerResult::Continue, 1501 }; return AnalyzeInnerPacket(packet, data, 1501);
} }
// Undefined (1500 < EtherType < 1536) // Undefined (1500 < EtherType < 1536)
packet->Weird("undefined_ether_type"); packet->Weird("undefined_ether_type");
return { AnalyzerResult::Failed, protocol }; return AnalyzerResult::Failed;
} }

View file

@ -12,7 +12,7 @@ public:
EthernetAnalyzer(); EthernetAnalyzer();
~EthernetAnalyzer() override = default; ~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() static zeek::packet_analysis::AnalyzerPtr Instantiate()
{ {

View file

@ -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; packet->l3_proto = L3_IPV4;
// Leave packet analyzer land // Leave packet analyzer land
return { AnalyzerResult::Terminate, 0 }; return AnalyzerResult::Terminate;
} }

View file

@ -12,7 +12,7 @@ public:
IPv4Analyzer(); IPv4Analyzer();
~IPv4Analyzer() override = default; ~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() static zeek::packet_analysis::AnalyzerPtr Instantiate()
{ {

View file

@ -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; packet->l3_proto = L3_IPV6;
// Leave packet analyzer land // Leave packet analyzer land
return { AnalyzerResult::Terminate, 0 }; return AnalyzerResult::Terminate;
} }

View file

@ -12,7 +12,7 @@ public:
IPv6Analyzer(); IPv6Analyzer();
~IPv6Analyzer() override = default; ~IPv6Analyzer() override = default;
AnalysisResultTuple Analyze(Packet* packet, const uint8_t*& data) override; AnalyzerResult Analyze(Packet* packet, const uint8_t*& data) override;
static AnalyzerPtr Instantiate() static AnalyzerPtr Instantiate()
{ {