mirror of
https://github.com/zeek/zeek.git
synced 2025-10-02 06:38:20 +00:00
Move dispatching into packet analyzers.
WIP that updates only the Ethernet analyzer.
This commit is contained in:
parent
96d0e11bb8
commit
9feda100b9
13 changed files with 105 additions and 88 deletions
|
@ -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
|
||||||
|
|
|
@ -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)
|
||||||
};
|
};
|
||||||
|
|
|
@ -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);
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
|
@ -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;
|
||||||
|
|
||||||
|
|
|
@ -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;
|
||||||
|
|
|
@ -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;
|
||||||
|
|
|
@ -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)
|
||||||
|
|
|
@ -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;
|
||||||
}
|
}
|
||||||
|
|
|
@ -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()
|
||||||
{
|
{
|
||||||
|
|
|
@ -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;
|
||||||
}
|
}
|
||||||
|
|
|
@ -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()
|
||||||
{
|
{
|
||||||
|
|
|
@ -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;
|
||||||
}
|
}
|
||||||
|
|
|
@ -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()
|
||||||
{
|
{
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue