Improve packet analyzer API.

This commit is contained in:
Jan Grashoefer 2020-08-31 17:13:22 +02:00 committed by Tim Wojtulewicz
parent d5ca0f9da5
commit 90eb97876f
40 changed files with 138 additions and 136 deletions

View file

@ -79,11 +79,6 @@ void Packet::Weird(const char* name)
l2_valid = false; l2_valid = false;
} }
const u_char* const Packet::GetEndOfData() const
{
return data + cap_len;
}
IntrusivePtr<RecordVal> Packet::ToRawPktHdrVal() const IntrusivePtr<RecordVal> Packet::ToRawPktHdrVal() const
{ {
static auto raw_pkt_hdr_type = id::find_type<RecordType>("raw_pkt_hdr"); static auto raw_pkt_hdr_type = id::find_type<RecordType>("raw_pkt_hdr");

View file

@ -140,13 +140,6 @@ public:
[[deprecated("Remove in v4.1. Use ToRawPktHdrval() instead.")]] [[deprecated("Remove in v4.1. Use ToRawPktHdrval() instead.")]]
RecordVal* BuildPktHdrVal() const; RecordVal* BuildPktHdrVal() const;
/**
* Returns the end of the captured data for bound checking.
*
* @return End of the packet data.
*/
const u_char* const GetEndOfData() const;
/** /**
* Describes the packet, with standard signature. * Describes the packet, with standard signature.
*/ */
@ -228,7 +221,7 @@ public:
*/ */
bool l3_checksummed; bool l3_checksummed;
// Wrapper to generate a packet-level weird. Has to be public for llanalyzers to use it. // Wrapper to generate a packet-level weird. Has to be public for packet analyzers to use it.
void Weird(const char* name); void Weird(const char* name);
private: private:

View file

@ -57,8 +57,8 @@ AnalyzerPtr Analyzer::Lookup(uint32_t identifier) const
return dispatcher.Lookup(identifier); return dispatcher.Lookup(identifier);
} }
AnalyzerResult Analyzer::AnalyzeInnerPacket(Packet* packet, AnalyzerResult Analyzer::ForwardPacket(size_t len, const uint8_t* data, Packet* packet,
const uint8_t*& data, uint32_t identifier) const uint32_t identifier) const
{ {
auto inner_analyzer = Lookup(identifier); auto inner_analyzer = Lookup(identifier);
if ( ! inner_analyzer ) if ( ! inner_analyzer )
@ -74,13 +74,13 @@ AnalyzerResult Analyzer::AnalyzeInnerPacket(Packet* packet,
DBG_LOG(DBG_PACKET_ANALYSIS, "Analysis in %s succeeded, next layer identifier is %#x.", DBG_LOG(DBG_PACKET_ANALYSIS, "Analysis in %s succeeded, next layer identifier is %#x.",
GetAnalyzerName(), identifier); GetAnalyzerName(), identifier);
return inner_analyzer->Analyze(packet, data); return inner_analyzer->AnalyzePacket(len, data, packet);
} }
AnalyzerResult Analyzer::AnalyzeInnerPacket(Packet* packet, const uint8_t*& data) const AnalyzerResult Analyzer::ForwardPacket(size_t len, const uint8_t* data, Packet* packet) const
{ {
if ( default_analyzer ) if ( default_analyzer )
return default_analyzer->Analyze(packet, data); return default_analyzer->AnalyzePacket(len, data, packet);
DBG_LOG(DBG_PACKET_ANALYSIS, "Analysis in %s stopped, no default analyzer available.", DBG_LOG(DBG_PACKET_ANALYSIS, "Analysis in %s stopped, no default analyzer available.",
GetAnalyzerName()); GetAnalyzerName());

View file

@ -10,7 +10,6 @@ namespace zeek::packet_analysis {
/** /**
* Result of packet analysis. * Result of packet analysis.
*/ */
//TODO: Replace with bool?
enum class AnalyzerResult { enum class AnalyzerResult {
Failed, // Analysis failed Failed, // Analysis failed
Terminate // Analysis succeeded and there is no further analysis to do Terminate // Analysis succeeded and there is no further analysis to do
@ -85,18 +84,19 @@ public:
void RegisterDefaultAnalyzer(AnalyzerPtr default_analyzer); void RegisterDefaultAnalyzer(AnalyzerPtr default_analyzer);
/** /**
* Analyzes the given packet. The data reference points to the part of the * Analyzes the given packet. A common case is that the analyzed protocol
* raw packet to be analyzed. If the analyzed protocol encapsulates another * encapsulates another protocol, which can be determined by an identifier
* protocol, the data reference should be updated to point to that payload. * in the header. In this case, derived classes may use ForwardPacket() to
* forward the payload to the corresponding analyzer.
* *
* @param packet The packet to analyze. * @param len The number of bytes passed in.
* @param data Reference to the payload pointer into the raw packet. * @param data Pointer to the input to process.
* @param packet Object that maintains the packet's meta data.
* *
* @return A tuple of analysis result and identifier. The result indicates * @return The outcome of the analysis.
* how to proceed. If analysis can continue, the identifier determines the
* encapsulated protocol.
*/ */
virtual AnalyzerResult Analyze(Packet* packet, const uint8_t*& data) = 0; virtual AnalyzerResult AnalyzePacket(size_t len, const uint8_t* data,
Packet* packet) = 0;
protected: protected:
friend class Manager; friend class Manager;
@ -121,7 +121,7 @@ protected:
* *
* @return The outcome of the analysis. * @return The outcome of the analysis.
*/ */
AnalyzerResult AnalyzeInnerPacket(Packet* packet, const uint8_t*& data, AnalyzerResult ForwardPacket(size_t len, const uint8_t* data, Packet* packet,
uint32_t identifier) const; uint32_t identifier) const;
/** /**
@ -133,7 +133,7 @@ protected:
* *
* @return The outcome of the analysis. * @return The outcome of the analysis.
*/ */
AnalyzerResult AnalyzeInnerPacket(Packet* packet, const uint8_t*& data) const; AnalyzerResult ForwardPacket(size_t len, const uint8_t* data, Packet* packet) const;
private: private:
Tag tag; Tag tag;

View file

@ -120,8 +120,6 @@ 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
// Start packet analysis // Start packet analysis
const uint8_t* data = packet->data;
auto root_analyzer = root_dispatcher.Lookup(packet->link_type); auto root_analyzer = root_dispatcher.Lookup(packet->link_type);
auto analyzer = root_analyzer ? root_analyzer : default_analyzer; auto analyzer = root_analyzer ? root_analyzer : default_analyzer;
if ( !analyzer ) if ( !analyzer )
@ -130,10 +128,7 @@ void Manager::ProcessPacket(Packet* packet)
return; return;
} }
auto result = analyzer->Analyze(packet, data); auto result = analyzer->AnalyzePacket(packet->cap_len, packet->data, packet);
// Calculate header size after processing packet layers.
packet->hdr_size = static_cast<uint32_t>(data - packet->data);
} }
AnalyzerPtr Manager::InstantiateAnalyzer(const Tag& tag) AnalyzerPtr Manager::InstantiateAnalyzer(const Tag& tag)

View file

@ -1,6 +1,5 @@
add_subdirectory(skip) add_subdirectory(skip)
add_subdirectory(wrapper)
add_subdirectory(null) add_subdirectory(null)
add_subdirectory(ethernet) add_subdirectory(ethernet)
add_subdirectory(vlan) add_subdirectory(vlan)

View file

@ -81,18 +81,24 @@ ARPAnalyzer::ARPAnalyzer()
#define ARPOP_INVREPLY ARPOP_InREPLY #define ARPOP_INVREPLY ARPOP_InREPLY
#endif #endif
zeek::packet_analysis::AnalyzerResult ARPAnalyzer::Analyze(Packet* packet, const uint8_t*& data) zeek::packet_analysis::AnalyzerResult ARPAnalyzer::AnalyzePacket(size_t len,
const uint8_t* data, Packet* packet)
{ {
packet->l3_proto = L3_ARP; packet->l3_proto = L3_ARP;
// Check whether the header is complete.
if ( sizeof(struct arp_pkthdr) > len )
{
packet->Weird("truncated_ARP");
return AnalyzerResult::Failed;
}
// Check whether the packet is OK ("inspired" in tcpdump's print-arp.c). // Check whether the packet is OK ("inspired" in tcpdump's print-arp.c).
auto ah = (const struct arp_pkthdr*) data; auto ah = (const struct arp_pkthdr*) data;
// Check the size. // Check the size.
auto min_length = (ar_tpa(ah) - (char*) data) + ah->ar_pln; size_t min_length = (ar_tpa(ah) - (char*) data) + ah->ar_pln;
auto pkt_hdr_len = data - packet->data; if ( min_length > len )
auto real_length = packet->cap_len - pkt_hdr_len;
if ( min_length > real_length )
{ {
packet->Weird("truncated_ARP"); packet->Weird("truncated_ARP");
return AnalyzerResult::Failed; return AnalyzerResult::Failed;

View file

@ -18,7 +18,7 @@ public:
ARPAnalyzer(); ARPAnalyzer();
~ARPAnalyzer() override = default; ~ARPAnalyzer() override = default;
AnalyzerResult Analyze(Packet* packet, const uint8_t*& data) override; AnalyzerResult AnalyzePacket(size_t len, const uint8_t* data, Packet* packet) override;
static zeek::packet_analysis::AnalyzerPtr Instantiate() static zeek::packet_analysis::AnalyzerPtr Instantiate()
{ {

View file

@ -31,13 +31,12 @@ zeek::packet_analysis::AnalyzerPtr EthernetAnalyzer::LoadAnalyzer(const std::str
return packet_mgr->GetAnalyzer(analyzer_val->AsEnumVal()); return packet_mgr->GetAnalyzer(analyzer_val->AsEnumVal());
} }
zeek::packet_analysis::AnalyzerResult EthernetAnalyzer::Analyze(Packet* packet, const uint8_t*& data) zeek::packet_analysis::AnalyzerResult EthernetAnalyzer::AnalyzePacket(size_t len,
const uint8_t* data, Packet* packet)
{ {
auto end_of_data = packet->GetEndOfData();
// Make sure that we actually got an entire ethernet header before trying // Make sure that we actually got an entire ethernet header before trying
// to pull bytes out of it. // to pull bytes out of it.
if ( data + 16 >= end_of_data ) if ( 16 >= len )
{ {
packet->Weird("truncated_ethernet_frame"); packet->Weird("truncated_ethernet_frame");
return AnalyzerResult::Failed; return AnalyzerResult::Failed;
@ -48,13 +47,14 @@ zeek::packet_analysis::AnalyzerResult EthernetAnalyzer::Analyze(Packet* packet,
{ {
auto constexpr cfplen = 16; auto constexpr cfplen = 16;
if ( data + cfplen + 14 >= end_of_data ) if ( cfplen + 14 >= len )
{ {
packet->Weird("truncated_link_header_cfp"); packet->Weird("truncated_link_header_cfp");
return AnalyzerResult::Failed; return AnalyzerResult::Failed;
} }
data += cfplen; data += cfplen;
len -= cfplen;
} }
// Get protocol being carried from the ethernet frame. // Get protocol being carried from the ethernet frame.
@ -66,15 +66,12 @@ zeek::packet_analysis::AnalyzerResult EthernetAnalyzer::Analyze(Packet* packet,
// Ethernet II frames // Ethernet II frames
if ( protocol >= 1536 ) if ( protocol >= 1536 )
{ return ForwardPacket(len - 14, data + 14, packet, protocol);
data += 14;
return AnalyzeInnerPacket(packet, data, protocol);
}
// Other ethernet frame types // Other ethernet frame types
if ( protocol <= 1500 ) if ( protocol <= 1500 )
{ {
if ( data + 16 >= end_of_data ) if ( 16 >= len )
{ {
packet->Weird("truncated_ethernet_frame"); packet->Weird("truncated_ethernet_frame");
return AnalyzerResult::Failed; return AnalyzerResult::Failed;
@ -96,7 +93,7 @@ zeek::packet_analysis::AnalyzerResult EthernetAnalyzer::Analyze(Packet* packet,
eth_analyzer = LLCAnalyzer; eth_analyzer = LLCAnalyzer;
if ( eth_analyzer ) if ( eth_analyzer )
return eth_analyzer->Analyze(packet, data); return eth_analyzer->AnalyzePacket(len, data, packet);
return AnalyzerResult::Terminate; return AnalyzerResult::Terminate;
} }

View file

@ -13,7 +13,7 @@ public:
~EthernetAnalyzer() override = default; ~EthernetAnalyzer() override = default;
void Initialize() override; void Initialize() override;
AnalyzerResult Analyze(Packet* packet, const uint8_t*& data) override; AnalyzerResult AnalyzePacket(size_t len, const uint8_t* data, Packet* packet) override;
static zeek::packet_analysis::AnalyzerPtr Instantiate() static zeek::packet_analysis::AnalyzerPtr Instantiate()
{ {

View file

@ -10,17 +10,17 @@ FDDIAnalyzer::FDDIAnalyzer()
{ {
} }
zeek::packet_analysis::AnalyzerResult FDDIAnalyzer::Analyze(Packet* packet, const uint8_t*& data) zeek::packet_analysis::AnalyzerResult FDDIAnalyzer::AnalyzePacket(size_t len,
const uint8_t* data, Packet* packet)
{ {
auto hdr_size = 13 + 8; // FDDI header + LLC size_t hdr_size = 13 + 8; // FDDI header + LLC
if ( data + hdr_size >= packet->GetEndOfData() ) if ( hdr_size >= len )
{ {
packet->Weird("FDDI_analyzer_failed"); packet->Weird("FDDI_analyzer_failed");
return AnalyzerResult::Failed; return AnalyzerResult::Failed;
} }
// We just skip the header and hope for default analysis // We just skip the header and hope for default analysis
data += hdr_size; return ForwardPacket(len - hdr_size, data + hdr_size, packet);
return AnalyzeInnerPacket(packet, data);
} }

View file

@ -12,7 +12,7 @@ public:
FDDIAnalyzer(); FDDIAnalyzer();
~FDDIAnalyzer() override = default; ~FDDIAnalyzer() override = default;
AnalyzerResult Analyze(Packet* packet, const uint8_t*& data) override; AnalyzerResult AnalyzePacket(size_t len, const uint8_t* data, Packet* packet) override;
static zeek::packet_analysis::AnalyzerPtr Instantiate() static zeek::packet_analysis::AnalyzerPtr Instantiate()
{ {

View file

@ -10,13 +10,12 @@ IEEE802_11Analyzer::IEEE802_11Analyzer()
{ {
} }
zeek::packet_analysis::AnalyzerResult IEEE802_11Analyzer::Analyze(Packet* packet, const uint8_t*& data) zeek::packet_analysis::AnalyzerResult IEEE802_11Analyzer::AnalyzePacket(size_t len,
const uint8_t* data, Packet* packet)
{ {
auto end_of_data = packet->GetEndOfData();
u_char len_80211 = 24; // minimal length of data frames u_char len_80211 = 24; // minimal length of data frames
if ( data + len_80211 >= end_of_data ) if ( len_80211 >= len )
{ {
packet->Weird("truncated_802_11_header"); packet->Weird("truncated_802_11_header");
return AnalyzerResult::Failed; return AnalyzerResult::Failed;
@ -48,7 +47,7 @@ zeek::packet_analysis::AnalyzerResult IEEE802_11Analyzer::Analyze(Packet* packet
len_80211 += 2; len_80211 += 2;
} }
if ( data + len_80211 >= end_of_data ) if ( len_80211 >= len )
{ {
packet->Weird("truncated_802_11_header"); packet->Weird("truncated_802_11_header");
return AnalyzerResult::Failed; return AnalyzerResult::Failed;
@ -82,7 +81,8 @@ zeek::packet_analysis::AnalyzerResult IEEE802_11Analyzer::Analyze(Packet* packet
// skip 802.11 data header // skip 802.11 data header
data += len_80211; data += len_80211;
if ( data + 8 >= end_of_data ) len_80211 += 8;
if ( len_80211 >= len )
{ {
packet->Weird("truncated_802_11_header"); packet->Weird("truncated_802_11_header");
return AnalyzerResult::Failed; return AnalyzerResult::Failed;
@ -108,5 +108,5 @@ zeek::packet_analysis::AnalyzerResult IEEE802_11Analyzer::Analyze(Packet* packet
uint32_t protocol = (data[0] << 8) + data[1]; uint32_t protocol = (data[0] << 8) + data[1];
data += 2; data += 2;
return AnalyzeInnerPacket(packet, data, protocol); return ForwardPacket(len - len_80211, data, packet, protocol);
} }

View file

@ -12,7 +12,7 @@ public:
IEEE802_11Analyzer(); IEEE802_11Analyzer();
~IEEE802_11Analyzer() override = default; ~IEEE802_11Analyzer() override = default;
AnalyzerResult Analyze(Packet* packet, const uint8_t*& data) override; AnalyzerResult AnalyzePacket(size_t len, const uint8_t* data, Packet* packet) override;
static zeek::packet_analysis::AnalyzerPtr Instantiate() static zeek::packet_analysis::AnalyzerPtr Instantiate()
{ {

View file

@ -12,26 +12,23 @@ IEEE802_11_RadioAnalyzer::IEEE802_11_RadioAnalyzer()
{ {
} }
zeek::packet_analysis::AnalyzerResult IEEE802_11_RadioAnalyzer::Analyze(Packet* packet, const uint8_t*& data) zeek::packet_analysis::AnalyzerResult IEEE802_11_RadioAnalyzer::AnalyzePacket(size_t len,
const uint8_t* data, Packet* packet)
{ {
auto end_of_data = packet->GetEndOfData(); if ( 3 >= len )
if ( data + 3 >= end_of_data )
{ {
packet->Weird("truncated_radiotap_header"); packet->Weird("truncated_radiotap_header");
return AnalyzerResult::Failed; return AnalyzerResult::Failed;
} }
// Skip over the RadioTap header // Skip over the RadioTap header
int rtheader_len = (data[3] << 8) + data[2]; size_t rtheader_len = (data[3] << 8) + data[2];
if ( data + rtheader_len >= end_of_data ) if ( rtheader_len >= len )
{ {
packet->Weird("truncated_radiotap_header"); packet->Weird("truncated_radiotap_header");
return AnalyzerResult::Failed; return AnalyzerResult::Failed;
} }
data += rtheader_len; return ForwardPacket(len - rtheader_len, data + rtheader_len, packet, DLT_IEEE802_11);
return AnalyzeInnerPacket(packet, data, DLT_IEEE802_11);
} }

View file

@ -12,7 +12,7 @@ public:
IEEE802_11_RadioAnalyzer(); IEEE802_11_RadioAnalyzer();
~IEEE802_11_RadioAnalyzer() override = default; ~IEEE802_11_RadioAnalyzer() override = default;
AnalyzerResult Analyze(Packet* packet, const uint8_t*& data) override; AnalyzerResult AnalyzePacket(size_t len, const uint8_t* data, Packet* packet) override;
static zeek::packet_analysis::AnalyzerPtr Instantiate() static zeek::packet_analysis::AnalyzerPtr Instantiate()
{ {

View file

@ -10,10 +10,11 @@ IPAnalyzer::IPAnalyzer()
{ {
} }
zeek::packet_analysis::AnalyzerResult IPAnalyzer::Analyze(Packet* packet, const uint8_t*& data) zeek::packet_analysis::AnalyzerResult IPAnalyzer::AnalyzePacket(size_t len,
const uint8_t* data, Packet* packet)
{ {
// Assume we're pointing at IP. Just figure out which version. // Assume we're pointing at IP. Just figure out which version.
if ( data + sizeof(struct ip) >= packet->GetEndOfData() ) if ( sizeof(struct ip) >= len )
{ {
packet->Weird("packet_analyzer_truncated_header"); packet->Weird("packet_analyzer_truncated_header");
return AnalyzerResult::Failed; return AnalyzerResult::Failed;
@ -23,7 +24,6 @@ zeek::packet_analysis::AnalyzerResult IPAnalyzer::Analyze(Packet* packet, const
uint32_t protocol = ip->ip_v; uint32_t protocol = ip->ip_v;
auto inner_analyzer = Lookup(protocol); auto inner_analyzer = Lookup(protocol);
if ( inner_analyzer == nullptr ) if ( inner_analyzer == nullptr )
{ {
DBG_LOG(DBG_PACKET_ANALYSIS, "Analysis in %s failed, could not find analyzer for identifier %#x.", DBG_LOG(DBG_PACKET_ANALYSIS, "Analysis in %s failed, could not find analyzer for identifier %#x.",
@ -34,5 +34,5 @@ zeek::packet_analysis::AnalyzerResult IPAnalyzer::Analyze(Packet* packet, const
DBG_LOG(DBG_PACKET_ANALYSIS, "Analysis in %s succeeded, next layer identifier is %#x.", DBG_LOG(DBG_PACKET_ANALYSIS, "Analysis in %s succeeded, next layer identifier is %#x.",
GetAnalyzerName(), protocol); GetAnalyzerName(), protocol);
return inner_analyzer->Analyze(packet, data); return inner_analyzer->AnalyzePacket(len, data, packet);
} }

View file

@ -12,7 +12,7 @@ public:
IPAnalyzer(); IPAnalyzer();
~IPAnalyzer() override = default; ~IPAnalyzer() override = default;
AnalyzerResult Analyze(Packet* packet, const uint8_t*& data) override; AnalyzerResult AnalyzePacket(size_t len, const uint8_t* data, Packet* packet) override;
static zeek::packet_analysis::AnalyzerPtr Instantiate() static zeek::packet_analysis::AnalyzerPtr Instantiate()
{ {

View file

@ -9,9 +9,11 @@ IPv4Analyzer::IPv4Analyzer()
{ {
} }
zeek::packet_analysis::AnalyzerResult IPv4Analyzer::Analyze(Packet* packet, const uint8_t*& data) zeek::packet_analysis::AnalyzerResult IPv4Analyzer::AnalyzePacket(size_t len,
const uint8_t* data, Packet* packet)
{ {
packet->l3_proto = L3_IPV4; packet->l3_proto = L3_IPV4;
packet->hdr_size = static_cast<uint32_t>(data - packet->data);
// Leave packet analyzer land // Leave packet analyzer land
return AnalyzerResult::Terminate; return AnalyzerResult::Terminate;

View file

@ -12,7 +12,7 @@ public:
IPv4Analyzer(); IPv4Analyzer();
~IPv4Analyzer() override = default; ~IPv4Analyzer() override = default;
AnalyzerResult Analyze(Packet* packet, const uint8_t*& data) override; AnalyzerResult AnalyzePacket(size_t len, const uint8_t* data, Packet* packet) override;
static zeek::packet_analysis::AnalyzerPtr Instantiate() static zeek::packet_analysis::AnalyzerPtr Instantiate()
{ {

View file

@ -9,9 +9,11 @@ IPv6Analyzer::IPv6Analyzer()
{ {
} }
zeek::packet_analysis::AnalyzerResult IPv6Analyzer::Analyze(Packet* packet, const uint8_t*& data) zeek::packet_analysis::AnalyzerResult IPv6Analyzer::AnalyzePacket(size_t len,
const uint8_t* data, Packet* packet)
{ {
packet->l3_proto = L3_IPV6; packet->l3_proto = L3_IPV6;
packet->hdr_size = static_cast<uint32_t>(data - packet->data);
// Leave packet analyzer land // Leave packet analyzer land
return AnalyzerResult::Terminate; return AnalyzerResult::Terminate;

View file

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

View file

@ -9,9 +9,11 @@ LinuxSLLAnalyzer::LinuxSLLAnalyzer()
{ {
} }
zeek::packet_analysis::AnalyzerResult LinuxSLLAnalyzer::Analyze(Packet* packet, const uint8_t*& data) zeek::packet_analysis::AnalyzerResult LinuxSLLAnalyzer::AnalyzePacket(size_t len,
const uint8_t* data, Packet* packet)
{ {
if ( data + sizeof(SLLHeader) >= packet->GetEndOfData() ) auto len_sll_hdr = sizeof(SLLHeader);
if ( len_sll_hdr >= len )
{ {
packet->Weird("truncated_Linux_SLL_header"); packet->Weird("truncated_Linux_SLL_header");
return AnalyzerResult::Failed; return AnalyzerResult::Failed;
@ -27,6 +29,5 @@ zeek::packet_analysis::AnalyzerResult LinuxSLLAnalyzer::Analyze(Packet* packet,
// here will cause crashes elsewhere. // here will cause crashes elsewhere.
packet->l2_dst = Packet::L2_EMPTY_ADDR; packet->l2_dst = Packet::L2_EMPTY_ADDR;
data += sizeof(SLLHeader); return ForwardPacket(len - len_sll_hdr, data + len_sll_hdr, packet, protocol);
return AnalyzeInnerPacket(packet, data, protocol);
} }

View file

@ -12,7 +12,7 @@ public:
LinuxSLLAnalyzer(); LinuxSLLAnalyzer();
~LinuxSLLAnalyzer() override = default; ~LinuxSLLAnalyzer() override = default;
AnalyzerResult Analyze(Packet* packet, const uint8_t*& data) override; AnalyzerResult AnalyzePacket(size_t len, const uint8_t* data, Packet* packet) override;
static zeek::packet_analysis::AnalyzerPtr Instantiate() static zeek::packet_analysis::AnalyzerPtr Instantiate()
{ {

View file

@ -9,16 +9,15 @@ MPLSAnalyzer::MPLSAnalyzer()
{ {
} }
zeek::packet_analysis::AnalyzerResult MPLSAnalyzer::Analyze(Packet* packet, const uint8_t*& data) zeek::packet_analysis::AnalyzerResult MPLSAnalyzer::AnalyzePacket(size_t len,
const uint8_t* data, Packet* packet)
{ {
auto end_of_data = packet->GetEndOfData();
// Skip the MPLS label stack. // Skip the MPLS label stack.
bool end_of_stack = false; bool end_of_stack = false;
while ( ! end_of_stack ) while ( ! end_of_stack )
{ {
if ( data + 4 >= end_of_data ) if ( 4 >= len )
{ {
packet->Weird("truncated_link_header"); packet->Weird("truncated_link_header");
return AnalyzerResult::Failed; return AnalyzerResult::Failed;
@ -26,11 +25,13 @@ zeek::packet_analysis::AnalyzerResult MPLSAnalyzer::Analyze(Packet* packet, cons
end_of_stack = *(data + 2u) & 0x01; end_of_stack = *(data + 2u) & 0x01;
data += 4; data += 4;
len -= 4;
} }
// According to RFC3032 the encapsulated protocol is not encoded. // According to RFC3032 the encapsulated protocol is not encoded.
// We assume that what remains is IP. // We assume that what remains is IP.
if ( data + sizeof(struct ip) >= end_of_data ) //TODO: Make that configurable
if ( sizeof(struct ip) >= len )
{ {
packet->Weird("no_ip_in_mpls_payload"); packet->Weird("no_ip_in_mpls_payload");
return AnalyzerResult::Failed; return AnalyzerResult::Failed;

View file

@ -12,7 +12,7 @@ public:
MPLSAnalyzer(); MPLSAnalyzer();
~MPLSAnalyzer() override = default; ~MPLSAnalyzer() override = default;
AnalyzerResult Analyze(Packet* packet, const uint8_t*& data) override; AnalyzerResult AnalyzePacket(size_t len, const uint8_t* data, Packet* packet) override;
static zeek::packet_analysis::AnalyzerPtr Instantiate() static zeek::packet_analysis::AnalyzerPtr Instantiate()
{ {

View file

@ -10,8 +10,14 @@ NFLogAnalyzer::NFLogAnalyzer()
{ {
} }
zeek::packet_analysis::AnalyzerResult NFLogAnalyzer::Analyze(Packet* packet, const uint8_t*& data) { zeek::packet_analysis::AnalyzerResult NFLogAnalyzer::AnalyzePacket(size_t len,
auto end_of_data = packet->GetEndOfData(); const uint8_t* data, Packet* packet)
{
if ( 4 >= len )
{
packet->Weird("truncated_nflog_header");
return AnalyzerResult::Failed;
}
// See https://www.tcpdump.org/linktypes/LINKTYPE_NFLOG.html // See https://www.tcpdump.org/linktypes/LINKTYPE_NFLOG.html
uint32_t protocol = data[0]; uint32_t protocol = data[0];
@ -25,13 +31,14 @@ zeek::packet_analysis::AnalyzerResult NFLogAnalyzer::Analyze(Packet* packet, con
// Skip to TLVs. // Skip to TLVs.
data += 4; data += 4;
len -= 4;
uint16_t tlv_len; uint16_t tlv_len;
uint16_t tlv_type; uint16_t tlv_type;
while ( true ) while ( true )
{ {
if ( data + 4 >= end_of_data ) if ( 4 >= len )
{ {
packet->Weird("nflog_no_pcap_payload"); packet->Weird("nflog_no_pcap_payload");
return AnalyzerResult::Failed; return AnalyzerResult::Failed;
@ -49,6 +56,7 @@ zeek::packet_analysis::AnalyzerResult NFLogAnalyzer::Analyze(Packet* packet, con
{ {
// The raw packet payload follows this TLV. // The raw packet payload follows this TLV.
data += 4; data += 4;
len -= 4;
break; break;
} }
else else
@ -72,8 +80,9 @@ zeek::packet_analysis::AnalyzerResult NFLogAnalyzer::Analyze(Packet* packet, con
} }
data += tlv_len; data += tlv_len;
len -= tlv_len;
} }
} }
return AnalyzeInnerPacket(packet, data, protocol); return ForwardPacket(len, data, packet, protocol);
} }

View file

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

View file

@ -10,16 +10,16 @@ NullAnalyzer::NullAnalyzer()
{ {
} }
zeek::packet_analysis::AnalyzerResult NullAnalyzer::Analyze(Packet* packet, const uint8_t*& data) zeek::packet_analysis::AnalyzerResult NullAnalyzer::AnalyzePacket(size_t len,
const uint8_t* data, Packet* packet)
{ {
if ( data + 4 >= packet->GetEndOfData() ) if ( 4 >= len )
{ {
packet->Weird("null_analyzer_failed"); packet->Weird("null_analyzer_failed");
return AnalyzerResult::Failed; return AnalyzerResult::Failed;
} }
uint32_t protocol = (data[3] << 24) + (data[2] << 16) + (data[1] << 8) + data[0]; uint32_t protocol = (data[3] << 24) + (data[2] << 16) + (data[1] << 8) + data[0];
data += 4; // skip link header // skip link header
return ForwardPacket(len - 4, data + 4, packet, protocol);
return AnalyzeInnerPacket(packet, data, protocol);
} }

View file

@ -12,7 +12,7 @@ public:
NullAnalyzer(); NullAnalyzer();
~NullAnalyzer() override = default; ~NullAnalyzer() override = default;
AnalyzerResult Analyze(Packet* packet, const uint8_t*& data) override; AnalyzerResult AnalyzePacket(size_t len, const uint8_t* data, Packet* packet) override;
static zeek::packet_analysis::AnalyzerPtr Instantiate() static zeek::packet_analysis::AnalyzerPtr Instantiate()
{ {

View file

@ -10,11 +10,17 @@ PPPSerialAnalyzer::PPPSerialAnalyzer()
{ {
} }
zeek::packet_analysis::AnalyzerResult PPPSerialAnalyzer::Analyze(Packet* packet, const uint8_t*& data) zeek::packet_analysis::AnalyzerResult PPPSerialAnalyzer::AnalyzePacket(size_t len,
const uint8_t* data, Packet* packet)
{ {
if ( 4 >= len )
{
packet->Weird("truncated_ppp_serial_header");
return AnalyzerResult::Failed;
}
// Extract protocol identifier // Extract protocol identifier
uint32_t protocol = (data[2] << 8) + data[3]; uint32_t protocol = (data[2] << 8) + data[3];
data += 4; // skip link header // skip link header
return ForwardPacket(len - 4, data + 4, packet, protocol);
return AnalyzeInnerPacket(packet, data, protocol);
} }

View file

@ -12,7 +12,7 @@ public:
PPPSerialAnalyzer(); PPPSerialAnalyzer();
~PPPSerialAnalyzer() override = default; ~PPPSerialAnalyzer() override = default;
AnalyzerResult Analyze(Packet* packet, const uint8_t*& data) override; AnalyzerResult AnalyzePacket(size_t len, const uint8_t* data, Packet* packet) override;
static zeek::packet_analysis::AnalyzerPtr Instantiate() static zeek::packet_analysis::AnalyzerPtr Instantiate()
{ {

View file

@ -10,9 +10,10 @@ PPPoEAnalyzer::PPPoEAnalyzer()
{ {
} }
zeek::packet_analysis::AnalyzerResult PPPoEAnalyzer::Analyze(Packet* packet, const uint8_t*& data) zeek::packet_analysis::AnalyzerResult PPPoEAnalyzer::AnalyzePacket(size_t len,
const uint8_t* data, Packet* packet)
{ {
if ( data + 8 >= packet->GetEndOfData() ) if ( 8 >= len )
{ {
packet->Weird("truncated_pppoe_header"); packet->Weird("truncated_pppoe_header");
return AnalyzerResult::Failed; return AnalyzerResult::Failed;
@ -20,7 +21,6 @@ zeek::packet_analysis::AnalyzerResult PPPoEAnalyzer::Analyze(Packet* packet, con
// Extract protocol identifier // Extract protocol identifier
uint32_t protocol = (data[6] << 8u) + data[7]; uint32_t protocol = (data[6] << 8u) + data[7];
data += 8; // Skip the PPPoE session and PPP header // Skip the PPPoE session and PPP header
return ForwardPacket(len - 8, data + 8, packet, protocol);
return AnalyzeInnerPacket(packet, data, protocol);
} }

View file

@ -12,7 +12,7 @@ public:
PPPoEAnalyzer(); PPPoEAnalyzer();
~PPPoEAnalyzer() override = default; ~PPPoEAnalyzer() override = default;
AnalyzerResult Analyze(Packet* packet, const uint8_t*& data) override; AnalyzerResult AnalyzePacket(size_t len, const uint8_t* data, Packet* packet) override;
static zeek::packet_analysis::AnalyzerPtr Instantiate() static zeek::packet_analysis::AnalyzerPtr Instantiate()
{ {

View file

@ -19,8 +19,8 @@ void SkipAnalyzer::Initialize()
skip_bytes = skip_val->AsCount(); skip_bytes = skip_val->AsCount();
} }
zeek::packet_analysis::AnalyzerResult SkipAnalyzer::Analyze(Packet* packet, const uint8_t*& data) zeek::packet_analysis::AnalyzerResult SkipAnalyzer::AnalyzePacket(size_t len,
const uint8_t* data, Packet* packet)
{ {
data += skip_bytes; return ForwardPacket(len - skip_bytes, data + skip_bytes, packet);
return AnalyzeInnerPacket(packet, data);
} }

View file

@ -13,7 +13,7 @@ public:
~SkipAnalyzer() override = default; ~SkipAnalyzer() override = default;
void Initialize() override; void Initialize() override;
AnalyzerResult Analyze(Packet* packet, const uint8_t*& data) override; AnalyzerResult AnalyzePacket(size_t len, const uint8_t* data, Packet* packet) override;
static zeek::packet_analysis::AnalyzerPtr Instantiate() static zeek::packet_analysis::AnalyzerPtr Instantiate()
{ {

View file

@ -10,9 +10,10 @@ VLANAnalyzer::VLANAnalyzer()
{ {
} }
zeek::packet_analysis::AnalyzerResult VLANAnalyzer::Analyze(Packet* packet, const uint8_t*& data) zeek::packet_analysis::AnalyzerResult VLANAnalyzer::AnalyzePacket(size_t len,
const uint8_t* data, Packet* packet)
{ {
if ( data + 4 >= packet->GetEndOfData() ) if ( 4 >= len )
{ {
packet->Weird("truncated_VLAN_header"); packet->Weird("truncated_VLAN_header");
return AnalyzerResult::Failed; return AnalyzerResult::Failed;
@ -23,7 +24,6 @@ zeek::packet_analysis::AnalyzerResult VLANAnalyzer::Analyze(Packet* packet, cons
uint32_t protocol = ((data[2] << 8u) + data[3]); uint32_t protocol = ((data[2] << 8u) + data[3]);
packet->eth_type = protocol; packet->eth_type = protocol;
data += 4; // Skip the VLAN header // Skip the VLAN header
return ForwardPacket(len - 4, data + 4, packet, protocol);
return AnalyzeInnerPacket(packet, data, protocol);
} }

View file

@ -12,7 +12,7 @@ public:
VLANAnalyzer(); VLANAnalyzer();
~VLANAnalyzer() override = default; ~VLANAnalyzer() override = default;
AnalyzerResult Analyze(Packet* packet, const uint8_t*& data) override; AnalyzerResult AnalyzePacket(size_t len, const uint8_t* data, Packet* packet) override;
static zeek::packet_analysis::AnalyzerPtr Instantiate() static zeek::packet_analysis::AnalyzerPtr Instantiate()
{ {

View file

@ -10,12 +10,11 @@ Bar::Bar()
{ {
} }
zeek::packet_analysis::AnalyzerResult Bar::Analyze(Packet* packet, const uint8_t*& data) zeek::packet_analysis::AnalyzerResult Bar::AnalyzePacket(size_t len,
const uint8_t* data, Packet* packet)
{ {
auto end_of_data = packet->GetEndOfData();
// Rudimentary parsing of 802.2 LLC // Rudimentary parsing of 802.2 LLC
if ( data + 17 >= end_of_data ) if ( 17 >= len )
{ {
packet->Weird("truncated_llc_header"); packet->Weird("truncated_llc_header");
return AnalyzerResult::Failed; return AnalyzerResult::Failed;

View file

@ -10,7 +10,7 @@ public:
Bar(); Bar();
~Bar() override = default; ~Bar() override = default;
AnalyzerResult Analyze(Packet* packet, const uint8_t*& data) override; AnalyzerResult AnalyzePacket(size_t len, const uint8_t* data, Packet* packet) override;
static AnalyzerPtr Instantiate() static AnalyzerPtr Instantiate()
{ {