mirror of
https://github.com/zeek/zeek.git
synced 2025-10-04 07:38:19 +00:00
Add method for packet analyzers to register for protocol detection
This commit is contained in:
parent
a7d3cb48ef
commit
d4f57a6100
3 changed files with 99 additions and 18 deletions
|
@ -77,21 +77,34 @@ bool Analyzer::ForwardPacket(size_t len, const uint8_t* data, Packet* packet,
|
||||||
uint32_t identifier) const
|
uint32_t identifier) const
|
||||||
{
|
{
|
||||||
auto inner_analyzer = Lookup(identifier);
|
auto inner_analyzer = Lookup(identifier);
|
||||||
|
if ( ! inner_analyzer )
|
||||||
|
{
|
||||||
|
for ( const auto& child : analyzers_to_detect )
|
||||||
|
{
|
||||||
|
if ( child->DetectProtocol(len, data, packet) )
|
||||||
|
{
|
||||||
|
DBG_LOG(DBG_PACKET_ANALYSIS,
|
||||||
|
"Protocol detection in %s succeeded, next layer analyzer is %s",
|
||||||
|
GetAnalyzerName(), child->GetAnalyzerName());
|
||||||
|
inner_analyzer = child;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if ( ! inner_analyzer )
|
if ( ! inner_analyzer )
|
||||||
inner_analyzer = default_analyzer;
|
inner_analyzer = default_analyzer;
|
||||||
|
|
||||||
if ( inner_analyzer == nullptr )
|
if ( ! inner_analyzer )
|
||||||
{
|
{
|
||||||
|
DBG_LOG(DBG_PACKET_ANALYSIS,
|
||||||
|
"Analysis in %s failed, could not find analyzer for identifier %#x.",
|
||||||
|
GetAnalyzerName(), identifier);
|
||||||
|
|
||||||
if ( report_unknown_protocols )
|
if ( report_unknown_protocols )
|
||||||
{
|
|
||||||
DBG_LOG(DBG_PACKET_ANALYSIS,
|
|
||||||
"Analysis in %s failed, could not find analyzer for identifier %#x.",
|
|
||||||
GetAnalyzerName(), identifier);
|
|
||||||
packet_mgr->ReportUnknownProtocol(GetAnalyzerName(), identifier, data, len);
|
packet_mgr->ReportUnknownProtocol(GetAnalyzerName(), identifier, data, len);
|
||||||
return false;
|
|
||||||
}
|
return false;
|
||||||
else
|
|
||||||
return true;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
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.",
|
||||||
|
@ -101,16 +114,35 @@ bool Analyzer::ForwardPacket(size_t len, const uint8_t* data, Packet* packet,
|
||||||
|
|
||||||
bool Analyzer::ForwardPacket(size_t len, const uint8_t* data, Packet* packet) const
|
bool Analyzer::ForwardPacket(size_t len, const uint8_t* data, Packet* packet) const
|
||||||
{
|
{
|
||||||
if ( default_analyzer )
|
AnalyzerPtr inner_analyzer = nullptr;
|
||||||
return default_analyzer->AnalyzePacket(len, data, packet);
|
|
||||||
|
|
||||||
DBG_LOG(DBG_PACKET_ANALYSIS, "Analysis in %s stopped, no default analyzer available.",
|
for ( const auto& child : analyzers_to_detect )
|
||||||
GetAnalyzerName());
|
{
|
||||||
|
if ( child->DetectProtocol(len, data, packet) )
|
||||||
|
{
|
||||||
|
DBG_LOG(DBG_PACKET_ANALYSIS,
|
||||||
|
"Protocol detection in %s succeeded, next layer analyzer is %s",
|
||||||
|
GetAnalyzerName(), child->GetAnalyzerName());
|
||||||
|
inner_analyzer = child;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if ( report_unknown_protocols )
|
if ( ! inner_analyzer )
|
||||||
Weird("no_suitable_analyzer_found", packet);
|
inner_analyzer = default_analyzer;
|
||||||
|
|
||||||
return true;
|
if ( ! inner_analyzer )
|
||||||
|
{
|
||||||
|
DBG_LOG(DBG_PACKET_ANALYSIS, "Analysis in %s stopped, no default analyzer available.",
|
||||||
|
GetAnalyzerName());
|
||||||
|
|
||||||
|
if ( report_unknown_protocols )
|
||||||
|
Weird("no_suitable_analyzer_found", packet);
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return inner_analyzer->AnalyzePacket(len, data, packet);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Analyzer::DumpDebug() const
|
void Analyzer::DumpDebug() const
|
||||||
|
|
|
@ -1,6 +1,8 @@
|
||||||
// See the file "COPYING" in the main distribution directory for copyright.
|
// See the file "COPYING" in the main distribution directory for copyright.
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
|
#include <set>
|
||||||
|
|
||||||
#include "zeek/Tag.h"
|
#include "zeek/Tag.h"
|
||||||
#include "zeek/iosource/Packet.h"
|
#include "zeek/iosource/Packet.h"
|
||||||
#include "zeek/packet_analysis/Manager.h"
|
#include "zeek/packet_analysis/Manager.h"
|
||||||
|
@ -98,6 +100,32 @@ public:
|
||||||
*/
|
*/
|
||||||
void RegisterProtocol(uint32_t identifier, AnalyzerPtr child);
|
void RegisterProtocol(uint32_t identifier, AnalyzerPtr child);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Registers an analyzer to use for protocol detection if identifier
|
||||||
|
* matching fails. This will also be preferred over the default analyzer
|
||||||
|
* if one exists.
|
||||||
|
*
|
||||||
|
* @param child The analyzer that will be called for protocol detection.
|
||||||
|
*/
|
||||||
|
void RegisterProtocolDetection(AnalyzerPtr child) { analyzers_to_detect.insert(child); }
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Detects whether the protocol for an analyzer can be found in the packet
|
||||||
|
* data. Packet analyzers can overload this method to provide any sort of
|
||||||
|
* pattern-matching or byte-value detection against the packet data to
|
||||||
|
* determine whether the packet contains the analyzer's protocol. The
|
||||||
|
* analyzer must also register for the detection in script-land using the
|
||||||
|
* PacketAnalyzer::register_protocol_detection bif method.
|
||||||
|
*
|
||||||
|
* @param len The number of bytes passed in. As we move along the chain of
|
||||||
|
* analyzers, this is the number of bytes we have left of the packet to
|
||||||
|
* process.
|
||||||
|
* @param data Pointer to the input to process.
|
||||||
|
* @param packet Object that maintains the packet's meta data.
|
||||||
|
* @return true if the protocol is detected in the packet data.
|
||||||
|
*/
|
||||||
|
virtual bool DetectProtocol(size_t len, const uint8_t* data, Packet* packet) { return false; }
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
friend class Manager;
|
friend class Manager;
|
||||||
|
|
||||||
|
@ -174,6 +202,8 @@ private:
|
||||||
*/
|
*/
|
||||||
bool report_unknown_protocols = true;
|
bool report_unknown_protocols = true;
|
||||||
|
|
||||||
|
std::set<AnalyzerPtr> analyzers_to_detect;
|
||||||
|
|
||||||
void Init(const zeek::Tag& tag);
|
void Init(const zeek::Tag& tag);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -28,8 +28,8 @@ function register_packet_analyzer%(parent: PacketAnalyzer::Tag, identifier: coun
|
||||||
return zeek::val_mgr->True();
|
return zeek::val_mgr->True();
|
||||||
%}
|
%}
|
||||||
|
|
||||||
## Attempts to add an entry to `parent`'s dispatcher that maps a protocol/index to a next-stage `child` analyzer.
|
## Attempts to add an entry to `parent`'s dispatcher that maps a protocol/index to a next-stage `child`
|
||||||
## This may fail if either of the two names does not respond to a known analyzer.
|
## analyzer. This may fail if either of the two names does not respond to a known analyzer.
|
||||||
##
|
##
|
||||||
## parent: The parent analyzer being modified
|
## parent: The parent analyzer being modified
|
||||||
## identifier: The identifier for the protocol being registered
|
## identifier: The identifier for the protocol being registered
|
||||||
|
@ -58,3 +58,22 @@ function PacketAnalyzer::__set_ignore_checksums_nets%(v: subnet_set%) : bool
|
||||||
zeek::packet_analysis::IP::IPBasedAnalyzer::SetIgnoreChecksumsNets(zeek::IntrusivePtr{zeek::NewRef{}, v->AsTableVal()});
|
zeek::packet_analysis::IP::IPBasedAnalyzer::SetIgnoreChecksumsNets(zeek::IntrusivePtr{zeek::NewRef{}, v->AsTableVal()});
|
||||||
return zeek::val_mgr->True();
|
return zeek::val_mgr->True();
|
||||||
%}
|
%}
|
||||||
|
|
||||||
|
## Registers a child analyzer with a parent analyzer to perform packet detection when determining whether
|
||||||
|
## to forward from parent to child.
|
||||||
|
##
|
||||||
|
## parent: The parent analyzer being modified
|
||||||
|
## child: The analyzer that will use protocol detection
|
||||||
|
function register_protocol_detection%(parent: PacketAnalyzer::Tag, child: PacketAnalyzer::Tag%): bool
|
||||||
|
%{
|
||||||
|
packet_analysis::AnalyzerPtr parent_analyzer = packet_mgr->GetAnalyzer(parent->AsEnumVal());
|
||||||
|
if ( ! parent_analyzer )
|
||||||
|
return zeek::val_mgr->False();
|
||||||
|
|
||||||
|
packet_analysis::AnalyzerPtr child_analyzer = packet_mgr->GetAnalyzer(child->AsEnumVal());
|
||||||
|
if ( ! child_analyzer )
|
||||||
|
return zeek::val_mgr->False();
|
||||||
|
|
||||||
|
parent_analyzer->RegisterProtocolDetection(child_analyzer);
|
||||||
|
return zeek::val_mgr->True();
|
||||||
|
%}
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue