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/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

View file

@ -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)
};

View file

@ -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);
}
}

View file

@ -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;

View file

@ -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;

View file

@ -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<std::string, AnalyzerPtr> analyzers;

View file

@ -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)

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();
@ -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;
}

View file

@ -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()
{

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

View file

@ -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()
{

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

View file

@ -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()
{