Reformat Zeek in Spicy style

This largely copies over Spicy's `.clang-format` configuration file. The
one place where we deviate is header include order since Zeek depends on
headers being included in a certain order.
This commit is contained in:
Benjamin Bannier 2023-10-10 21:13:34 +02:00
parent 7b8e7ed72c
commit f5a76c1aed
786 changed files with 131714 additions and 153609 deletions

View file

@ -8,235 +8,194 @@
#include "zeek/session/Manager.h"
#include "zeek/util.h"
namespace zeek::packet_analysis
{
namespace zeek::packet_analysis {
Analyzer::Analyzer(std::string name, bool report_unknown_protocols)
: report_unknown_protocols(report_unknown_protocols)
{
Tag t = packet_mgr->GetComponentTag(name);
: report_unknown_protocols(report_unknown_protocols) {
Tag t = packet_mgr->GetComponentTag(name);
if ( ! t )
reporter->InternalError("unknown packet_analysis name %s", name.c_str());
if ( ! t )
reporter->InternalError("unknown packet_analysis name %s", name.c_str());
Init(t);
}
Init(t);
}
Analyzer::Analyzer(const Tag& tag)
{
Init(tag);
}
Analyzer::Analyzer(const Tag& tag) { Init(tag); }
void Analyzer::Init(const Tag& _tag)
{
tag = _tag;
}
void Analyzer::Init(const Tag& _tag) { tag = _tag; }
void Analyzer::Initialize()
{
default_analyzer = LoadAnalyzer("default_analyzer");
}
void Analyzer::Initialize() { default_analyzer = LoadAnalyzer("default_analyzer"); }
zeek::packet_analysis::AnalyzerPtr Analyzer::LoadAnalyzer(const std::string& name)
{
auto& analyzer = zeek::id::find(GetModuleName() + name);
if ( ! analyzer )
return nullptr;
zeek::packet_analysis::AnalyzerPtr Analyzer::LoadAnalyzer(const std::string& name) {
auto& analyzer = zeek::id::find(GetModuleName() + name);
if ( ! analyzer )
return nullptr;
auto& analyzer_val = analyzer->GetVal();
if ( ! analyzer_val )
return nullptr;
auto& analyzer_val = analyzer->GetVal();
if ( ! analyzer_val )
return nullptr;
return packet_mgr->GetAnalyzer(analyzer_val->AsEnumVal());
}
return packet_mgr->GetAnalyzer(analyzer_val->AsEnumVal());
}
const Tag Analyzer::GetAnalyzerTag() const
{
assert(tag);
return tag;
}
const Tag Analyzer::GetAnalyzerTag() const {
assert(tag);
return tag;
}
const char* Analyzer::GetAnalyzerName() const
{
assert(tag);
return packet_mgr->GetComponentName(tag).c_str();
}
const char* Analyzer::GetAnalyzerName() const {
assert(tag);
return packet_mgr->GetComponentName(tag).c_str();
}
bool Analyzer::IsAnalyzer(const char* name)
{
assert(tag);
return packet_mgr->GetComponentName(tag) == name;
}
bool Analyzer::IsAnalyzer(const char* name) {
assert(tag);
return packet_mgr->GetComponentName(tag) == name;
}
AnalyzerPtr Analyzer::Lookup(uint32_t identifier) const
{
return dispatcher.Lookup(identifier);
}
AnalyzerPtr Analyzer::Lookup(uint32_t identifier) const { return dispatcher.Lookup(identifier); }
bool Analyzer::ForwardPacket(size_t len, const uint8_t* data, Packet* packet,
uint32_t identifier) const
{
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;
}
}
}
bool Analyzer::ForwardPacket(size_t len, const uint8_t* data, Packet* packet, uint32_t identifier) const {
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 )
inner_analyzer = default_analyzer;
if ( ! inner_analyzer )
inner_analyzer = default_analyzer;
if ( ! inner_analyzer )
{
DBG_LOG(DBG_PACKET_ANALYSIS,
"Analysis in %s failed, could not find analyzer for identifier %#x.",
GetAnalyzerName(), identifier);
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 )
packet_mgr->ReportUnknownProtocol(GetAnalyzerName(), identifier, data, len);
if ( report_unknown_protocols )
packet_mgr->ReportUnknownProtocol(GetAnalyzerName(), identifier, data, len);
return false;
}
return false;
}
if ( ! inner_analyzer->IsEnabled() )
{
DBG_LOG(DBG_PACKET_ANALYSIS,
"Analysis in %s found disabled next layer analyzer %s for identifier %#x",
GetAnalyzerName(), inner_analyzer->GetAnalyzerName(), identifier);
return false;
}
if ( ! inner_analyzer->IsEnabled() ) {
DBG_LOG(DBG_PACKET_ANALYSIS, "Analysis in %s found disabled next layer analyzer %s for identifier %#x",
GetAnalyzerName(), inner_analyzer->GetAnalyzerName(), identifier);
return false;
}
DBG_LOG(DBG_PACKET_ANALYSIS, "Analysis in %s succeeded, next layer identifier is %#x.",
GetAnalyzerName(), identifier);
return inner_analyzer->AnalyzePacket(len, data, packet);
}
DBG_LOG(DBG_PACKET_ANALYSIS, "Analysis in %s succeeded, next layer identifier is %#x.", GetAnalyzerName(),
identifier);
return inner_analyzer->AnalyzePacket(len, data, packet);
}
bool Analyzer::ForwardPacket(size_t len, const uint8_t* data, Packet* packet) const
{
AnalyzerPtr inner_analyzer = nullptr;
bool Analyzer::ForwardPacket(size_t len, const uint8_t* data, Packet* packet) const {
AnalyzerPtr inner_analyzer = nullptr;
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;
}
}
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 )
inner_analyzer = default_analyzer;
if ( ! inner_analyzer )
inner_analyzer = default_analyzer;
if ( ! inner_analyzer )
{
DBG_LOG(DBG_PACKET_ANALYSIS, "Analysis in %s stopped, no default analyzer available.",
GetAnalyzerName());
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);
if ( report_unknown_protocols )
Weird("no_suitable_analyzer_found", packet);
return false;
}
return false;
}
return inner_analyzer->AnalyzePacket(len, data, packet);
}
return inner_analyzer->AnalyzePacket(len, data, packet);
}
void Analyzer::DumpDebug() const
{
void Analyzer::DumpDebug() const {
#ifdef DEBUG
DBG_LOG(DBG_PACKET_ANALYSIS, "Dispatcher for %s", this->GetAnalyzerName());
dispatcher.DumpDebug();
DBG_LOG(DBG_PACKET_ANALYSIS, "Dispatcher for %s", this->GetAnalyzerName());
dispatcher.DumpDebug();
#endif
}
}
void Analyzer::RegisterProtocol(uint32_t identifier, AnalyzerPtr child)
{
if ( run_state::detail::zeek_init_done )
reporter->FatalError("Packet protocols cannot be registered after zeek_init has finished.");
void Analyzer::RegisterProtocol(uint32_t identifier, AnalyzerPtr child) {
if ( run_state::detail::zeek_init_done )
reporter->FatalError("Packet protocols cannot be registered after zeek_init has finished.");
dispatcher.Register(identifier, std::move(child));
}
dispatcher.Register(identifier, std::move(child));
}
void Analyzer::Weird(const char* name, Packet* packet, const char* addl) const
{
session_mgr->Weird(name, packet, addl, GetAnalyzerName());
}
void Analyzer::Weird(const char* name, Packet* packet, const char* addl) const {
session_mgr->Weird(name, packet, addl, GetAnalyzerName());
}
void Analyzer::EnqueueAnalyzerConfirmationInfo(session::Session* session, const zeek::Tag& arg_tag)
{
static auto info_type = zeek::id::find_type<RecordType>("AnalyzerConfirmationInfo");
static auto info_c_idx = info_type->FieldOffset("c");
void Analyzer::EnqueueAnalyzerConfirmationInfo(session::Session* session, const zeek::Tag& arg_tag) {
static auto info_type = zeek::id::find_type<RecordType>("AnalyzerConfirmationInfo");
static auto info_c_idx = info_type->FieldOffset("c");
auto info = make_intrusive<RecordVal>(info_type);
info->Assign(info_c_idx, session->GetVal());
auto info = make_intrusive<RecordVal>(info_type);
info->Assign(info_c_idx, session->GetVal());
event_mgr.Enqueue(analyzer_confirmation_info, arg_tag.AsVal(), info);
}
event_mgr.Enqueue(analyzer_confirmation_info, arg_tag.AsVal(), info);
}
void Analyzer::AnalyzerConfirmation(session::Session* session, zeek::Tag arg_tag)
{
const auto& effective_tag = arg_tag ? arg_tag : GetAnalyzerTag();
void Analyzer::AnalyzerConfirmation(session::Session* session, zeek::Tag arg_tag) {
const auto& effective_tag = arg_tag ? arg_tag : GetAnalyzerTag();
if ( ! session )
return;
if ( ! session )
return;
if ( session->AnalyzerState(effective_tag) == session::AnalyzerConfirmationState::CONFIRMED )
return;
if ( session->AnalyzerState(effective_tag) == session::AnalyzerConfirmationState::CONFIRMED )
return;
// If this session violated previously, we don't allow through a confirmation.
if ( session->AnalyzerState(effective_tag) == session::AnalyzerConfirmationState::VIOLATED )
return;
// If this session violated previously, we don't allow through a confirmation.
if ( session->AnalyzerState(effective_tag) == session::AnalyzerConfirmationState::VIOLATED )
return;
session->SetAnalyzerState(effective_tag, session::AnalyzerConfirmationState::CONFIRMED);
session->SetAnalyzerState(effective_tag, session::AnalyzerConfirmationState::CONFIRMED);
if ( analyzer_confirmation_info )
EnqueueAnalyzerConfirmationInfo(session, effective_tag);
}
if ( analyzer_confirmation_info )
EnqueueAnalyzerConfirmationInfo(session, effective_tag);
}
void Analyzer::EnqueueAnalyzerViolationInfo(session::Session* session, const char* reason,
const char* data, int len, const zeek::Tag& arg_tag)
{
static auto info_type = zeek::id::find_type<RecordType>("AnalyzerViolationInfo");
static auto info_reason_idx = info_type->FieldOffset("reason");
static auto info_c_idx = info_type->FieldOffset("c");
static auto info_data_idx = info_type->FieldOffset("data");
void Analyzer::EnqueueAnalyzerViolationInfo(session::Session* session, const char* reason, const char* data, int len,
const zeek::Tag& arg_tag) {
static auto info_type = zeek::id::find_type<RecordType>("AnalyzerViolationInfo");
static auto info_reason_idx = info_type->FieldOffset("reason");
static auto info_c_idx = info_type->FieldOffset("c");
static auto info_data_idx = info_type->FieldOffset("data");
auto info = zeek::make_intrusive<RecordVal>(info_type);
info->Assign(info_reason_idx, make_intrusive<StringVal>(reason));
info->Assign(info_c_idx, session->GetVal());
if ( data && len )
info->Assign(info_data_idx, make_intrusive<StringVal>(len, data));
auto info = zeek::make_intrusive<RecordVal>(info_type);
info->Assign(info_reason_idx, make_intrusive<StringVal>(reason));
info->Assign(info_c_idx, session->GetVal());
if ( data && len )
info->Assign(info_data_idx, make_intrusive<StringVal>(len, data));
event_mgr.Enqueue(analyzer_violation_info, arg_tag.AsVal(), info);
}
event_mgr.Enqueue(analyzer_violation_info, arg_tag.AsVal(), info);
}
void Analyzer::AnalyzerViolation(const char* reason, session::Session* session, const char* data,
int len, zeek::Tag arg_tag)
{
const auto& effective_tag = arg_tag ? arg_tag : GetAnalyzerTag();
void Analyzer::AnalyzerViolation(const char* reason, session::Session* session, const char* data, int len,
zeek::Tag arg_tag) {
const auto& effective_tag = arg_tag ? arg_tag : GetAnalyzerTag();
if ( ! session )
return;
if ( ! session )
return;
if ( session->AnalyzerState(effective_tag) == session::AnalyzerConfirmationState::VIOLATED )
return;
if ( session->AnalyzerState(effective_tag) == session::AnalyzerConfirmationState::VIOLATED )
return;
session->SetAnalyzerState(effective_tag, session::AnalyzerConfirmationState::VIOLATED);
session->SetAnalyzerState(effective_tag, session::AnalyzerConfirmationState::VIOLATED);
if ( analyzer_violation_info )
EnqueueAnalyzerViolationInfo(session, reason, data, len, effective_tag);
}
if ( analyzer_violation_info )
EnqueueAnalyzerViolationInfo(session, reason, data, len, effective_tag);
}
} // namespace zeek::packet_analysis
} // namespace zeek::packet_analysis

View file

@ -8,279 +8,269 @@
#include "zeek/packet_analysis/Manager.h"
#include "zeek/session/Session.h"
namespace zeek::packet_analysis
{
namespace zeek::packet_analysis {
/**
* Main packet analyzer interface.
*/
class Analyzer
{
class Analyzer {
public:
/**
* Constructor.
*
* @param name The name for the type of analyzer. The name must match
* the one the corresponding Component registers.
* @param report_unknown_protocols Flag for whether to report unknown
* protocols during packet forwarding. This should generally always be
* set to true.
*/
explicit Analyzer(std::string name, bool report_unknown_protocols = true);
/**
* Constructor.
*
* @param name The name for the type of analyzer. The name must match
* the one the corresponding Component registers.
* @param report_unknown_protocols Flag for whether to report unknown
* protocols during packet forwarding. This should generally always be
* set to true.
*/
explicit Analyzer(std::string name, bool report_unknown_protocols = true);
/**
* Constructor.
*
* @param tag The tag for the type of analyzer. The tag must map to
* the name the corresponding Component registers.
*/
explicit Analyzer(const zeek::Tag& tag);
/**
* Constructor.
*
* @param tag The tag for the type of analyzer. The tag must map to
* the name the corresponding Component registers.
*/
explicit Analyzer(const zeek::Tag& tag);
/**
* Destructor.
*/
virtual ~Analyzer() = default;
/**
* Destructor.
*/
virtual ~Analyzer() = default;
/**
* Initialize the analyzer. This method is called after the configuration
* was read. Derived classes can override this method to implement custom
* initialization.
* When overriding this methods, always make sure to call the base-class
* version to ensure proper initialization.
*/
virtual void Initialize();
/**
* Initialize the analyzer. This method is called after the configuration
* was read. Derived classes can override this method to implement custom
* initialization.
* When overriding this methods, always make sure to call the base-class
* version to ensure proper initialization.
*/
virtual void Initialize();
/**
* Returns the tag associated with the analyzer's type.
*/
const zeek::Tag GetAnalyzerTag() const;
/**
* Returns the tag associated with the analyzer's type.
*/
const zeek::Tag GetAnalyzerTag() const;
/**
* Returns a textual description of the analyzer's type. This is
* what's passed to the constructor and usually corresponds to the
* protocol name, e.g., "ARP".
*/
const char* GetAnalyzerName() const;
/**
* Returns a textual description of the analyzer's type. This is
* what's passed to the constructor and usually corresponds to the
* protocol name, e.g., "ARP".
*/
const char* GetAnalyzerName() const;
/**
* Returns true if this analyzer's type matches the name passes in.
* This is shortcut for comparing GetAnalyzerName() with the given
* name.
*
* @param name The name to check.
*/
bool IsAnalyzer(const char* name);
/**
* Returns true if this analyzer's type matches the name passes in.
* This is shortcut for comparing GetAnalyzerName() with the given
* name.
*
* @param name The name to check.
*/
bool IsAnalyzer(const char* name);
/**
* Return whether this analyzer is enabled or not.
*
* @return true if the analyzer is enabled, else false.
*/
bool IsEnabled() const { return enabled; }
/**
* Return whether this analyzer is enabled or not.
*
* @return true if the analyzer is enabled, else false.
*/
bool IsEnabled() const { return enabled; }
/**
* Analyzes the given packet. A common case is that the analyzed protocol
* encapsulates another protocol, which can be determined by an identifier
* in the header. In this case, derived classes may use ForwardPacket() to
* forward the payload to the corresponding analyzer.
*
* @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 false if the analysis failed, else true.
*/
virtual bool AnalyzePacket(size_t len, const uint8_t* data, Packet* packet) = 0;
/**
* Analyzes the given packet. A common case is that the analyzed protocol
* encapsulates another protocol, which can be determined by an identifier
* in the header. In this case, derived classes may use ForwardPacket() to
* forward the payload to the corresponding analyzer.
*
* @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 false if the analysis failed, else true.
*/
virtual bool AnalyzePacket(size_t len, const uint8_t* data, Packet* packet) = 0;
/**
* Dumps out debug information to the \c analyzer debug stream.
*/
void DumpDebug() const;
/**
* Dumps out debug information to the \c analyzer debug stream.
*/
void DumpDebug() const;
/**
* Adds a protocol to this analyzer's dispatcher.
*
* @param identifier The identifier for the protocol being added.
* @param child The analyzer that will be called for the new protocol during
* forwarding.
*/
void RegisterProtocol(uint32_t identifier, AnalyzerPtr child);
/**
* Adds a protocol to this analyzer's dispatcher.
*
* @param identifier The identifier for the protocol being added.
* @param child The analyzer that will be called for the new protocol during
* forwarding.
*/
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); }
/**
* 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; }
/**
* 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; }
/**
* Signals Zeek's protocol detection that the analyzer has recognized
* the input to indeed conform to the expected protocol. This should
* be called as early as possible during a connection's life-time. It
* may turn into \c analyzer_confirmation_info event at the script-layer (but
* only once per analyzer for each connection, even if the method is
* called multiple times).
*
* If tag is given, it overrides the analyzer tag passed to the
* scripting layer; the default is the one of the analyzer itself.
*/
virtual void AnalyzerConfirmation(session::Session* session, zeek::Tag tag = zeek::Tag());
/**
* Signals Zeek's protocol detection that the analyzer has recognized
* the input to indeed conform to the expected protocol. This should
* be called as early as possible during a connection's life-time. It
* may turn into \c analyzer_confirmation_info event at the script-layer (but
* only once per analyzer for each connection, even if the method is
* called multiple times).
*
* If tag is given, it overrides the analyzer tag passed to the
* scripting layer; the default is the one of the analyzer itself.
*/
virtual void AnalyzerConfirmation(session::Session* session, zeek::Tag tag = zeek::Tag());
/**
* Signals Zeek's protocol detection that the analyzer has found a
* severe protocol violation that could indicate that it's not
* parsing the expected protocol. This turns into \c
* analyzer_violation_info events at the script-layer (one such event is
* raised for each call to this method so that the script-layer can
* built up a notion of how prevalent protocol violations are; the
* more, the less likely it's the right protocol).
*
* @param reason A textual description of the error encountered.
*
* @param data An optional pointer to the malformed data.
*
* @param len If \a data is given, the length of it.
*/
virtual void AnalyzerViolation(const char* reason, session::Session* session,
const char* data = nullptr, int len = 0,
zeek::Tag tag = zeek::Tag());
/**
* Signals Zeek's protocol detection that the analyzer has found a
* severe protocol violation that could indicate that it's not
* parsing the expected protocol. This turns into \c
* analyzer_violation_info events at the script-layer (one such event is
* raised for each call to this method so that the script-layer can
* built up a notion of how prevalent protocol violations are; the
* more, the less likely it's the right protocol).
*
* @param reason A textual description of the error encountered.
*
* @param data An optional pointer to the malformed data.
*
* @param len If \a data is given, the length of it.
*/
virtual void AnalyzerViolation(const char* reason, session::Session* session, const char* data = nullptr,
int len = 0, zeek::Tag tag = zeek::Tag());
/**
* Returns true if ProtocolConfirmation() has been called at least
* once.
*/
bool AnalyzerConfirmed(session::Session* session) const
{
return session->AnalyzerState(GetAnalyzerTag()) ==
session::AnalyzerConfirmationState::CONFIRMED;
}
bool AnalyzerViolated(session::Session* session) const
{
return session->AnalyzerState(GetAnalyzerTag()) ==
session::AnalyzerConfirmationState::VIOLATED;
}
/**
* Returns true if ProtocolConfirmation() has been called at least
* once.
*/
bool AnalyzerConfirmed(session::Session* session) const {
return session->AnalyzerState(GetAnalyzerTag()) == session::AnalyzerConfirmationState::CONFIRMED;
}
bool AnalyzerViolated(session::Session* session) const {
return session->AnalyzerState(GetAnalyzerTag()) == session::AnalyzerConfirmationState::VIOLATED;
}
/**
* Reports a Weird with the analyzer's name included in the addl field.
*
* @param name The name of the weird.
* @param packet An optional pointer to a packet to be used for additional
* information in the weird output.
* @param addl An optional string containing additional information about
* the weird. If this is passed, the analyzer's name will be prepended to
* it before output.
*/
void Weird(const char* name, Packet* packet = nullptr, const char* addl = "") const;
/**
* Reports a Weird with the analyzer's name included in the addl field.
*
* @param name The name of the weird.
* @param packet An optional pointer to a packet to be used for additional
* information in the weird output.
* @param addl An optional string containing additional information about
* the weird. If this is passed, the analyzer's name will be prepended to
* it before output.
*/
void Weird(const char* name, Packet* packet = nullptr, const char* addl = "") const;
protected:
friend class Component;
friend class Manager;
friend class Component;
friend class Manager;
/**
* Looks up the analyzer for the encapsulated protocol based on the given
* identifier.
*
* @param identifier Identifier for the encapsulated protocol.
* @return The analyzer registered for the given identifier. Returns a
* nullptr if no analyzer is registered.
*/
AnalyzerPtr Lookup(uint32_t identifier) const;
/**
* Looks up the analyzer for the encapsulated protocol based on the given
* identifier.
*
* @param identifier Identifier for the encapsulated protocol.
* @return The analyzer registered for the given identifier. Returns a
* nullptr if no analyzer is registered.
*/
AnalyzerPtr Lookup(uint32_t identifier) const;
/**
* Returns an analyzer based on a script-land definition.
*
* @param name The script-land identifier for a PacketAnalyzer::Tag value.
* @return The defined analyzer if available, else nullptr.
*/
AnalyzerPtr LoadAnalyzer(const std::string& name);
/**
* Returns an analyzer based on a script-land definition.
*
* @param name The script-land identifier for a PacketAnalyzer::Tag value.
* @return The defined analyzer if available, else nullptr.
*/
AnalyzerPtr LoadAnalyzer(const std::string& name);
/**
* Enable or disable this analyzer. This is meant for internal use by
* manager and component.
*
* @param value The new enabled value.
*/
void SetEnabled(bool value) { enabled = value; }
/**
* Enable or disable this analyzer. This is meant for internal use by
* manager and component.
*
* @param value The new enabled value.
*/
void SetEnabled(bool value) { enabled = value; }
/**
* Returns the module name corresponding to the analyzer, i.e. its script-land
* namespace. Configuration values for the analyzer are expected in this module.
* @return Analyzer's module name.
*/
std::string GetModuleName() const
{
return util::fmt("PacketAnalyzer::%s::", GetAnalyzerName());
};
/**
* Returns the module name corresponding to the analyzer, i.e. its script-land
* namespace. Configuration values for the analyzer are expected in this module.
* @return Analyzer's module name.
*/
std::string GetModuleName() const { return util::fmt("PacketAnalyzer::%s::", GetAnalyzerName()); };
/**
* Triggers analysis of the encapsulated packet. The encapsulated protocol
* is determined using the given identifier.
*
* @param len The length of the data left to analyze.
* @param data Pointer to the payload in the raw packet left to analyze.
* @param packet The packet to analyze.
* @param identifier The identifier of the encapsulated protocol.
*
* @return false if the analysis failed, else true.
*/
bool ForwardPacket(size_t len, const uint8_t* data, Packet* packet, uint32_t identifier) const;
/**
* Triggers analysis of the encapsulated packet. The encapsulated protocol
* is determined using the given identifier.
*
* @param len The length of the data left to analyze.
* @param data Pointer to the payload in the raw packet left to analyze.
* @param packet The packet to analyze.
* @param identifier The identifier of the encapsulated protocol.
*
* @return false if the analysis failed, else true.
*/
bool ForwardPacket(size_t len, const uint8_t* data, Packet* packet, uint32_t identifier) const;
/**
* Triggers default analysis of the encapsulated packet if the default analyzer
* is set.
*
* @param len The length of the data left to analyze.
* @param data Pointer to the payload in the raw packet left to analyze.
* @param packet The packet to analyze.
*
* @return false if the analysis failed, else true.
*/
bool ForwardPacket(size_t len, const uint8_t* data, Packet* packet) const;
/**
* Triggers default analysis of the encapsulated packet if the default analyzer
* is set.
*
* @param len The length of the data left to analyze.
* @param data Pointer to the payload in the raw packet left to analyze.
* @param packet The packet to analyze.
*
* @return false if the analysis failed, else true.
*/
bool ForwardPacket(size_t len, const uint8_t* data, Packet* packet) const;
private:
// Internal helper to raise analyzer_confirmation events
void EnqueueAnalyzerConfirmationInfo(session::Session* session, const zeek::Tag& arg_tag);
// Internal helper to raise analyzer_confirmation events
void EnqueueAnalyzerConfirmationInfo(session::Session* session, const zeek::Tag& arg_tag);
// Internal helper to raise analyzer_violation_info
void EnqueueAnalyzerViolationInfo(session::Session* session, const char* reason,
const char* data, int len, const zeek::Tag& arg_tag);
// Internal helper to raise analyzer_violation_info
void EnqueueAnalyzerViolationInfo(session::Session* session, const char* reason, const char* data, int len,
const zeek::Tag& arg_tag);
zeek::Tag tag;
Dispatcher dispatcher;
AnalyzerPtr default_analyzer = nullptr;
bool enabled = true;
zeek::Tag tag;
Dispatcher dispatcher;
AnalyzerPtr default_analyzer = nullptr;
bool enabled = true;
/**
* Flag for whether to report unknown protocols in ForwardPacket.
*/
bool report_unknown_protocols = true;
/**
* Flag for whether to report unknown protocols in ForwardPacket.
*/
bool report_unknown_protocols = true;
std::set<AnalyzerPtr> analyzers_to_detect;
std::set<AnalyzerPtr> analyzers_to_detect;
void Init(const zeek::Tag& tag);
};
void Init(const zeek::Tag& tag);
};
using AnalyzerPtr = std::shared_ptr<Analyzer>;
}
} // namespace zeek::packet_analysis

View file

@ -8,37 +8,30 @@
using namespace zeek::packet_analysis;
Component::Component(const std::string& name, factory_callback arg_factory,
Tag::subtype_t arg_subtype)
: plugin::Component(plugin::component::PACKET_ANALYZER, name, arg_subtype,
packet_mgr->GetTagType())
{
factory = arg_factory;
}
Component::Component(const std::string& name, factory_callback arg_factory, Tag::subtype_t arg_subtype)
: plugin::Component(plugin::component::PACKET_ANALYZER, name, arg_subtype, packet_mgr->GetTagType()) {
factory = arg_factory;
}
void Component::Initialize()
{
InitializeTag();
packet_mgr->RegisterComponent(this, "ANALYZER_");
}
void Component::Initialize() {
InitializeTag();
packet_mgr->RegisterComponent(this, "ANALYZER_");
}
void Component::SetEnabled(bool arg_enabled)
{
enabled = arg_enabled;
void Component::SetEnabled(bool arg_enabled) {
enabled = arg_enabled;
// If we already have instantiated an analyzer, update its state.
if ( auto analyzer = packet_mgr->GetAnalyzer(Tag().AsVal().get()) )
analyzer->SetEnabled(enabled);
}
// If we already have instantiated an analyzer, update its state.
if ( auto analyzer = packet_mgr->GetAnalyzer(Tag().AsVal().get()) )
analyzer->SetEnabled(enabled);
}
void Component::DoDescribe(ODesc* d) const
{
if ( factory )
{
d->Add("ANALYZER_");
d->Add(CanonicalName());
d->Add(", ");
}
void Component::DoDescribe(ODesc* d) const {
if ( factory ) {
d->Add("ANALYZER_");
d->Add(CanonicalName());
d->Add(", ");
}
d->Add(enabled ? "enabled" : "disabled");
}
d->Add(enabled ? "enabled" : "disabled");
}

View file

@ -10,55 +10,53 @@
#include "zeek/plugin/Component.h"
#include "zeek/util.h"
namespace zeek::packet_analysis
{
namespace zeek::packet_analysis {
class Analyzer;
using AnalyzerPtr = std::shared_ptr<Analyzer>;
class Component : public plugin::Component
{
class Component : public plugin::Component {
public:
using factory_callback = std::function<AnalyzerPtr()>;
using factory_callback = std::function<AnalyzerPtr()>;
Component(const std::string& name, factory_callback factory, zeek::Tag::subtype_t subtype = 0);
~Component() override = default;
Component(const std::string& name, factory_callback factory, zeek::Tag::subtype_t subtype = 0);
~Component() override = default;
/**
* Initialization function. This function has to be called before any
* plugin component functionality is used; it is used to add the
* plugin component to the list of components and to initialize tags
*/
void Initialize() override;
/**
* Initialization function. This function has to be called before any
* plugin component functionality is used; it is used to add the
* plugin component to the list of components and to initialize tags
*/
void Initialize() override;
/**
* Returns the analyzer's factory function.
*/
factory_callback Factory() const { return factory; }
/**
* Returns the analyzer's factory function.
*/
factory_callback Factory() const { return factory; }
/**
* Returns true if the analyzer is currently enabled and hence
* available for use.
*/
bool Enabled() const { return enabled; }
/**
* Returns true if the analyzer is currently enabled and hence
* available for use.
*/
bool Enabled() const { return enabled; }
/**
* Enables or disables this analyzer.
*
* @param arg_enabled True to enabled, false to disable.
*
*/
void SetEnabled(bool arg_enabled);
/**
* Enables or disables this analyzer.
*
* @param arg_enabled True to enabled, false to disable.
*
*/
void SetEnabled(bool arg_enabled);
protected:
/**
* Overridden from plugin::Component.
*/
void DoDescribe(ODesc* d) const override;
/**
* Overridden from plugin::Component.
*/
void DoDescribe(ODesc* d) const override;
private:
factory_callback factory; // The analyzer's factory callback.
bool enabled = true; // True if the analyzer is enabled.
};
factory_callback factory; // The analyzer's factory callback.
bool enabled = true; // True if the analyzer is enabled.
};
}
} // namespace zeek::packet_analysis

View file

@ -8,99 +8,76 @@
#include "zeek/Reporter.h"
#include "zeek/packet_analysis/Analyzer.h"
namespace zeek::packet_analysis
{
namespace zeek::packet_analysis {
Dispatcher::~Dispatcher()
{
FreeValues();
}
Dispatcher::~Dispatcher() { FreeValues(); }
void Dispatcher::Register(uint32_t identifier, AnalyzerPtr analyzer)
{
// If the table has size 1 and the entry is nullptr, there was nothing added yet. Just add it.
if ( table.size() == 1 && table[0] == nullptr )
{
table[0] = std::move(analyzer);
lowest_identifier = identifier;
return;
}
void Dispatcher::Register(uint32_t identifier, AnalyzerPtr analyzer) {
// If the table has size 1 and the entry is nullptr, there was nothing added yet. Just add it.
if ( table.size() == 1 && table[0] == nullptr ) {
table[0] = std::move(analyzer);
lowest_identifier = identifier;
return;
}
// If highestIdentifier == identifier, overwrite would happen -> no check needed, will return
// false
if ( GetHighestIdentifier() < identifier )
{
table.resize(table.size() + (identifier - GetHighestIdentifier()), nullptr);
}
else if ( identifier < lowest_identifier )
{
// Lower than the lowest registered identifier. Shift up by lowerBound - identifier
uint32_t distance = lowest_identifier - identifier;
table.resize(table.size() + distance, nullptr);
// If highestIdentifier == identifier, overwrite would happen -> no check needed, will return
// false
if ( GetHighestIdentifier() < identifier ) {
table.resize(table.size() + (identifier - GetHighestIdentifier()), nullptr);
}
else if ( identifier < lowest_identifier ) {
// Lower than the lowest registered identifier. Shift up by lowerBound - identifier
uint32_t distance = lowest_identifier - identifier;
table.resize(table.size() + distance, nullptr);
// Shift values
for ( ssize_t i = table.size() - 1; i >= 0; i-- )
{
if ( table[i] != nullptr )
{
table.at(i + distance) = std::move(table.at(i));
table.at(i) = nullptr;
}
}
// Shift values
for ( ssize_t i = table.size() - 1; i >= 0; i-- ) {
if ( table[i] != nullptr ) {
table.at(i + distance) = std::move(table.at(i));
table.at(i) = nullptr;
}
}
lowest_identifier = identifier;
}
lowest_identifier = identifier;
}
int64_t index = identifier - lowest_identifier;
if ( table[index] != nullptr )
reporter->Info("Overwriting packet analyzer mapping %#8" PRIx64 " => %s with %s",
index + lowest_identifier, table[index]->GetAnalyzerName(),
analyzer->GetAnalyzerName());
table[index] = std::move(analyzer);
}
int64_t index = identifier - lowest_identifier;
if ( table[index] != nullptr )
reporter->Info("Overwriting packet analyzer mapping %#8" PRIx64 " => %s with %s", index + lowest_identifier,
table[index]->GetAnalyzerName(), analyzer->GetAnalyzerName());
table[index] = std::move(analyzer);
}
AnalyzerPtr Dispatcher::Lookup(uint32_t identifier) const
{
int64_t index = identifier - lowest_identifier;
if ( index >= 0 && index < static_cast<int64_t>(table.size()) && table[index] != nullptr )
return table[index];
AnalyzerPtr Dispatcher::Lookup(uint32_t identifier) const {
int64_t index = identifier - lowest_identifier;
if ( index >= 0 && index < static_cast<int64_t>(table.size()) && table[index] != nullptr )
return table[index];
return nullptr;
}
return nullptr;
}
size_t Dispatcher::Count() const
{
return std::count_if(table.begin(), table.end(),
[](AnalyzerPtr a)
{
return a != nullptr;
});
}
size_t Dispatcher::Count() const {
return std::count_if(table.begin(), table.end(), [](AnalyzerPtr a) { return a != nullptr; });
}
void Dispatcher::Clear()
{
FreeValues();
table.clear();
}
void Dispatcher::Clear() {
FreeValues();
table.clear();
}
void Dispatcher::FreeValues()
{
for ( auto& current : table )
current = nullptr;
}
void Dispatcher::FreeValues() {
for ( auto& current : table )
current = nullptr;
}
void Dispatcher::DumpDebug() const
{
void Dispatcher::DumpDebug() const {
#ifdef DEBUG
DBG_LOG(DBG_PACKET_ANALYSIS, "Dispatcher elements (used/total): %lu/%lu", Count(),
table.size());
for ( size_t i = 0; i < table.size(); i++ )
{
if ( table[i] != nullptr )
DBG_LOG(DBG_PACKET_ANALYSIS, "%#8lx => %s", i + lowest_identifier,
table[i]->GetAnalyzerName());
}
DBG_LOG(DBG_PACKET_ANALYSIS, "Dispatcher elements (used/total): %lu/%lu", Count(), table.size());
for ( size_t i = 0; i < table.size(); i++ ) {
if ( table[i] != nullptr )
DBG_LOG(DBG_PACKET_ANALYSIS, "%#8lx => %s", i + lowest_identifier, table[i]->GetAnalyzerName());
}
#endif
}
}
}
} // namespace zeek::packet_analysis

View file

@ -7,8 +7,7 @@
#include <memory>
#include <vector>
namespace zeek::packet_analysis
{
namespace zeek::packet_analysis {
class Analyzer; // Forward declaration for Value
using AnalyzerPtr = std::shared_ptr<zeek::packet_analysis::Analyzer>;
@ -16,52 +15,51 @@ using AnalyzerPtr = std::shared_ptr<zeek::packet_analysis::Analyzer>;
/**
* The Dispatcher class manages identifier-to-analyzer mappings.
*/
class Dispatcher
{
class Dispatcher {
public:
Dispatcher() : table(std::vector<AnalyzerPtr>(1, nullptr)){};
~Dispatcher();
Dispatcher() : table(std::vector<AnalyzerPtr>(1, nullptr)){};
~Dispatcher();
/**
* Register an analyzer for a given identifier.
*
* @param identifier The identifier.
* @param analyzer The analyzer to register.
*/
void Register(uint32_t identifier, AnalyzerPtr analyzer);
/**
* Register an analyzer for a given identifier.
*
* @param identifier The identifier.
* @param analyzer The analyzer to register.
*/
void Register(uint32_t identifier, AnalyzerPtr analyzer);
/**
* Looks up the analyzer for an identifier.
*
* @param identifier The identifier to look up.
* @return The analyzer registered for the given identifier. Returns a
* nullptr if no analyzer is registered.
*/
AnalyzerPtr Lookup(uint32_t identifier) const;
/**
* Looks up the analyzer for an identifier.
*
* @param identifier The identifier to look up.
* @return The analyzer registered for the given identifier. Returns a
* nullptr if no analyzer is registered.
*/
AnalyzerPtr Lookup(uint32_t identifier) const;
/**
* Returns the number of registered analyzers.
* @return Number of registered analyzers.
*/
size_t Count() const;
/**
* Returns the number of registered analyzers.
* @return Number of registered analyzers.
*/
size_t Count() const;
/**
* Removes all mappings from the dispatcher.
*/
void Clear();
/**
* Removes all mappings from the dispatcher.
*/
void Clear();
/**
* Dumps out the data structure to the \c analyzer debug stream.
*/
void DumpDebug() const;
/**
* Dumps out the data structure to the \c analyzer debug stream.
*/
void DumpDebug() const;
private:
uint32_t lowest_identifier = 0;
std::vector<AnalyzerPtr> table;
uint32_t lowest_identifier = 0;
std::vector<AnalyzerPtr> table;
void FreeValues();
void FreeValues();
inline uint32_t GetHighestIdentifier() const { return lowest_identifier + table.size() - 1; }
};
inline uint32_t GetHighestIdentifier() const { return lowest_identifier + table.size() - 1; }
};
}
} // namespace zeek::packet_analysis

View file

@ -13,266 +13,228 @@
using namespace zeek::packet_analysis;
Manager::Manager()
: plugin::ComponentManager<packet_analysis::Component>("PacketAnalyzer", "Tag", "AllAnalyzers")
{
}
Manager::Manager() : plugin::ComponentManager<packet_analysis::Component>("PacketAnalyzer", "Tag", "AllAnalyzers") {}
Manager::~Manager()
{
delete pkt_profiler;
delete pkt_filter;
}
Manager::~Manager() {
delete pkt_profiler;
delete pkt_filter;
}
void Manager::InitPostScript(const std::string& unprocessed_output_file)
{
// Instantiate objects for all available analyzers
for ( const auto& analyzerComponent : GetComponents() )
{
if ( AnalyzerPtr newAnalyzer = InstantiateAnalyzer(analyzerComponent->Tag()) )
{
newAnalyzer->SetEnabled(analyzerComponent->Enabled());
analyzers.emplace(analyzerComponent->Name(), newAnalyzer);
}
}
void Manager::InitPostScript(const std::string& unprocessed_output_file) {
// Instantiate objects for all available analyzers
for ( const auto& analyzerComponent : GetComponents() ) {
if ( AnalyzerPtr newAnalyzer = InstantiateAnalyzer(analyzerComponent->Tag()) ) {
newAnalyzer->SetEnabled(analyzerComponent->Enabled());
analyzers.emplace(analyzerComponent->Name(), newAnalyzer);
}
}
// Initialize all analyzers
for ( auto& [name, analyzer] : analyzers )
analyzer->Initialize();
// Initialize all analyzers
for ( auto& [name, analyzer] : analyzers )
analyzer->Initialize();
root_analyzer = analyzers["Root"];
root_analyzer = analyzers["Root"];
auto pkt_profile_file = id::find_val("pkt_profile_file");
auto pkt_profile_file = id::find_val("pkt_profile_file");
if ( detail::pkt_profile_mode && detail::pkt_profile_freq > 0 && pkt_profile_file )
pkt_profiler = new detail::PacketProfiler(
detail::pkt_profile_mode, detail::pkt_profile_freq, pkt_profile_file->AsFile());
if ( detail::pkt_profile_mode && detail::pkt_profile_freq > 0 && pkt_profile_file )
pkt_profiler =
new detail::PacketProfiler(detail::pkt_profile_mode, detail::pkt_profile_freq, pkt_profile_file->AsFile());
unknown_sampling_rate = id::find_val("UnknownProtocol::sampling_rate")->AsCount();
unknown_sampling_threshold = id::find_val("UnknownProtocol::sampling_threshold")->AsCount();
unknown_sampling_duration = id::find_val("UnknownProtocol::sampling_duration")->AsInterval();
unknown_first_bytes_count = id::find_val("UnknownProtocol::first_bytes_count")->AsCount();
unknown_sampling_rate = id::find_val("UnknownProtocol::sampling_rate")->AsCount();
unknown_sampling_threshold = id::find_val("UnknownProtocol::sampling_threshold")->AsCount();
unknown_sampling_duration = id::find_val("UnknownProtocol::sampling_duration")->AsInterval();
unknown_first_bytes_count = id::find_val("UnknownProtocol::first_bytes_count")->AsCount();
if ( ! unprocessed_output_file.empty() )
// This gets automatically cleaned up by iosource_mgr. No need to delete it locally.
unprocessed_dumper = iosource_mgr->OpenPktDumper(unprocessed_output_file, true);
}
if ( ! unprocessed_output_file.empty() )
// This gets automatically cleaned up by iosource_mgr. No need to delete it locally.
unprocessed_dumper = iosource_mgr->OpenPktDumper(unprocessed_output_file, true);
}
void Manager::Done() { }
void Manager::Done() {}
void Manager::DumpDebug()
{
void Manager::DumpDebug() {
#ifdef DEBUG
DBG_LOG(DBG_PACKET_ANALYSIS, "Available packet analyzers after zeek_init():");
for ( auto& current : GetComponents() )
DBG_LOG(DBG_PACKET_ANALYSIS, " %s", current->Name().c_str());
DBG_LOG(DBG_PACKET_ANALYSIS, "Available packet analyzers after zeek_init():");
for ( auto& current : GetComponents() )
DBG_LOG(DBG_PACKET_ANALYSIS, " %s", current->Name().c_str());
DBG_LOG(DBG_PACKET_ANALYSIS, "Packet analyzer debug information:");
for ( auto& [name, analyzer] : analyzers )
analyzer->DumpDebug();
DBG_LOG(DBG_PACKET_ANALYSIS, "Packet analyzer debug information:");
for ( auto& [name, analyzer] : analyzers )
analyzer->DumpDebug();
#endif
}
}
AnalyzerPtr Manager::GetAnalyzer(EnumVal* val)
{
auto analyzer_comp = Lookup(val);
if ( ! analyzer_comp )
return nullptr;
AnalyzerPtr Manager::GetAnalyzer(EnumVal* val) {
auto analyzer_comp = Lookup(val);
if ( ! analyzer_comp )
return nullptr;
return GetAnalyzer(analyzer_comp->Name());
}
return GetAnalyzer(analyzer_comp->Name());
}
AnalyzerPtr Manager::GetAnalyzer(const std::string& name)
{
auto analyzer_it = analyzers.find(name);
if ( analyzer_it == analyzers.end() )
return nullptr;
AnalyzerPtr Manager::GetAnalyzer(const std::string& name) {
auto analyzer_it = analyzers.find(name);
if ( analyzer_it == analyzers.end() )
return nullptr;
return analyzer_it->second;
}
return analyzer_it->second;
}
bool Manager::EnableAnalyzer(EnumVal* tag)
{
Component* c = Lookup(tag);
c->SetEnabled(true);
bool Manager::EnableAnalyzer(EnumVal* tag) {
Component* c = Lookup(tag);
c->SetEnabled(true);
return true;
}
return true;
}
bool Manager::DisableAnalyzer(EnumVal* tag)
{
Component* c = Lookup(tag);
c->SetEnabled(false);
bool Manager::DisableAnalyzer(EnumVal* tag) {
Component* c = Lookup(tag);
c->SetEnabled(false);
return true;
}
return true;
}
void Manager::ProcessPacket(Packet* packet)
{
void Manager::ProcessPacket(Packet* packet) {
#ifdef DEBUG
static size_t counter = 0;
DBG_LOG(DBG_PACKET_ANALYSIS, "Analyzing packet %ld, ts=%.3f...", ++counter, packet->time);
static size_t counter = 0;
DBG_LOG(DBG_PACKET_ANALYSIS, "Analyzing packet %ld, ts=%.3f...", ++counter, packet->time);
#endif
zeek::detail::SegmentProfiler prof(detail::segment_logger, "dispatching-packet");
if ( pkt_profiler )
pkt_profiler->ProfilePkt(zeek::run_state::processing_start_time, packet->cap_len);
zeek::detail::SegmentProfiler prof(detail::segment_logger, "dispatching-packet");
if ( pkt_profiler )
pkt_profiler->ProfilePkt(zeek::run_state::processing_start_time, packet->cap_len);
++num_packets_processed;
++num_packets_processed;
bool dumped_packet = false;
if ( packet->dump_packet || zeek::detail::record_all_packets )
{
DumpPacket(packet, packet->dump_size);
dumped_packet = true;
}
bool dumped_packet = false;
if ( packet->dump_packet || zeek::detail::record_all_packets ) {
DumpPacket(packet, packet->dump_size);
dumped_packet = true;
}
// Start packet analysis
root_analyzer->ForwardPacket(packet->cap_len, packet->data, packet, packet->link_type);
// Start packet analysis
root_analyzer->ForwardPacket(packet->cap_len, packet->data, packet, packet->link_type);
if ( ! packet->processed )
{
if ( packet_not_processed )
event_mgr.Enqueue(packet_not_processed, Packet::ToVal(packet));
if ( ! packet->processed ) {
if ( packet_not_processed )
event_mgr.Enqueue(packet_not_processed, Packet::ToVal(packet));
plugin_mgr->HookUnprocessedPacket(packet);
plugin_mgr->HookUnprocessedPacket(packet);
if ( unprocessed_dumper )
unprocessed_dumper->Dump(packet);
if ( unprocessed_dumper )
unprocessed_dumper->Dump(packet);
total_not_processed++;
}
total_not_processed++;
}
if ( raw_packet )
event_mgr.Enqueue(raw_packet, packet->ToRawPktHdrVal());
if ( raw_packet )
event_mgr.Enqueue(raw_packet, packet->ToRawPktHdrVal());
// Check whether packet should be recorded based on session analysis
if ( packet->dump_packet && ! dumped_packet )
DumpPacket(packet, packet->dump_size);
}
// Check whether packet should be recorded based on session analysis
if ( packet->dump_packet && ! dumped_packet )
DumpPacket(packet, packet->dump_size);
}
bool Manager::ProcessInnerPacket(Packet* packet)
{
return root_analyzer->ForwardPacket(packet->cap_len, packet->data, packet, packet->link_type);
}
bool Manager::ProcessInnerPacket(Packet* packet) {
return root_analyzer->ForwardPacket(packet->cap_len, packet->data, packet, packet->link_type);
}
AnalyzerPtr Manager::InstantiateAnalyzer(const Tag& tag)
{
Component* c = Lookup(tag);
AnalyzerPtr Manager::InstantiateAnalyzer(const Tag& tag) {
Component* c = Lookup(tag);
if ( ! c )
{
reporter->InternalWarning("request to instantiate unknown packet_analysis");
return nullptr;
}
if ( ! c ) {
reporter->InternalWarning("request to instantiate unknown packet_analysis");
return nullptr;
}
if ( ! c->Factory() )
{
reporter->InternalWarning("analyzer %s cannot be instantiated dynamically",
GetComponentName(tag).c_str());
return nullptr;
}
if ( ! c->Factory() ) {
reporter->InternalWarning("analyzer %s cannot be instantiated dynamically", GetComponentName(tag).c_str());
return nullptr;
}
AnalyzerPtr a = c->Factory()();
AnalyzerPtr a = c->Factory()();
if ( ! a )
{
reporter->InternalWarning("analyzer instantiation failed");
return nullptr;
}
if ( ! a ) {
reporter->InternalWarning("analyzer instantiation failed");
return nullptr;
}
if ( tag != a->GetAnalyzerTag() )
{
reporter->InternalError("Mismatch of requested analyzer %s and instantiated analyzer %s. "
"This usually means that the plugin author made a mistake.",
GetComponentName(tag).c_str(),
GetComponentName(a->GetAnalyzerTag()).c_str());
}
if ( tag != a->GetAnalyzerTag() ) {
reporter->InternalError(
"Mismatch of requested analyzer %s and instantiated analyzer %s. "
"This usually means that the plugin author made a mistake.",
GetComponentName(tag).c_str(), GetComponentName(a->GetAnalyzerTag()).c_str());
}
return a;
}
return a;
}
AnalyzerPtr Manager::InstantiateAnalyzer(const std::string& name)
{
Tag tag = GetComponentTag(name);
return tag ? InstantiateAnalyzer(tag) : nullptr;
}
AnalyzerPtr Manager::InstantiateAnalyzer(const std::string& name) {
Tag tag = GetComponentTag(name);
return tag ? InstantiateAnalyzer(tag) : nullptr;
}
void Manager::DumpPacket(const Packet* pkt, int len)
{
if ( ! run_state::detail::pkt_dumper )
return;
void Manager::DumpPacket(const Packet* pkt, int len) {
if ( ! run_state::detail::pkt_dumper )
return;
if ( len != 0 )
{
if ( (uint32_t)len > pkt->cap_len )
reporter->Warning("bad modified caplen");
else
const_cast<Packet*>(pkt)->cap_len = len;
}
if ( len != 0 ) {
if ( (uint32_t)len > pkt->cap_len )
reporter->Warning("bad modified caplen");
else
const_cast<Packet*>(pkt)->cap_len = len;
}
run_state::detail::pkt_dumper->Dump(pkt);
}
run_state::detail::pkt_dumper->Dump(pkt);
}
class UnknownProtocolTimer final : public zeek::detail::Timer
{
class UnknownProtocolTimer final : public zeek::detail::Timer {
public:
// Represents a combination of an analyzer name and protocol identifier, where the identifier
// was reported as unknown by the analyzer.
using UnknownProtocolPair = std::pair<std::string, uint32_t>;
// Represents a combination of an analyzer name and protocol identifier, where the identifier
// was reported as unknown by the analyzer.
using UnknownProtocolPair = std::pair<std::string, uint32_t>;
UnknownProtocolTimer(double t, UnknownProtocolPair p, double timeout)
: zeek::detail::Timer(t + timeout, zeek::detail::TIMER_UNKNOWN_PROTOCOL_EXPIRE),
unknown_protocol(std::move(p))
{
}
UnknownProtocolTimer(double t, UnknownProtocolPair p, double timeout)
: zeek::detail::Timer(t + timeout, zeek::detail::TIMER_UNKNOWN_PROTOCOL_EXPIRE),
unknown_protocol(std::move(p)) {}
void Dispatch(double t, bool is_expire) override
{
zeek::packet_mgr->ResetUnknownProtocolTimer(unknown_protocol.first,
unknown_protocol.second);
}
void Dispatch(double t, bool is_expire) override {
zeek::packet_mgr->ResetUnknownProtocolTimer(unknown_protocol.first, unknown_protocol.second);
}
UnknownProtocolPair unknown_protocol;
};
UnknownProtocolPair unknown_protocol;
};
void Manager::ResetUnknownProtocolTimer(const std::string& analyzer, uint32_t protocol)
{
unknown_protocols.erase(std::make_pair(analyzer, protocol));
}
void Manager::ResetUnknownProtocolTimer(const std::string& analyzer, uint32_t protocol) {
unknown_protocols.erase(std::make_pair(analyzer, protocol));
}
bool Manager::PermitUnknownProtocol(const std::string& analyzer, uint32_t protocol)
{
auto p = std::make_pair(analyzer, protocol);
uint64_t& count = unknown_protocols[p];
++count;
bool Manager::PermitUnknownProtocol(const std::string& analyzer, uint32_t protocol) {
auto p = std::make_pair(analyzer, protocol);
uint64_t& count = unknown_protocols[p];
++count;
if ( count == 1 )
detail::timer_mgr->Add(
new UnknownProtocolTimer(run_state::network_time, p, unknown_sampling_duration));
if ( count == 1 )
detail::timer_mgr->Add(new UnknownProtocolTimer(run_state::network_time, p, unknown_sampling_duration));
if ( count < unknown_sampling_threshold )
return true;
if ( count < unknown_sampling_threshold )
return true;
auto num_above_threshold = count - unknown_sampling_threshold;
if ( unknown_sampling_rate )
return num_above_threshold % unknown_sampling_rate == 0;
auto num_above_threshold = count - unknown_sampling_threshold;
if ( unknown_sampling_rate )
return num_above_threshold % unknown_sampling_rate == 0;
return false;
}
return false;
}
void Manager::ReportUnknownProtocol(const std::string& analyzer, uint32_t protocol,
const uint8_t* data, size_t len)
{
if ( unknown_protocol )
{
if ( PermitUnknownProtocol(analyzer, protocol) )
{
int bytes_len = std::min(unknown_first_bytes_count, static_cast<uint64_t>(len));
void Manager::ReportUnknownProtocol(const std::string& analyzer, uint32_t protocol, const uint8_t* data, size_t len) {
if ( unknown_protocol ) {
if ( PermitUnknownProtocol(analyzer, protocol) ) {
int bytes_len = std::min(unknown_first_bytes_count, static_cast<uint64_t>(len));
event_mgr.Enqueue(unknown_protocol, make_intrusive<StringVal>(analyzer),
val_mgr->Count(protocol),
make_intrusive<StringVal>(bytes_len, (const char*)data));
}
}
}
event_mgr.Enqueue(unknown_protocol, make_intrusive<StringVal>(analyzer), val_mgr->Count(protocol),
make_intrusive<StringVal>(bytes_len, (const char*)data));
}
}
}

View file

@ -10,222 +10,216 @@
#include "zeek/packet_analysis/Dispatcher.h"
#include "zeek/plugin/ComponentManager.h"
namespace zeek
{
namespace zeek {
namespace detail
{
namespace detail {
class PacketProfiler;
}
}
namespace iosource
{
namespace iosource {
class PktDumper;
}
}
namespace packet_analysis
{
namespace packet_analysis {
class Analyzer;
using AnalyzerPtr = std::shared_ptr<Analyzer>;
class Manager : public plugin::ComponentManager<Component>
{
class Manager : public plugin::ComponentManager<Component> {
public:
/**
* Constructor.
*/
Manager();
/**
* Constructor.
*/
Manager();
/**
* Destructor.
*/
~Manager();
/**
* Destructor.
*/
~Manager();
/**
* Second-stage initialization of the manager. This is called late
* during Zeek's initialization after any scripts are processed.
*
* @param unprocessed_output_file A path to a file where unprocessed
* packets will be written. This can be an empty string to disable
* writing packets.
*/
void InitPostScript(const std::string& unprocessed_output_file);
/**
* Second-stage initialization of the manager. This is called late
* during Zeek's initialization after any scripts are processed.
*
* @param unprocessed_output_file A path to a file where unprocessed
* packets will be written. This can be an empty string to disable
* writing packets.
*/
void InitPostScript(const std::string& unprocessed_output_file);
/**
* Finished the manager's operations.
*/
void Done();
/**
* Finished the manager's operations.
*/
void Done();
/**
* Dumps out the state of all registered analyzers to the \c analyzer
* debug stream. Should be called only after any \c zeek_init events
* have executed to ensure that any of their changes are applied.
*/
void DumpDebug(); // Called after zeek_init() events.
/**
* Dumps out the state of all registered analyzers to the \c analyzer
* debug stream. Should be called only after any \c zeek_init events
* have executed to ensure that any of their changes are applied.
*/
void DumpDebug(); // Called after zeek_init() events.
/**
* Looks up an analyzer instance.
*
* @param val The analyzer's tag value.
*
* @return The analyzer instance or nullptr if no instance is found.
*/
AnalyzerPtr GetAnalyzer(EnumVal* val);
/**
* Looks up an analyzer instance.
*
* @param val The analyzer's tag value.
*
* @return The analyzer instance or nullptr if no instance is found.
*/
AnalyzerPtr GetAnalyzer(EnumVal* val);
/**
* Looks up an analyzer instance.
*
* @param name The name of the analyzer.
*
* @return The analyzer instance or nullptr if no instance is found.
*/
AnalyzerPtr GetAnalyzer(const std::string& name);
/**
* Looks up an analyzer instance.
*
* @param name The name of the analyzer.
*
* @return The analyzer instance or nullptr if no instance is found.
*/
AnalyzerPtr GetAnalyzer(const std::string& name);
/**
* Enables an analyzer type. Only enabled analyzers will participate
* in packet processing.
*
* @param tag The analyzer's tag.
*
* @return True if successful.
*/
bool EnableAnalyzer(zeek::EnumVal* tag);
/**
* Enables an analyzer type. Only enabled analyzers will participate
* in packet processing.
*
* @param tag The analyzer's tag.
*
* @return True if successful.
*/
bool EnableAnalyzer(zeek::EnumVal* tag);
/**
* Enables an analyzer type. Only enabled analyzers will participate
* in packet processing.
*
* @param tag The analyzer's tag.
*
* @return True if successful.
*/
bool EnableAnalyzer(const zeek::Tag& tag) { return EnableAnalyzer(tag.AsVal().get()); }
/**
* Enables an analyzer type. Only enabled analyzers will participate
* in packet processing.
*
* @param tag The analyzer's tag.
*
* @return True if successful.
*/
bool EnableAnalyzer(const zeek::Tag& tag) { return EnableAnalyzer(tag.AsVal().get()); }
/**
* Disables an analyzer type. Disabled analyzers will not participate
* in packet processing.
*
* @param tag The packet analyzer's tag.
*
* @return True if successful.
*/
bool DisableAnalyzer(zeek::EnumVal* tag);
/**
* Disables an analyzer type. Disabled analyzers will not participate
* in packet processing.
*
* @param tag The packet analyzer's tag.
*
* @return True if successful.
*/
bool DisableAnalyzer(zeek::EnumVal* tag);
/**
* Disables an analyzer type. Disabled analyzers will not participate
* in packet processing.
*
* @param tag The packet analyzer's tag.
*
* @return True if successful.
*/
bool DisableAnalyzer(const zeek::Tag& tag) { return DisableAnalyzer(tag.AsVal().get()); };
/**
* Disables an analyzer type. Disabled analyzers will not participate
* in packet processing.
*
* @param tag The packet analyzer's tag.
*
* @return True if successful.
*/
bool DisableAnalyzer(const zeek::Tag& tag) { return DisableAnalyzer(tag.AsVal().get()); };
/**
* Processes a packet by applying the configured packet analyzers.
*
* @param packet The packet to process.
*/
void ProcessPacket(Packet* packet);
/**
* Processes a packet by applying the configured packet analyzers.
*
* @param packet The packet to process.
*/
void ProcessPacket(Packet* packet);
/**
* Process the inner packet of an encapsulation. This can be used by tunnel
* analyzers to process a inner packet from the "beginning" directly through
* the root analyzer. This short-circuits some of the additional processing
* that happens in ProcessPacket().
*
* @param packet The packet to process.
*/
bool ProcessInnerPacket(Packet* packet);
/**
* Process the inner packet of an encapsulation. This can be used by tunnel
* analyzers to process a inner packet from the "beginning" directly through
* the root analyzer. This short-circuits some of the additional processing
* that happens in ProcessPacket().
*
* @param packet The packet to process.
*/
bool ProcessInnerPacket(Packet* packet);
uint64_t PacketsProcessed() const { return num_packets_processed; }
uint64_t PacketsProcessed() const { return num_packets_processed; }
/**
* Records the given packet if a dumper is active.
*
* @param pkt The packet to record.
* @param len The number of bytes to record. If set to zero, the whole
* packet is recorded.
*/
void DumpPacket(const Packet* pkt, int len = 0);
/**
* Records the given packet if a dumper is active.
*
* @param pkt The packet to record.
* @param len The number of bytes to record. If set to zero, the whole
* packet is recorded.
*/
void DumpPacket(const Packet* pkt, int len = 0);
/**
* Attempts to write an entry to unknown_protocols.log, rate-limited to avoid
* spamming the log with duplicates.
*
* @param analyzer The name of the analyzer that was trying to forward the packet.
* @param protocol The protocol of the next header that couldn't be forwarded.
* @param data A pointer to the data of the next header being processed. If this
* is passed as a nullptr, the first_bytes log column will be blank.
* @param len The remaining length of the data in the packet being processed.
*/
void ReportUnknownProtocol(const std::string& analyzer, uint32_t protocol,
const uint8_t* data = nullptr, size_t len = 0);
/**
* Attempts to write an entry to unknown_protocols.log, rate-limited to avoid
* spamming the log with duplicates.
*
* @param analyzer The name of the analyzer that was trying to forward the packet.
* @param protocol The protocol of the next header that couldn't be forwarded.
* @param data A pointer to the data of the next header being processed. If this
* is passed as a nullptr, the first_bytes log column will be blank.
* @param len The remaining length of the data in the packet being processed.
*/
void ReportUnknownProtocol(const std::string& analyzer, uint32_t protocol, const uint8_t* data = nullptr,
size_t len = 0);
/**
* Callback method for UnknownProtocolTimer to remove an analyzer/protocol
* pair from the map so that it can be logged again.
*/
void ResetUnknownProtocolTimer(const std::string& analyzer, uint32_t protocol);
/**
* Callback method for UnknownProtocolTimer to remove an analyzer/protocol
* pair from the map so that it can be logged again.
*/
void ResetUnknownProtocolTimer(const std::string& analyzer, uint32_t protocol);
detail::PacketFilter* GetPacketFilter(bool init = true)
{
if ( ! pkt_filter && init )
pkt_filter = new detail::PacketFilter(detail::packet_filter_default);
return pkt_filter;
}
detail::PacketFilter* GetPacketFilter(bool init = true) {
if ( ! pkt_filter && init )
pkt_filter = new detail::PacketFilter(detail::packet_filter_default);
return pkt_filter;
}
/**
* Returns the total number of packets received that weren't considered
* processed by some analyzer.
*/
uint64_t GetUnprocessedCount() const { return total_not_processed; }
/**
* Returns the total number of packets received that weren't considered
* processed by some analyzer.
*/
uint64_t GetUnprocessedCount() const { return total_not_processed; }
private:
/**
* Instantiates a new analyzer instance.
*
* @param tag The analyzer's tag.
*
* @return The new analyzer instance. Returns null if tag is invalid, the
* requested analyzer is disabled, or the analyzer can't be instantiated.
*/
AnalyzerPtr InstantiateAnalyzer(const zeek::Tag& tag);
/**
* Instantiates a new analyzer instance.
*
* @param tag The analyzer's tag.
*
* @return The new analyzer instance. Returns null if tag is invalid, the
* requested analyzer is disabled, or the analyzer can't be instantiated.
*/
AnalyzerPtr InstantiateAnalyzer(const zeek::Tag& tag);
/**
* Instantiates a new analyzer.
*
* @param name The name of the analyzer.
*
* @return The new analyzer instance. Returns null if the name is not known
* or if the requested analyzer that is disabled.
*/
AnalyzerPtr InstantiateAnalyzer(const std::string& name);
/**
* Instantiates a new analyzer.
*
* @param name The name of the analyzer.
*
* @return The new analyzer instance. Returns null if the name is not known
* or if the requested analyzer that is disabled.
*/
AnalyzerPtr InstantiateAnalyzer(const std::string& name);
bool PermitUnknownProtocol(const std::string& analyzer, uint32_t protocol);
bool PermitUnknownProtocol(const std::string& analyzer, uint32_t protocol);
std::map<std::string, AnalyzerPtr> analyzers;
AnalyzerPtr root_analyzer = nullptr;
std::map<std::string, AnalyzerPtr> analyzers;
AnalyzerPtr root_analyzer = nullptr;
uint64_t num_packets_processed = 0;
detail::PacketProfiler* pkt_profiler = nullptr;
detail::PacketFilter* pkt_filter = nullptr;
uint64_t num_packets_processed = 0;
detail::PacketProfiler* pkt_profiler = nullptr;
detail::PacketFilter* pkt_filter = nullptr;
using UnknownProtocolPair = std::pair<std::string, uint32_t>;
std::map<UnknownProtocolPair, uint64_t> unknown_protocols;
using UnknownProtocolPair = std::pair<std::string, uint32_t>;
std::map<UnknownProtocolPair, uint64_t> unknown_protocols;
uint64_t unknown_sampling_threshold = 0;
uint64_t unknown_sampling_rate = 0;
double unknown_sampling_duration = 0;
uint64_t unknown_first_bytes_count = 0;
uint64_t unknown_sampling_threshold = 0;
uint64_t unknown_sampling_rate = 0;
double unknown_sampling_duration = 0;
uint64_t unknown_first_bytes_count = 0;
uint64_t total_not_processed = 0;
iosource::PktDumper* unprocessed_dumper = nullptr;
};
uint64_t total_not_processed = 0;
iosource::PktDumper* unprocessed_dumper = nullptr;
};
} // namespace packet_analysis
} // namespace packet_analysis
extern zeek::packet_analysis::Manager* packet_mgr;
} // namespace zeek
} // namespace zeek

View file

@ -19,7 +19,7 @@
using namespace zeek::packet_analysis::ARP;
ARPAnalyzer::ARPAnalyzer() : zeek::packet_analysis::Analyzer("ARP") { }
ARPAnalyzer::ARPAnalyzer() : zeek::packet_analysis::Analyzer("ARP") {}
// Argh! FreeBSD and Linux have almost completely different net/if_arp.h .
// ... and on Solaris we are missing half of the ARPOP codes, so define
@ -84,165 +84,140 @@ ARPAnalyzer::ARPAnalyzer() : zeek::packet_analysis::Analyzer("ARP") { }
#define ARPHRD_IEEE802 6
#endif
bool ARPAnalyzer::AnalyzePacket(size_t len, const uint8_t* data, Packet* packet)
{
packet->l3_proto = L3_ARP;
bool ARPAnalyzer::AnalyzePacket(size_t len, const uint8_t* data, Packet* packet) {
packet->l3_proto = L3_ARP;
// Check whether the header is complete.
if ( sizeof(struct arp_pkthdr) > len )
{
Weird("truncated_ARP", packet);
return false;
}
// Check whether the header is complete.
if ( sizeof(struct arp_pkthdr) > len ) {
Weird("truncated_ARP", packet);
return false;
}
// Check whether the packet is OK ("inspired" in tcpdump's print-arp.c).
auto ah = (const struct arp_pkthdr*)data;
// Check whether the packet is OK ("inspired" in tcpdump's print-arp.c).
auto ah = (const struct arp_pkthdr*)data;
// Check the size.
size_t min_length = (ar_tpa(ah) - (caddr_t)data) + ah->ar_pln;
if ( min_length > len )
{
Weird("truncated_ARP", packet);
return false;
}
// Check the size.
size_t min_length = (ar_tpa(ah) - (caddr_t)data) + ah->ar_pln;
if ( min_length > len ) {
Weird("truncated_ARP", packet);
return false;
}
// ARP packets are considered processed if we get to this point. There may be issues
// with the processing of them, but they're actually an ARP packet and anything else
// will be reported via events.
packet->processed = true;
// ARP packets are considered processed if we get to this point. There may be issues
// with the processing of them, but they're actually an ARP packet and anything else
// will be reported via events.
packet->processed = true;
// Check the address description fields.
switch ( ntohs(ah->ar_hrd) )
{
case ARPHRD_ETHER:
case ARPHRD_IEEE802:
if ( ah->ar_hln != 6 )
{
// don't know how to handle the opcode
BadARPEvent(ah, "corrupt-arp-header (hrd=%i, hln=%i)", ntohs(ah->ar_hrd),
ah->ar_hln);
return false;
}
break;
// Check the address description fields.
switch ( ntohs(ah->ar_hrd) ) {
case ARPHRD_ETHER:
case ARPHRD_IEEE802:
if ( ah->ar_hln != 6 ) {
// don't know how to handle the opcode
BadARPEvent(ah, "corrupt-arp-header (hrd=%i, hln=%i)", ntohs(ah->ar_hrd), ah->ar_hln);
return false;
}
break;
default:
{
// don't know how to proceed
BadARPEvent(ah, "unknown-arp-hw-address (hrd=%i)", ntohs(ah->ar_hrd));
return false;
}
}
default: {
// don't know how to proceed
BadARPEvent(ah, "unknown-arp-hw-address (hrd=%i)", ntohs(ah->ar_hrd));
return false;
}
}
// Note: We don't support IPv6 addresses.
switch ( ntohs(ah->ar_pro) )
{
case ETHERTYPE_IP:
if ( ah->ar_pln != 4 )
{
// don't know how to handle the opcode
BadARPEvent(ah, "corrupt-arp-header (pro=%i, pln=%i)", ntohs(ah->ar_pro),
ah->ar_pln);
return false;
}
break;
// Note: We don't support IPv6 addresses.
switch ( ntohs(ah->ar_pro) ) {
case ETHERTYPE_IP:
if ( ah->ar_pln != 4 ) {
// don't know how to handle the opcode
BadARPEvent(ah, "corrupt-arp-header (pro=%i, pln=%i)", ntohs(ah->ar_pro), ah->ar_pln);
return false;
}
break;
default:
{
// don't know how to proceed
BadARPEvent(ah, "unknown-arp-proto-address (pro=%i)", ntohs(ah->ar_pro));
return false;
}
}
default: {
// don't know how to proceed
BadARPEvent(ah, "unknown-arp-proto-address (pro=%i)", ntohs(ah->ar_pro));
return false;
}
}
// Check MAC src address = ARP sender MAC address.
if ( memcmp(packet->l2_src, (const char*)ar_sha(ah), ah->ar_hln) != 0 )
{
BadARPEvent(ah, "weird-arp-sha");
return false;
}
// Check MAC src address = ARP sender MAC address.
if ( memcmp(packet->l2_src, (const char*)ar_sha(ah), ah->ar_hln) != 0 ) {
BadARPEvent(ah, "weird-arp-sha");
return false;
}
// Check the code is supported.
switch ( ntohs(ah->ar_op) )
{
case ARPOP_REQUEST:
RequestReplyEvent(arp_request, packet->l2_src, packet->l2_dst, ah);
break;
// Check the code is supported.
switch ( ntohs(ah->ar_op) ) {
case ARPOP_REQUEST: RequestReplyEvent(arp_request, packet->l2_src, packet->l2_dst, ah); break;
case ARPOP_REPLY:
RequestReplyEvent(arp_reply, packet->l2_src, packet->l2_dst, ah);
break;
case ARPOP_REPLY: RequestReplyEvent(arp_reply, packet->l2_src, packet->l2_dst, ah); break;
case ARPOP_REVREQUEST:
case ARPOP_REVREPLY:
case ARPOP_INVREQUEST:
case ARPOP_INVREPLY:
{
// don't know how to handle the opcode
BadARPEvent(ah, "unimplemented-arp-opcode (%i)", ntohs(ah->ar_op));
return false;
}
case ARPOP_REVREQUEST:
case ARPOP_REVREPLY:
case ARPOP_INVREQUEST:
case ARPOP_INVREPLY: {
// don't know how to handle the opcode
BadARPEvent(ah, "unimplemented-arp-opcode (%i)", ntohs(ah->ar_op));
return false;
}
default:
{
// invalid opcode
BadARPEvent(ah, "invalid-arp-opcode (opcode=%i)", ntohs(ah->ar_op));
return false;
}
}
default: {
// invalid opcode
BadARPEvent(ah, "invalid-arp-opcode (opcode=%i)", ntohs(ah->ar_op));
return false;
}
}
// Leave packet analyzer land
return true;
}
// Leave packet analyzer land
return true;
}
zeek::AddrValPtr ARPAnalyzer::ToAddrVal(const void* addr, size_t len)
{
if ( len < 4 )
return zeek::make_intrusive<zeek::AddrVal>(static_cast<uint32_t>(0));
zeek::AddrValPtr ARPAnalyzer::ToAddrVal(const void* addr, size_t len) {
if ( len < 4 )
return zeek::make_intrusive<zeek::AddrVal>(static_cast<uint32_t>(0));
// Note: We only handle IPv4 addresses.
return zeek::make_intrusive<zeek::AddrVal>(*(const uint32_t*)addr);
}
// Note: We only handle IPv4 addresses.
return zeek::make_intrusive<zeek::AddrVal>(*(const uint32_t*)addr);
}
zeek::StringValPtr ARPAnalyzer::ToEthAddrStr(const u_char* addr, size_t len)
{
if ( len < 6 )
return zeek::make_intrusive<zeek::StringVal>("");
zeek::StringValPtr ARPAnalyzer::ToEthAddrStr(const u_char* addr, size_t len) {
if ( len < 6 )
return zeek::make_intrusive<zeek::StringVal>("");
char buf[1024];
snprintf(buf, sizeof(buf), "%02x:%02x:%02x:%02x:%02x:%02x", addr[0], addr[1], addr[2], addr[3],
addr[4], addr[5]);
return zeek::make_intrusive<zeek::StringVal>(buf);
}
char buf[1024];
snprintf(buf, sizeof(buf), "%02x:%02x:%02x:%02x:%02x:%02x", addr[0], addr[1], addr[2], addr[3], addr[4], addr[5]);
return zeek::make_intrusive<zeek::StringVal>(buf);
}
void ARPAnalyzer::BadARPEvent(const struct arp_pkthdr* hdr, const char* fmt, ...)
{
if ( ! bad_arp )
return;
void ARPAnalyzer::BadARPEvent(const struct arp_pkthdr* hdr, const char* fmt, ...) {
if ( ! bad_arp )
return;
char msg[1024];
va_list args;
va_start(args, fmt);
vsnprintf(msg, sizeof(msg), fmt, args);
va_end(args);
char msg[1024];
va_list args;
va_start(args, fmt);
vsnprintf(msg, sizeof(msg), fmt, args);
va_end(args);
event_mgr.Enqueue(bad_arp, ToAddrVal(reinterpret_cast<const u_char*>(ar_spa(hdr)), hdr->ar_pln),
ToEthAddrStr(reinterpret_cast<const u_char*>(ar_sha(hdr)), hdr->ar_hln),
ToAddrVal(reinterpret_cast<const u_char*>(ar_tpa(hdr)), hdr->ar_pln),
ToEthAddrStr(reinterpret_cast<const u_char*>(ar_tha(hdr)), hdr->ar_hln),
zeek::make_intrusive<zeek::StringVal>(msg));
}
event_mgr.Enqueue(bad_arp, ToAddrVal(reinterpret_cast<const u_char*>(ar_spa(hdr)), hdr->ar_pln),
ToEthAddrStr(reinterpret_cast<const u_char*>(ar_sha(hdr)), hdr->ar_hln),
ToAddrVal(reinterpret_cast<const u_char*>(ar_tpa(hdr)), hdr->ar_pln),
ToEthAddrStr(reinterpret_cast<const u_char*>(ar_tha(hdr)), hdr->ar_hln),
zeek::make_intrusive<zeek::StringVal>(msg));
}
void ARPAnalyzer::RequestReplyEvent(EventHandlerPtr e, const u_char* src, const u_char* dst,
const struct arp_pkthdr* hdr)
{
if ( ! e )
return;
const struct arp_pkthdr* hdr) {
if ( ! e )
return;
// The src and dst pointers are the l2_src and l2_dst addresses from the packet. We assume
// that the length of those were validated at some point earlier in the processing.
event_mgr.Enqueue(e, ToEthAddrStr(src, 6), ToEthAddrStr(dst, 6),
ToAddrVal(ar_spa(hdr), hdr->ar_pln),
ToEthAddrStr(reinterpret_cast<const u_char*>(ar_sha(hdr)), hdr->ar_hln),
ToAddrVal(ar_tpa(hdr), hdr->ar_pln),
ToEthAddrStr(reinterpret_cast<const u_char*>(ar_tha(hdr)), hdr->ar_hln));
}
// The src and dst pointers are the l2_src and l2_dst addresses from the packet. We assume
// that the length of those were validated at some point earlier in the processing.
event_mgr.Enqueue(e, ToEthAddrStr(src, 6), ToEthAddrStr(dst, 6), ToAddrVal(ar_spa(hdr), hdr->ar_pln),
ToEthAddrStr(reinterpret_cast<const u_char*>(ar_sha(hdr)), hdr->ar_hln),
ToAddrVal(ar_tpa(hdr), hdr->ar_pln),
ToEthAddrStr(reinterpret_cast<const u_char*>(ar_tha(hdr)), hdr->ar_hln));
}

View file

@ -15,30 +15,23 @@
#define arp_pkthdr arphdr
#endif
namespace zeek::packet_analysis::ARP
{
namespace zeek::packet_analysis::ARP {
class ARPAnalyzer : public Analyzer
{
class ARPAnalyzer : public Analyzer {
public:
ARPAnalyzer();
~ARPAnalyzer() override = default;
ARPAnalyzer();
~ARPAnalyzer() override = default;
bool AnalyzePacket(size_t len, const uint8_t* data, Packet* packet) override;
bool AnalyzePacket(size_t len, const uint8_t* data, Packet* packet) override;
static zeek::packet_analysis::AnalyzerPtr Instantiate()
{
return std::make_shared<ARPAnalyzer>();
}
static zeek::packet_analysis::AnalyzerPtr Instantiate() { return std::make_shared<ARPAnalyzer>(); }
private:
zeek::AddrValPtr ToAddrVal(const void* addr, size_t len);
zeek::StringValPtr ToEthAddrStr(const u_char* addr, size_t len);
zeek::AddrValPtr ToAddrVal(const void* addr, size_t len);
zeek::StringValPtr ToEthAddrStr(const u_char* addr, size_t len);
void BadARPEvent(const struct arp_pkthdr* hdr, const char* fmt, ...)
__attribute__((format(printf, 3, 4)));
void RequestReplyEvent(EventHandlerPtr e, const u_char* src, const u_char* dst,
const struct arp_pkthdr* hdr);
};
void BadARPEvent(const struct arp_pkthdr* hdr, const char* fmt, ...) __attribute__((format(printf, 3, 4)));
void RequestReplyEvent(EventHandlerPtr e, const u_char* src, const u_char* dst, const struct arp_pkthdr* hdr);
};
}
} // namespace zeek::packet_analysis::ARP

View file

@ -5,23 +5,19 @@
#include "zeek/packet_analysis/Component.h"
#include "zeek/packet_analysis/protocol/arp/ARP.h"
namespace zeek::plugin::Zeek_ARP
{
namespace zeek::plugin::Zeek_ARP {
class Plugin final : public zeek::plugin::Plugin
{
class Plugin final : public zeek::plugin::Plugin {
public:
zeek::plugin::Configuration Configure() override
{
AddComponent(new zeek::packet_analysis::Component(
"ARP", zeek::packet_analysis::ARP::ARPAnalyzer::Instantiate));
zeek::plugin::Configuration Configure() override {
AddComponent(new zeek::packet_analysis::Component("ARP", zeek::packet_analysis::ARP::ARPAnalyzer::Instantiate));
zeek::plugin::Configuration config;
config.name = "Zeek::ARP";
config.description = "ARP packet analyzer";
return config;
}
zeek::plugin::Configuration config;
config.name = "Zeek::ARP";
config.description = "ARP packet analyzer";
return config;
}
} plugin;
} plugin;
}
} // namespace zeek::plugin::Zeek_ARP

View file

@ -6,80 +6,72 @@
using namespace zeek::packet_analysis::AYIYA;
AYIYAAnalyzer::AYIYAAnalyzer() : zeek::packet_analysis::Analyzer("AYIYA") { }
AYIYAAnalyzer::AYIYAAnalyzer() : zeek::packet_analysis::Analyzer("AYIYA") {}
bool AYIYAAnalyzer::AnalyzePacket(size_t len, const uint8_t* data, Packet* packet)
{
// AYIYA always comes from a TCP or UDP connection, which means that session
// should always be valid and always be a connection. Return a weird if we
// didn't have a session stored.
if ( ! packet->session )
{
Analyzer::Weird("ayiya_missing_connection");
return false;
}
else if ( AnalyzerViolated(packet->session) )
return false;
bool AYIYAAnalyzer::AnalyzePacket(size_t len, const uint8_t* data, Packet* packet) {
// AYIYA always comes from a TCP or UDP connection, which means that session
// should always be valid and always be a connection. Return a weird if we
// didn't have a session stored.
if ( ! packet->session ) {
Analyzer::Weird("ayiya_missing_connection");
return false;
}
else if ( AnalyzerViolated(packet->session) )
return false;
if ( packet->encap && packet->encap->Depth() >= BifConst::Tunnel::max_depth )
{
Weird("exceeded_tunnel_max_depth", packet);
return false;
}
if ( packet->encap && packet->encap->Depth() >= BifConst::Tunnel::max_depth ) {
Weird("exceeded_tunnel_max_depth", packet);
return false;
}
// This will be expanded based on the header data, but it has to be at least
// this long.
size_t hdr_size = 8;
// This will be expanded based on the header data, but it has to be at least
// this long.
size_t hdr_size = 8;
if ( hdr_size > len )
{
AnalyzerViolation("Truncated AYIYA", packet->session);
return false;
}
if ( hdr_size > len ) {
AnalyzerViolation("Truncated AYIYA", packet->session);
return false;
}
uint8_t identity_len = 1 << (data[0] >> 4);
uint8_t signature_len = (data[1] >> 4) * 4;
hdr_size += identity_len + signature_len;
uint8_t identity_len = 1 << (data[0] >> 4);
uint8_t signature_len = (data[1] >> 4) * 4;
hdr_size += identity_len + signature_len;
// Double-check this one now that we know the actual full length of the header.
if ( hdr_size > len )
{
AnalyzerViolation("Truncated AYIYA", packet->session);
return false;
}
// Double-check this one now that we know the actual full length of the header.
if ( hdr_size > len ) {
AnalyzerViolation("Truncated AYIYA", packet->session);
return false;
}
uint8_t op_code = data[2] & 0x0F;
uint8_t op_code = data[2] & 0x0F;
// Check that op_code is the "forward" command. Everything else is ignored.
// This isn't an error, it's just the end of our parsing.
if ( op_code != 1 )
return true;
// Check that op_code is the "forward" command. Everything else is ignored.
// This isn't an error, it's just the end of our parsing.
if ( op_code != 1 )
return true;
uint8_t next_header = data[3];
uint8_t next_header = data[3];
len -= hdr_size;
data += hdr_size;
len -= hdr_size;
data += hdr_size;
// We've successfully parsed the AYIYA part, so we might as well confirm this.
AnalyzerConfirmation(packet->session);
// We've successfully parsed the AYIYA part, so we might as well confirm this.
AnalyzerConfirmation(packet->session);
if ( len == 0 )
{
// A AYIYA header that isn't followed by a tunnelled packet seems weird.
Weird("ayiya_empty_packet", packet);
return false;
}
if ( len == 0 ) {
// A AYIYA header that isn't followed by a tunnelled packet seems weird.
Weird("ayiya_empty_packet", packet);
return false;
}
int encap_index = 0;
auto inner_packet = packet_analysis::IPTunnel::build_inner_packet(
packet, &encap_index, nullptr, len, data, DLT_RAW, BifEnum::Tunnel::AYIYA,
GetAnalyzerTag());
int encap_index = 0;
auto inner_packet = packet_analysis::IPTunnel::build_inner_packet(packet, &encap_index, nullptr, len, data, DLT_RAW,
BifEnum::Tunnel::AYIYA, GetAnalyzerTag());
return ForwardPacket(len, data, inner_packet.get(), next_header);
}
return ForwardPacket(len, data, inner_packet.get(), next_header);
}
bool AYIYAAnalyzer::DetectProtocol(size_t len, const uint8_t* data, Packet* packet)
{
// These magic numbers are based on the old DPD entry, which was based on... something?
return len >= 3 && data[1] == 0x52 && data[2] == 0x11;
}
bool AYIYAAnalyzer::DetectProtocol(size_t len, const uint8_t* data, Packet* packet) {
// These magic numbers are based on the old DPD entry, which was based on... something?
return len >= 3 && data[1] == 0x52 && data[2] == 0x11;
}

View file

@ -5,23 +5,18 @@
#include "zeek/packet_analysis/Analyzer.h"
#include "zeek/packet_analysis/Component.h"
namespace zeek::packet_analysis::AYIYA
{
namespace zeek::packet_analysis::AYIYA {
class AYIYAAnalyzer : public zeek::packet_analysis::Analyzer
{
class AYIYAAnalyzer : public zeek::packet_analysis::Analyzer {
public:
AYIYAAnalyzer();
~AYIYAAnalyzer() override = default;
AYIYAAnalyzer();
~AYIYAAnalyzer() override = default;
bool AnalyzePacket(size_t len, const uint8_t* data, Packet* packet) override;
bool AnalyzePacket(size_t len, const uint8_t* data, Packet* packet) override;
static zeek::packet_analysis::AnalyzerPtr Instantiate()
{
return std::make_shared<AYIYAAnalyzer>();
}
static zeek::packet_analysis::AnalyzerPtr Instantiate() { return std::make_shared<AYIYAAnalyzer>(); }
bool DetectProtocol(size_t len, const uint8_t* data, Packet* packet) override;
};
bool DetectProtocol(size_t len, const uint8_t* data, Packet* packet) override;
};
}
} // namespace zeek::packet_analysis::AYIYA

View file

@ -5,23 +5,20 @@
#include "zeek/packet_analysis/Component.h"
#include "zeek/packet_analysis/protocol/ayiya/AYIYA.h"
namespace zeek::plugin::Zeek_AYIYA
{
namespace zeek::plugin::Zeek_AYIYA {
class Plugin final : public zeek::plugin::Plugin
{
class Plugin final : public zeek::plugin::Plugin {
public:
zeek::plugin::Configuration Configure() override
{
AddComponent(new zeek::packet_analysis::Component(
"AYIYA", zeek::packet_analysis::AYIYA::AYIYAAnalyzer::Instantiate));
zeek::plugin::Configuration Configure() override {
AddComponent(
new zeek::packet_analysis::Component("AYIYA", zeek::packet_analysis::AYIYA::AYIYAAnalyzer::Instantiate));
zeek::plugin::Configuration config;
config.name = "Zeek::AYIYA";
config.description = "AYIYA packet analyzer";
return config;
}
zeek::plugin::Configuration config;
config.name = "Zeek::AYIYA";
config.description = "AYIYA packet analyzer";
return config;
}
} plugin;
} plugin;
}
} // namespace zeek::plugin::Zeek_AYIYA

View file

@ -6,75 +6,67 @@
using namespace zeek::packet_analysis::Ethernet;
EthernetAnalyzer::EthernetAnalyzer() : zeek::packet_analysis::Analyzer("Ethernet")
{
snap_forwarding_key = id::find_val("PacketAnalyzer::ETHERNET::SNAP_FORWARDING_KEY")->AsCount();
novell_forwarding_key =
id::find_val("PacketAnalyzer::ETHERNET::NOVELL_FORWARDING_KEY")->AsCount();
llc_forwarding_key = id::find_val("PacketAnalyzer::ETHERNET::LLC_FORWARDING_KEY")->AsCount();
}
EthernetAnalyzer::EthernetAnalyzer() : zeek::packet_analysis::Analyzer("Ethernet") {
snap_forwarding_key = id::find_val("PacketAnalyzer::ETHERNET::SNAP_FORWARDING_KEY")->AsCount();
novell_forwarding_key = id::find_val("PacketAnalyzer::ETHERNET::NOVELL_FORWARDING_KEY")->AsCount();
llc_forwarding_key = id::find_val("PacketAnalyzer::ETHERNET::LLC_FORWARDING_KEY")->AsCount();
}
bool EthernetAnalyzer::AnalyzePacket(size_t len, const uint8_t* data, Packet* packet)
{
// Make sure that we actually got an entire ethernet header before trying
// to pull bytes out of it.
if ( 16 >= len )
{
Weird("truncated_ethernet_frame", packet);
return false;
}
bool EthernetAnalyzer::AnalyzePacket(size_t len, const uint8_t* data, Packet* packet) {
// Make sure that we actually got an entire ethernet header before trying
// to pull bytes out of it.
if ( 16 >= len ) {
Weird("truncated_ethernet_frame", packet);
return false;
}
// Skip past Cisco FabricPath to encapsulated ethernet frame.
if ( data[12] == 0x89 && data[13] == 0x03 )
{
auto constexpr cfplen = 16;
// Skip past Cisco FabricPath to encapsulated ethernet frame.
if ( data[12] == 0x89 && data[13] == 0x03 ) {
auto constexpr cfplen = 16;
if ( cfplen + 14 >= len )
{
Weird("truncated_link_header_cfp", packet);
return false;
}
if ( cfplen + 14 >= len ) {
Weird("truncated_link_header_cfp", packet);
return false;
}
data += cfplen;
len -= cfplen;
}
data += cfplen;
len -= cfplen;
}
// Get protocol being carried from the ethernet frame.
uint32_t protocol = (data[12] << 8) + data[13];
// Get protocol being carried from the ethernet frame.
uint32_t protocol = (data[12] << 8) + data[13];
packet->eth_type = protocol;
packet->l2_dst = data;
packet->l2_src = data + 6;
packet->eth_type = protocol;
packet->l2_dst = data;
packet->l2_src = data + 6;
// Ethernet II frames
if ( protocol >= 1536 )
return ForwardPacket(len - 14, data + 14, packet, protocol);
// Ethernet II frames
if ( protocol >= 1536 )
return ForwardPacket(len - 14, data + 14, packet, protocol);
// Other ethernet frame types
if ( protocol <= 1500 )
{
len -= 14;
data += 14;
// Other ethernet frame types
if ( protocol <= 1500 ) {
len -= 14;
data += 14;
if ( len < protocol )
{
Weird("truncated_ethernet_frame", packet);
return false;
}
if ( len < protocol ) {
Weird("truncated_ethernet_frame", packet);
return false;
}
// Let specialized analyzers take over for non Ethernet II frames.
if ( data[0] == 0xAA && data[1] == 0xAA )
// IEEE 802.2 SNAP
return ForwardPacket(len, data, packet, snap_forwarding_key);
else if ( data[0] == 0xFF && data[1] == 0xFF )
// Novell raw IEEE 802.3
return ForwardPacket(len, data, packet, novell_forwarding_key);
else
// IEEE 802.2 LLC
return ForwardPacket(len, data, packet, llc_forwarding_key);
}
// Let specialized analyzers take over for non Ethernet II frames.
if ( data[0] == 0xAA && data[1] == 0xAA )
// IEEE 802.2 SNAP
return ForwardPacket(len, data, packet, snap_forwarding_key);
else if ( data[0] == 0xFF && data[1] == 0xFF )
// Novell raw IEEE 802.3
return ForwardPacket(len, data, packet, novell_forwarding_key);
else
// IEEE 802.2 LLC
return ForwardPacket(len, data, packet, llc_forwarding_key);
}
// Undefined (1500 < EtherType < 1536)
Weird("undefined_ether_type", packet);
return false;
}
// Undefined (1500 < EtherType < 1536)
Weird("undefined_ether_type", packet);
return false;
}

View file

@ -5,26 +5,21 @@
#include "zeek/packet_analysis/Analyzer.h"
#include "zeek/packet_analysis/Component.h"
namespace zeek::packet_analysis::Ethernet
{
namespace zeek::packet_analysis::Ethernet {
class EthernetAnalyzer : public Analyzer
{
class EthernetAnalyzer : public Analyzer {
public:
EthernetAnalyzer();
~EthernetAnalyzer() override = default;
EthernetAnalyzer();
~EthernetAnalyzer() override = default;
bool AnalyzePacket(size_t len, const uint8_t* data, Packet* packet) override;
bool AnalyzePacket(size_t len, const uint8_t* data, Packet* packet) override;
static zeek::packet_analysis::AnalyzerPtr Instantiate()
{
return std::make_shared<EthernetAnalyzer>();
}
static zeek::packet_analysis::AnalyzerPtr Instantiate() { return std::make_shared<EthernetAnalyzer>(); }
private:
zeek_uint_t snap_forwarding_key = 0;
zeek_uint_t novell_forwarding_key = 0;
zeek_uint_t llc_forwarding_key = 0;
};
zeek_uint_t snap_forwarding_key = 0;
zeek_uint_t novell_forwarding_key = 0;
zeek_uint_t llc_forwarding_key = 0;
};
}
} // namespace zeek::packet_analysis::Ethernet

View file

@ -5,23 +5,21 @@
#include "zeek/packet_analysis/Component.h"
#include "zeek/packet_analysis/protocol/ethernet/Ethernet.h"
namespace zeek::plugin::Zeek_Ethernet
{
namespace zeek::plugin::Zeek_Ethernet {
class Plugin final : public zeek::plugin::Plugin
{
class Plugin final : public zeek::plugin::Plugin {
public:
zeek::plugin::Configuration Configure() override
{
AddComponent(new zeek::packet_analysis::Component(
"Ethernet", zeek::packet_analysis::Ethernet::EthernetAnalyzer::Instantiate));
zeek::plugin::Configuration Configure() override {
AddComponent(
new zeek::packet_analysis::Component("Ethernet",
zeek::packet_analysis::Ethernet::EthernetAnalyzer::Instantiate));
zeek::plugin::Configuration config;
config.name = "Zeek::Ethernet";
config.description = "Ethernet packet analyzer";
return config;
}
zeek::plugin::Configuration config;
config.name = "Zeek::Ethernet";
config.description = "Ethernet packet analyzer";
return config;
}
} plugin;
} plugin;
}
} // namespace zeek::plugin::Zeek_Ethernet

View file

@ -4,18 +4,16 @@
using namespace zeek::packet_analysis::FDDI;
FDDIAnalyzer::FDDIAnalyzer() : zeek::packet_analysis::Analyzer("FDDI") { }
FDDIAnalyzer::FDDIAnalyzer() : zeek::packet_analysis::Analyzer("FDDI") {}
bool FDDIAnalyzer::AnalyzePacket(size_t len, const uint8_t* data, Packet* packet)
{
size_t hdr_size = 13 + 8; // FDDI header + LLC
bool FDDIAnalyzer::AnalyzePacket(size_t len, const uint8_t* data, Packet* packet) {
size_t hdr_size = 13 + 8; // FDDI header + LLC
if ( hdr_size >= len )
{
Weird("FDDI_analyzer_failed");
return false;
}
if ( hdr_size >= len ) {
Weird("FDDI_analyzer_failed");
return false;
}
// We just skip the header and hope for default analysis
return ForwardPacket(len - hdr_size, data + hdr_size, packet);
}
// We just skip the header and hope for default analysis
return ForwardPacket(len - hdr_size, data + hdr_size, packet);
}

View file

@ -5,21 +5,16 @@
#include "zeek/packet_analysis/Analyzer.h"
#include "zeek/packet_analysis/Component.h"
namespace zeek::packet_analysis::FDDI
{
namespace zeek::packet_analysis::FDDI {
class FDDIAnalyzer : public zeek::packet_analysis::Analyzer
{
class FDDIAnalyzer : public zeek::packet_analysis::Analyzer {
public:
FDDIAnalyzer();
~FDDIAnalyzer() override = default;
FDDIAnalyzer();
~FDDIAnalyzer() override = default;
bool AnalyzePacket(size_t len, const uint8_t* data, Packet* packet) override;
bool AnalyzePacket(size_t len, const uint8_t* data, Packet* packet) override;
static zeek::packet_analysis::AnalyzerPtr Instantiate()
{
return std::make_shared<FDDIAnalyzer>();
}
};
static zeek::packet_analysis::AnalyzerPtr Instantiate() { return std::make_shared<FDDIAnalyzer>(); }
};
}
} // namespace zeek::packet_analysis::FDDI

View file

@ -5,23 +5,20 @@
#include "zeek/packet_analysis/Component.h"
#include "zeek/packet_analysis/protocol/fddi/FDDI.h"
namespace zeek::plugin::Zeek_FDDI
{
namespace zeek::plugin::Zeek_FDDI {
class Plugin final : public zeek::plugin::Plugin
{
class Plugin final : public zeek::plugin::Plugin {
public:
zeek::plugin::Configuration Configure() override
{
AddComponent(new zeek::packet_analysis::Component(
"FDDI", zeek::packet_analysis::FDDI::FDDIAnalyzer::Instantiate));
zeek::plugin::Configuration Configure() override {
AddComponent(
new zeek::packet_analysis::Component("FDDI", zeek::packet_analysis::FDDI::FDDIAnalyzer::Instantiate));
zeek::plugin::Configuration config;
config.name = "Zeek::FDDI";
config.description = "FDDI packet analyzer";
return config;
}
zeek::plugin::Configuration config;
config.name = "Zeek::FDDI";
config.description = "FDDI packet analyzer";
return config;
}
} plugin;
} plugin;
}
} // namespace zeek::plugin::Zeek_FDDI

View file

@ -7,93 +7,82 @@
using namespace zeek::packet_analysis::Geneve;
GeneveAnalyzer::GeneveAnalyzer() : zeek::packet_analysis::Analyzer("Geneve") { }
GeneveAnalyzer::GeneveAnalyzer() : zeek::packet_analysis::Analyzer("Geneve") {}
bool GeneveAnalyzer::AnalyzePacket(size_t len, const uint8_t* data, Packet* packet)
{
// Geneve always comes from a UDP connection, which means that session should always
// be valid and always be a connection. Return a weird if we didn't have a session
// stored.
if ( ! packet->session )
{
Analyzer::Weird("geneve_missing_connection");
return false;
}
else if ( AnalyzerViolated(packet->session) )
return false;
bool GeneveAnalyzer::AnalyzePacket(size_t len, const uint8_t* data, Packet* packet) {
// Geneve always comes from a UDP connection, which means that session should always
// be valid and always be a connection. Return a weird if we didn't have a session
// stored.
if ( ! packet->session ) {
Analyzer::Weird("geneve_missing_connection");
return false;
}
else if ( AnalyzerViolated(packet->session) )
return false;
if ( packet->encap && packet->encap->Depth() >= BifConst::Tunnel::max_depth )
{
Weird("exceeded_tunnel_max_depth", packet);
return false;
}
if ( packet->encap && packet->encap->Depth() >= BifConst::Tunnel::max_depth ) {
Weird("exceeded_tunnel_max_depth", packet);
return false;
}
// This will be expanded based on the length of the options in the header,
// but it will be at least this long.
uint16_t hdr_size = 8;
// This will be expanded based on the length of the options in the header,
// but it will be at least this long.
uint16_t hdr_size = 8;
if ( hdr_size > len )
{
AnalyzerViolation("Geneve header truncation", packet->session,
reinterpret_cast<const char*>(data), len);
return false;
}
if ( hdr_size > len ) {
AnalyzerViolation("Geneve header truncation", packet->session, reinterpret_cast<const char*>(data), len);
return false;
}
// Validate that the version number is correct. According to the RFC, this
// should always be zero, and anything else should be treated as an error.
auto version = data[0] >> 6;
if ( version != 0 )
{
Weird("geneve_invalid_version", packet, util::fmt("%d", version));
return false;
}
// Validate that the version number is correct. According to the RFC, this
// should always be zero, and anything else should be treated as an error.
auto version = data[0] >> 6;
if ( version != 0 ) {
Weird("geneve_invalid_version", packet, util::fmt("%d", version));
return false;
}
// Option length is the number of bytes for options, expressed in 4-byte multiples.
uint8_t opt_len = (data[0] & 0x3F) * 4;
hdr_size += opt_len;
// Option length is the number of bytes for options, expressed in 4-byte multiples.
uint8_t opt_len = (data[0] & 0x3F) * 4;
hdr_size += opt_len;
// Double-check this one now that we know the actual full length of the header.
if ( hdr_size > len )
{
AnalyzerViolation("Geneve option header truncation", packet->session,
reinterpret_cast<const char*>(data), len);
return false;
}
// Double-check this one now that we know the actual full length of the header.
if ( hdr_size > len ) {
AnalyzerViolation("Geneve option header truncation", packet->session, reinterpret_cast<const char*>(data), len);
return false;
}
// Get the next header. This will probably be Ethernet (0x6558), but get it
// anyways so that the forwarding can do its thing.
auto next_header = (data[2] << 8) + data[3];
// Get the next header. This will probably be Ethernet (0x6558), but get it
// anyways so that the forwarding can do its thing.
auto next_header = (data[2] << 8) + data[3];
// Grab the VNI out of the data before advancing the data pointer
auto vni = (data[4] << 16) + (data[5] << 8) + data[6];
// Grab the VNI out of the data before advancing the data pointer
auto vni = (data[4] << 16) + (data[5] << 8) + data[6];
len -= hdr_size;
data += hdr_size;
len -= hdr_size;
data += hdr_size;
// We've successfully parsed the Geneve part, so we might as well confirm this.
AnalyzerConfirmation(packet->session);
// We've successfully parsed the Geneve part, so we might as well confirm this.
AnalyzerConfirmation(packet->session);
if ( len == 0 )
{
// A Geneve header that isn't followed by a tunnelled packet seems weird.
Weird("geneve_empty_packet", packet);
return false;
}
if ( len == 0 ) {
// A Geneve header that isn't followed by a tunnelled packet seems weird.
Weird("geneve_empty_packet", packet);
return false;
}
int encap_index = 0;
auto inner_packet = packet_analysis::IPTunnel::build_inner_packet(
packet, &encap_index, nullptr, len, data, DLT_RAW, BifEnum::Tunnel::GENEVE,
GetAnalyzerTag());
int encap_index = 0;
auto inner_packet = packet_analysis::IPTunnel::build_inner_packet(packet, &encap_index, nullptr, len, data, DLT_RAW,
BifEnum::Tunnel::GENEVE, GetAnalyzerTag());
bool analysis_succeeded = ForwardPacket(len, data, inner_packet.get(), next_header);
bool analysis_succeeded = ForwardPacket(len, data, inner_packet.get(), next_header);
if ( analysis_succeeded && geneve_packet )
{
EncapsulatingConn* ec = inner_packet->encap->At(encap_index);
if ( ec && ec->ip_hdr )
inner_packet->session->EnqueueEvent(geneve_packet, nullptr, packet->session->GetVal(),
ec->ip_hdr->ToPktHdrVal(), val_mgr->Count(vni));
}
if ( analysis_succeeded && geneve_packet ) {
EncapsulatingConn* ec = inner_packet->encap->At(encap_index);
if ( ec && ec->ip_hdr )
inner_packet->session->EnqueueEvent(geneve_packet, nullptr, packet->session->GetVal(),
ec->ip_hdr->ToPktHdrVal(), val_mgr->Count(vni));
}
return analysis_succeeded;
}
return analysis_succeeded;
}

View file

@ -5,21 +5,16 @@
#include "zeek/packet_analysis/Analyzer.h"
#include "zeek/packet_analysis/Component.h"
namespace zeek::packet_analysis::Geneve
{
namespace zeek::packet_analysis::Geneve {
class GeneveAnalyzer : public zeek::packet_analysis::Analyzer
{
class GeneveAnalyzer : public zeek::packet_analysis::Analyzer {
public:
GeneveAnalyzer();
~GeneveAnalyzer() override = default;
GeneveAnalyzer();
~GeneveAnalyzer() override = default;
bool AnalyzePacket(size_t len, const uint8_t* data, Packet* packet) override;
bool AnalyzePacket(size_t len, const uint8_t* data, Packet* packet) override;
static zeek::packet_analysis::AnalyzerPtr Instantiate()
{
return std::make_shared<GeneveAnalyzer>();
}
};
static zeek::packet_analysis::AnalyzerPtr Instantiate() { return std::make_shared<GeneveAnalyzer>(); }
};
}
} // namespace zeek::packet_analysis::Geneve

View file

@ -5,23 +5,20 @@
#include "zeek/packet_analysis/Component.h"
#include "zeek/packet_analysis/protocol/geneve/Geneve.h"
namespace zeek::plugin::Zeek_Geneve
{
namespace zeek::plugin::Zeek_Geneve {
class Plugin final : public zeek::plugin::Plugin
{
class Plugin final : public zeek::plugin::Plugin {
public:
zeek::plugin::Configuration Configure() override
{
AddComponent(new zeek::packet_analysis::Component(
"Geneve", zeek::packet_analysis::Geneve::GeneveAnalyzer::Instantiate));
zeek::plugin::Configuration Configure() override {
AddComponent(
new zeek::packet_analysis::Component("Geneve", zeek::packet_analysis::Geneve::GeneveAnalyzer::Instantiate));
zeek::plugin::Configuration config;
config.name = "Zeek::Geneve";
config.description = "Geneve packet analyzer";
return config;
}
zeek::plugin::Configuration config;
config.name = "Zeek::Geneve";
config.description = "Geneve packet analyzer";
return config;
}
} plugin;
} plugin;
}
} // namespace zeek::plugin::Zeek_Geneve

View file

@ -11,221 +11,192 @@
using namespace zeek::packet_analysis::GRE;
static unsigned int gre_header_len(uint16_t flags = 0)
{
unsigned int len = 4; // Always has 2 byte flags and 2 byte protocol type.
static unsigned int gre_header_len(uint16_t flags = 0) {
unsigned int len = 4; // Always has 2 byte flags and 2 byte protocol type.
if ( flags & 0x8000 )
// Checksum/Reserved1 present.
len += 4;
if ( flags & 0x8000 )
// Checksum/Reserved1 present.
len += 4;
// Not considering routing presence bit since it's deprecated ...
// Not considering routing presence bit since it's deprecated ...
if ( flags & 0x2000 )
// Key present.
len += 4;
if ( flags & 0x2000 )
// Key present.
len += 4;
if ( flags & 0x1000 )
// Sequence present.
len += 4;
if ( flags & 0x1000 )
// Sequence present.
len += 4;
if ( flags & 0x0080 )
// Acknowledgement present.
len += 4;
if ( flags & 0x0080 )
// Acknowledgement present.
len += 4;
return len;
}
return len;
}
GREAnalyzer::GREAnalyzer() : zeek::packet_analysis::Analyzer("GRE") { }
GREAnalyzer::GREAnalyzer() : zeek::packet_analysis::Analyzer("GRE") {}
bool GREAnalyzer::AnalyzePacket(size_t len, const uint8_t* data, Packet* packet)
{
if ( ! packet->ip_hdr )
{
reporter->InternalError("GREAnalyzer: ip_hdr not provided from earlier analyzer");
return false;
}
bool GREAnalyzer::AnalyzePacket(size_t len, const uint8_t* data, Packet* packet) {
if ( ! packet->ip_hdr ) {
reporter->InternalError("GREAnalyzer: ip_hdr not provided from earlier analyzer");
return false;
}
if ( len < gre_header_len() )
{
Weird("truncated_GRE", packet);
return false;
}
if ( len < gre_header_len() ) {
Weird("truncated_GRE", packet);
return false;
}
int proto = packet->proto;
int gre_link_type = DLT_RAW;
int proto = packet->proto;
int gre_link_type = DLT_RAW;
uint16_t flags_ver = ntohs(*((uint16_t*)(data + 0)));
uint16_t proto_typ = ntohs(*((uint16_t*)(data + 2)));
int gre_version = flags_ver & 0x0007;
uint16_t flags_ver = ntohs(*((uint16_t*)(data + 0)));
uint16_t proto_typ = ntohs(*((uint16_t*)(data + 2)));
int gre_version = flags_ver & 0x0007;
unsigned int eth_len = 0;
unsigned int gre_len = gre_header_len(flags_ver);
unsigned int pptp_len = gre_version == 1 ? 4 : 0;
unsigned int erspan_len = 0;
unsigned int eth_len = 0;
unsigned int gre_len = gre_header_len(flags_ver);
unsigned int pptp_len = gre_version == 1 ? 4 : 0;
unsigned int erspan_len = 0;
if ( gre_version != 0 && gre_version != 1 )
{
Weird("unknown_gre_version", packet, util::fmt("version=%d", gre_version));
return false;
}
if ( gre_version != 0 && gre_version != 1 ) {
Weird("unknown_gre_version", packet, util::fmt("version=%d", gre_version));
return false;
}
if ( gre_version == 0 )
{
if ( proto_typ == 0x6558 )
{
// transparent ethernet bridging
if ( len > gre_len + 14 )
{
eth_len = 14;
gre_link_type = DLT_EN10MB;
}
else
{
Weird("truncated_GRE", packet);
return false;
}
}
if ( gre_version == 0 ) {
if ( proto_typ == 0x6558 ) {
// transparent ethernet bridging
if ( len > gre_len + 14 ) {
eth_len = 14;
gre_link_type = DLT_EN10MB;
}
else {
Weird("truncated_GRE", packet);
return false;
}
}
else if ( proto_typ == 0x88be )
{
if ( len > gre_len + 14 )
{
// ERSPAN type I
erspan_len = 0;
eth_len = 14;
gre_link_type = DLT_EN10MB;
bool have_sequence_header = ((flags_ver & 0x1000) == 0x1000);
if ( have_sequence_header )
{
// ERSPAN type II
erspan_len += 8;
if ( len < gre_len + eth_len + erspan_len )
{
Weird("truncated_GRE", packet);
return false;
}
}
}
else
{
Weird("truncated_GRE", packet);
return false;
}
}
else if ( proto_typ == 0x88be ) {
if ( len > gre_len + 14 ) {
// ERSPAN type I
erspan_len = 0;
eth_len = 14;
gre_link_type = DLT_EN10MB;
bool have_sequence_header = ((flags_ver & 0x1000) == 0x1000);
if ( have_sequence_header ) {
// ERSPAN type II
erspan_len += 8;
if ( len < gre_len + eth_len + erspan_len ) {
Weird("truncated_GRE", packet);
return false;
}
}
}
else {
Weird("truncated_GRE", packet);
return false;
}
}
else if ( proto_typ == 0x22eb )
{
// ERSPAN type III
if ( len > gre_len + 14 + 12 )
{
erspan_len = 12;
eth_len = 14;
gre_link_type = DLT_EN10MB;
else if ( proto_typ == 0x22eb ) {
// ERSPAN type III
if ( len > gre_len + 14 + 12 ) {
erspan_len = 12;
eth_len = 14;
gre_link_type = DLT_EN10MB;
auto flags = data + gre_len + erspan_len - 1;
bool have_opt_header = ((*flags & 0x01) == 0x01);
auto flags = data + gre_len + erspan_len - 1;
bool have_opt_header = ((*flags & 0x01) == 0x01);
if ( have_opt_header )
{
if ( len > gre_len + erspan_len + 8 + eth_len )
erspan_len += 8;
else
{
Weird("truncated_GRE", packet);
return false;
}
}
}
else
{
Weird("truncated_GRE", packet);
return false;
}
}
else if ( ((proto_typ & 0x8200) == 0x8200 && (proto_typ & 0x0F) == 0) ||
((proto_typ & 0x8300) == 0x8300 && (proto_typ & 0x0F) == 0 &&
(proto_typ <= 0x8370)) ||
(proto_typ == 0x9000) )
{
// ARUBA: Set gre_link_type to IEEE802.11 so the IPTUNNEL analyzer uses
// that to instantiate the fake tunnel packet, otherwise it'd be using
// DLT_RAW which is not correct for ARUBA.
if ( len <= gre_len )
{
Weird("truncated_GRE", packet);
return false;
}
if ( have_opt_header ) {
if ( len > gre_len + erspan_len + 8 + eth_len )
erspan_len += 8;
else {
Weird("truncated_GRE", packet);
return false;
}
}
}
else {
Weird("truncated_GRE", packet);
return false;
}
}
else if ( ((proto_typ & 0x8200) == 0x8200 && (proto_typ & 0x0F) == 0) ||
((proto_typ & 0x8300) == 0x8300 && (proto_typ & 0x0F) == 0 && (proto_typ <= 0x8370)) ||
(proto_typ == 0x9000) ) {
// ARUBA: Set gre_link_type to IEEE802.11 so the IPTUNNEL analyzer uses
// that to instantiate the fake tunnel packet, otherwise it'd be using
// DLT_RAW which is not correct for ARUBA.
if ( len <= gre_len ) {
Weird("truncated_GRE", packet);
return false;
}
gre_link_type = DLT_IEEE802_11;
proto = proto_typ;
}
else
{
// Otherwise let the packet analysis forwarding handle it.
proto = proto_typ;
}
}
gre_link_type = DLT_IEEE802_11;
proto = proto_typ;
}
else {
// Otherwise let the packet analysis forwarding handle it.
proto = proto_typ;
}
}
else // gre_version == 1
{
if ( proto_typ != 0x880b )
{
// Enhanced GRE payload must be PPTP.
Weird("egre_protocol_type", packet, util::fmt("proto=%d", proto_typ));
return false;
}
}
else // gre_version == 1
{
if ( proto_typ != 0x880b ) {
// Enhanced GRE payload must be PPTP.
Weird("egre_protocol_type", packet, util::fmt("proto=%d", proto_typ));
return false;
}
}
if ( flags_ver & 0x4000 )
{
// RFC 2784 deprecates the variable length routing field specified by RFC 1701. It could be
// parsed here, but easiest to just skip for now.
Weird("gre_routing", packet);
return false;
}
if ( flags_ver & 0x4000 ) {
// RFC 2784 deprecates the variable length routing field specified by RFC 1701. It could be
// parsed here, but easiest to just skip for now.
Weird("gre_routing", packet);
return false;
}
if ( flags_ver & 0x0078 )
{
// Expect last 4 bits of flags are reserved, undefined.
Weird("unknown_gre_flags", packet);
return false;
}
if ( flags_ver & 0x0078 ) {
// Expect last 4 bits of flags are reserved, undefined.
Weird("unknown_gre_flags", packet);
return false;
}
if ( len < gre_len + pptp_len + eth_len + erspan_len )
{
Weird("truncated_GRE", packet);
return false;
}
if ( len < gre_len + pptp_len + eth_len + erspan_len ) {
Weird("truncated_GRE", packet);
return false;
}
// For GRE version 1/PPTP, reset the protocol based on a value from the PPTP header.
// TODO: where are these two values defined?
if ( gre_version == 1 )
{
uint16_t pptp_proto = ntohs(*((uint16_t*)(data + gre_len + 2)));
// For GRE version 1/PPTP, reset the protocol based on a value from the PPTP header.
// TODO: where are these two values defined?
if ( gre_version == 1 ) {
uint16_t pptp_proto = ntohs(*((uint16_t*)(data + gre_len + 2)));
if ( pptp_proto != 0x0021 && pptp_proto != 0x0057 )
{
Weird("non_ip_packet_in_encap", packet);
return false;
}
if ( pptp_proto != 0x0021 && pptp_proto != 0x0057 ) {
Weird("non_ip_packet_in_encap", packet);
return false;
}
proto = (pptp_proto == 0x0021) ? IPPROTO_IPV4 : IPPROTO_IPV6;
}
proto = (pptp_proto == 0x0021) ? IPPROTO_IPV4 : IPPROTO_IPV6;
}
data += gre_len + pptp_len + erspan_len;
len -= gre_len + pptp_len + erspan_len;
data += gre_len + pptp_len + erspan_len;
len -= gre_len + pptp_len + erspan_len;
// Treat GRE tunnel like IP tunnels, fallthrough to logic below now that GRE header is stripped
// and only payload packet remains. The only thing different is the tunnel type enum value to
// use.
packet->tunnel_type = BifEnum::Tunnel::GRE;
packet->gre_version = gre_version;
packet->gre_link_type = gre_link_type;
packet->proto = proto;
// Treat GRE tunnel like IP tunnels, fallthrough to logic below now that GRE header is stripped
// and only payload packet remains. The only thing different is the tunnel type enum value to
// use.
packet->tunnel_type = BifEnum::Tunnel::GRE;
packet->gre_version = gre_version;
packet->gre_link_type = gre_link_type;
packet->proto = proto;
// This will default to forwarding into IP Tunnel unless something custom is set up.
ForwardPacket(len, data, packet, proto);
// This will default to forwarding into IP Tunnel unless something custom is set up.
ForwardPacket(len, data, packet, proto);
return true;
}
return true;
}

View file

@ -5,21 +5,16 @@
#include "zeek/packet_analysis/Analyzer.h"
#include "zeek/packet_analysis/Component.h"
namespace zeek::packet_analysis::GRE
{
namespace zeek::packet_analysis::GRE {
class GREAnalyzer : public Analyzer
{
class GREAnalyzer : public Analyzer {
public:
GREAnalyzer();
~GREAnalyzer() override = default;
GREAnalyzer();
~GREAnalyzer() override = default;
bool AnalyzePacket(size_t len, const uint8_t* data, Packet* packet) override;
bool AnalyzePacket(size_t len, const uint8_t* data, Packet* packet) override;
static zeek::packet_analysis::AnalyzerPtr Instantiate()
{
return std::make_shared<GREAnalyzer>();
}
};
static zeek::packet_analysis::AnalyzerPtr Instantiate() { return std::make_shared<GREAnalyzer>(); }
};
}
} // namespace zeek::packet_analysis::GRE

View file

@ -5,23 +5,19 @@
#include "zeek/packet_analysis/Component.h"
#include "zeek/packet_analysis/protocol/gre/GRE.h"
namespace zeek::plugin::Zeek_GRE
{
namespace zeek::plugin::Zeek_GRE {
class Plugin final : public zeek::plugin::Plugin
{
class Plugin final : public zeek::plugin::Plugin {
public:
zeek::plugin::Configuration Configure() override
{
AddComponent(new zeek::packet_analysis::Component(
"GRE", zeek::packet_analysis::GRE::GREAnalyzer::Instantiate));
zeek::plugin::Configuration Configure() override {
AddComponent(new zeek::packet_analysis::Component("GRE", zeek::packet_analysis::GRE::GREAnalyzer::Instantiate));
zeek::plugin::Configuration config;
config.name = "Zeek::GRE";
config.description = "GRE packet analyzer";
return config;
}
zeek::plugin::Configuration config;
config.name = "Zeek::GRE";
config.description = "GRE packet analyzer";
return config;
}
} plugin;
} plugin;
}
} // namespace zeek::plugin::Zeek_GRE

View file

@ -6,97 +6,83 @@
#include "zeek/packet_analysis/protocol/ip/IP.h"
#include "zeek/packet_analysis/protocol/iptunnel/IPTunnel.h"
namespace zeek::packet_analysis::gtpv1
{
GTPv1_Analyzer::GTPv1_Analyzer() : zeek::packet_analysis::Analyzer("GTPV1") { }
namespace zeek::packet_analysis::gtpv1 {
GTPv1_Analyzer::GTPv1_Analyzer() : zeek::packet_analysis::Analyzer("GTPV1") {}
bool GTPv1_Analyzer::AnalyzePacket(size_t len, const uint8_t* data, Packet* packet)
{
// GTPv1 always comes from a UDP connection, which means that session should always
// be valid and always be a connection. Return a weird if we didn't have a session
// stored.
if ( ! packet->session )
{
Analyzer::Weird("gtpv1_missing_connection");
return false;
}
bool GTPv1_Analyzer::AnalyzePacket(size_t len, const uint8_t* data, Packet* packet) {
// GTPv1 always comes from a UDP connection, which means that session should always
// be valid and always be a connection. Return a weird if we didn't have a session
// stored.
if ( ! packet->session ) {
Analyzer::Weird("gtpv1_missing_connection");
return false;
}
auto conn = static_cast<Connection*>(packet->session);
zeek::detail::ConnKey conn_key = conn->Key();
auto conn = static_cast<Connection*>(packet->session);
zeek::detail::ConnKey conn_key = conn->Key();
auto cm_it = conn_map.find(conn_key);
if ( cm_it == conn_map.end() )
cm_it = conn_map.insert(cm_it,
{conn_key, std::make_unique<binpac::GTPv1::GTPv1_Conn>(this)});
auto cm_it = conn_map.find(conn_key);
if ( cm_it == conn_map.end() )
cm_it = conn_map.insert(cm_it, {conn_key, std::make_unique<binpac::GTPv1::GTPv1_Conn>(this)});
try
{
cm_it->second->set_raw_packet(packet);
cm_it->second->NewData(packet->is_orig, data, data + len);
}
catch ( const binpac::Exception& e )
{
AnalyzerViolation(util::fmt("Binpac exception: %s", e.c_msg()), packet->session);
return false;
}
try {
cm_it->second->set_raw_packet(packet);
cm_it->second->NewData(packet->is_orig, data, data + len);
} catch ( const binpac::Exception& e ) {
AnalyzerViolation(util::fmt("Binpac exception: %s", e.c_msg()), packet->session);
return false;
}
// Inner packet offset not being set means we failed to process somewhere, and SetInnerInfo()
// was never called by the binpac code. Assume this is a failure and return false.
if ( inner_packet_offset <= 0 )
return false;
// Inner packet offset not being set means we failed to process somewhere, and SetInnerInfo()
// was never called by the binpac code. Assume this is a failure and return false.
if ( inner_packet_offset <= 0 )
return false;
auto odata = data;
auto olen = len;
data += inner_packet_offset;
len -= inner_packet_offset;
inner_packet_offset = -1;
auto odata = data;
auto olen = len;
data += inner_packet_offset;
len -= inner_packet_offset;
inner_packet_offset = -1;
// TODO: i'm not sure about this. on the one hand, we do some error checking with the result
// but on the other hand we duplicate this work here. maybe this header could just be stored
// and reused in the IP analyzer somehow?
std::shared_ptr<IP_Hdr> inner = nullptr;
auto result = packet_analysis::IP::ParsePacket(len, data, next_header, inner);
// TODO: i'm not sure about this. on the one hand, we do some error checking with the result
// but on the other hand we duplicate this work here. maybe this header could just be stored
// and reused in the IP analyzer somehow?
std::shared_ptr<IP_Hdr> inner = nullptr;
auto result = packet_analysis::IP::ParsePacket(len, data, next_header, inner);
if ( result == packet_analysis::IP::ParseResult::Ok )
{
cm_it->second->set_valid(packet->is_orig, true);
if ( result == packet_analysis::IP::ParseResult::Ok ) {
cm_it->second->set_valid(packet->is_orig, true);
if ( (! BifConst::Tunnel::delay_gtp_confirmation) ||
(cm_it->second->valid(true) && cm_it->second->valid(false)) )
AnalyzerConfirmation(packet->session);
if ( (! BifConst::Tunnel::delay_gtp_confirmation) ||
(cm_it->second->valid(true) && cm_it->second->valid(false)) )
AnalyzerConfirmation(packet->session);
if ( gtp_hdr_val )
{
BifEvent::enqueue_gtpv1_g_pdu_packet(nullptr, conn, std::move(gtp_hdr_val),
inner->ToPktHdrVal());
gtp_hdr_val = nullptr;
}
}
else if ( result == packet_analysis::IP::ParseResult::BadProtocol )
{
AnalyzerViolation("Invalid IP version in wrapped packet", packet->session);
gtp_hdr_val = nullptr;
return false;
}
else if ( result == packet_analysis::IP::ParseResult::CaplenTooSmall )
{
AnalyzerViolation("Truncated GTPv1", packet->session);
gtp_hdr_val = nullptr;
return false;
}
else
{
AnalyzerViolation("GTPv1 payload length", packet->session);
gtp_hdr_val = nullptr;
return false;
}
if ( gtp_hdr_val ) {
BifEvent::enqueue_gtpv1_g_pdu_packet(nullptr, conn, std::move(gtp_hdr_val), inner->ToPktHdrVal());
gtp_hdr_val = nullptr;
}
}
else if ( result == packet_analysis::IP::ParseResult::BadProtocol ) {
AnalyzerViolation("Invalid IP version in wrapped packet", packet->session);
gtp_hdr_val = nullptr;
return false;
}
else if ( result == packet_analysis::IP::ParseResult::CaplenTooSmall ) {
AnalyzerViolation("Truncated GTPv1", packet->session);
gtp_hdr_val = nullptr;
return false;
}
else {
AnalyzerViolation("GTPv1 payload length", packet->session);
gtp_hdr_val = nullptr;
return false;
}
int encap_index = 0;
auto inner_packet = packet_analysis::IPTunnel::build_inner_packet(
packet, &encap_index, nullptr, len, data, DLT_RAW, BifEnum::Tunnel::GTPv1,
GetAnalyzerTag());
int encap_index = 0;
auto inner_packet = packet_analysis::IPTunnel::build_inner_packet(packet, &encap_index, nullptr, len, data, DLT_RAW,
BifEnum::Tunnel::GTPv1, GetAnalyzerTag());
return ForwardPacket(len, data, inner_packet.get());
}
return ForwardPacket(len, data, inner_packet.get());
}
} // namespace zeek::packet_analysis::gtpv1
} // namespace zeek::packet_analysis::gtpv1

View file

@ -4,43 +4,36 @@
#include "packet_analysis/protocol/gtpv1/gtpv1_pac.h"
namespace binpac::GTPv1
{
namespace binpac::GTPv1 {
class GTPv1_Conn;
}
}
namespace zeek::packet_analysis::gtpv1
{
namespace zeek::packet_analysis::gtpv1 {
class GTPv1_Analyzer final : public packet_analysis::Analyzer
{
class GTPv1_Analyzer final : public packet_analysis::Analyzer {
public:
explicit GTPv1_Analyzer();
~GTPv1_Analyzer() override = default;
explicit GTPv1_Analyzer();
~GTPv1_Analyzer() override = default;
bool AnalyzePacket(size_t len, const uint8_t* data, Packet* packet) override;
bool AnalyzePacket(size_t len, const uint8_t* data, Packet* packet) override;
static zeek::packet_analysis::AnalyzerPtr Instantiate()
{
return std::make_shared<GTPv1_Analyzer>();
}
static zeek::packet_analysis::AnalyzerPtr Instantiate() { return std::make_shared<GTPv1_Analyzer>(); }
void SetInnerInfo(int offset, uint8_t next, RecordValPtr val)
{
inner_packet_offset = offset;
next_header = next;
gtp_hdr_val = std::move(val);
}
void SetInnerInfo(int offset, uint8_t next, RecordValPtr val) {
inner_packet_offset = offset;
next_header = next;
gtp_hdr_val = std::move(val);
}
void RemoveConnection(const zeek::detail::ConnKey& conn_key) { conn_map.erase(conn_key); }
void RemoveConnection(const zeek::detail::ConnKey& conn_key) { conn_map.erase(conn_key); }
protected:
using ConnMap = std::map<zeek::detail::ConnKey, std::unique_ptr<binpac::GTPv1::GTPv1_Conn>>;
ConnMap conn_map;
using ConnMap = std::map<zeek::detail::ConnKey, std::unique_ptr<binpac::GTPv1::GTPv1_Conn>>;
ConnMap conn_map;
int inner_packet_offset = -1;
uint8_t next_header = 0;
RecordValPtr gtp_hdr_val;
};
int inner_packet_offset = -1;
uint8_t next_header = 0;
RecordValPtr gtp_hdr_val;
};
} // namespace zeek::packet_analysis::gtpv1
} // namespace zeek::packet_analysis::gtpv1

View file

@ -5,22 +5,19 @@
#include "zeek/packet_analysis/Component.h"
#include "zeek/packet_analysis/protocol/gtpv1/GTPv1.h"
namespace zeek::plugin::detail::Zeek_GTPv1
{
namespace zeek::plugin::detail::Zeek_GTPv1 {
class Plugin final : public zeek::plugin::Plugin
{
class Plugin final : public zeek::plugin::Plugin {
public:
zeek::plugin::Configuration Configure() override
{
AddComponent(new zeek::packet_analysis::Component(
"GTPv1", zeek::packet_analysis::gtpv1::GTPv1_Analyzer::Instantiate));
zeek::plugin::Configuration Configure() override {
AddComponent(
new zeek::packet_analysis::Component("GTPv1", zeek::packet_analysis::gtpv1::GTPv1_Analyzer::Instantiate));
zeek::plugin::Configuration config;
config.name = "Zeek::GTPv1";
config.description = "GTPv1 analyzer";
return config;
}
} plugin;
zeek::plugin::Configuration config;
config.name = "Zeek::GTPv1";
config.description = "GTPv1 analyzer";
return config;
}
} plugin;
} // namespace zeek::plugin::detail::Zeek_GTPv1
} // namespace zeek::plugin::detail::Zeek_GTPv1

File diff suppressed because it is too large Load diff

View file

@ -8,87 +8,81 @@
#include "zeek/packet_analysis/protocol/ip/IPBasedAnalyzer.h"
#include "zeek/packet_analysis/protocol/ip/SessionAdapter.h"
namespace zeek
{
namespace zeek {
class VectorVal;
using VectorValPtr = IntrusivePtr<VectorVal>;
class RecordVal;
using RecordValPtr = IntrusivePtr<RecordVal>;
namespace packet_analysis::ICMP
{
namespace packet_analysis::ICMP {
class ICMPSessionAdapter;
class ICMPAnalyzer final : public IP::IPBasedAnalyzer
{
class ICMPAnalyzer final : public IP::IPBasedAnalyzer {
public:
ICMPAnalyzer();
~ICMPAnalyzer() override = default;
ICMPAnalyzer();
~ICMPAnalyzer() override = default;
static zeek::packet_analysis::AnalyzerPtr Instantiate()
{
return std::make_shared<ICMPAnalyzer>();
}
static zeek::packet_analysis::AnalyzerPtr Instantiate() { return std::make_shared<ICMPAnalyzer>(); }
packet_analysis::IP::SessionAdapter* MakeSessionAdapter(Connection* conn) override;
packet_analysis::IP::SessionAdapter* MakeSessionAdapter(Connection* conn) override;
protected:
/**
* Parse the header from the packet into a ConnTuple object.
*/
bool BuildConnTuple(size_t len, const uint8_t* data, Packet* packet, ConnTuple& tuple) override;
/**
* Parse the header from the packet into a ConnTuple object.
*/
bool BuildConnTuple(size_t len, const uint8_t* data, Packet* packet, ConnTuple& tuple) override;
void DeliverPacket(Connection* c, double t, bool is_orig, int remaining, Packet* pkt) override;
void DeliverPacket(Connection* c, double t, bool is_orig, int remaining, Packet* pkt) override;
private:
void NextICMP4(double t, const struct icmp* icmpp, int len, int caplen, const u_char*& data,
const IP_Hdr* ip_hdr, ICMPSessionAdapter* adapter);
void NextICMP4(double t, const struct icmp* icmpp, int len, int caplen, const u_char*& data, const IP_Hdr* ip_hdr,
ICMPSessionAdapter* adapter);
void NextICMP6(double t, const struct icmp* icmpp, int len, int caplen, const u_char*& data,
const IP_Hdr* ip_hdr, ICMPSessionAdapter* adapter);
void NextICMP6(double t, const struct icmp* icmpp, int len, int caplen, const u_char*& data, const IP_Hdr* ip_hdr,
ICMPSessionAdapter* adapter);
void ICMP_Sent(const struct icmp* icmpp, int len, int caplen, int icmpv6, const u_char* data,
const IP_Hdr* ip_hdr, ICMPSessionAdapter* adapter);
void ICMP_Sent(const struct icmp* icmpp, int len, int caplen, int icmpv6, const u_char* data, const IP_Hdr* ip_hdr,
ICMPSessionAdapter* adapter);
void Echo(double t, const struct icmp* icmpp, int len, int caplen, const u_char*& data,
const IP_Hdr* ip_hdr, ICMPSessionAdapter* adapter);
void Redirect(double t, const struct icmp* icmpp, int len, int caplen, const u_char*& data,
const IP_Hdr* ip_hdr, ICMPSessionAdapter* adapter);
void RouterAdvert(double t, const struct icmp* icmpp, int len, int caplen, const u_char*& data,
const IP_Hdr* ip_hdr, ICMPSessionAdapter* adapter);
void NeighborAdvert(double t, const struct icmp* icmpp, int len, int caplen,
const u_char*& data, const IP_Hdr* ip_hdr, ICMPSessionAdapter* adapter);
void NeighborSolicit(double t, const struct icmp* icmpp, int len, int caplen,
const u_char*& data, const IP_Hdr* ip_hdr, ICMPSessionAdapter* adapter);
void RouterSolicit(double t, const struct icmp* icmpp, int len, int caplen, const u_char*& data,
const IP_Hdr* ip_hdr, ICMPSessionAdapter* adapter);
void Echo(double t, const struct icmp* icmpp, int len, int caplen, const u_char*& data, const IP_Hdr* ip_hdr,
ICMPSessionAdapter* adapter);
void Redirect(double t, const struct icmp* icmpp, int len, int caplen, const u_char*& data, const IP_Hdr* ip_hdr,
ICMPSessionAdapter* adapter);
void RouterAdvert(double t, const struct icmp* icmpp, int len, int caplen, const u_char*& data,
const IP_Hdr* ip_hdr, ICMPSessionAdapter* adapter);
void NeighborAdvert(double t, const struct icmp* icmpp, int len, int caplen, const u_char*& data,
const IP_Hdr* ip_hdr, ICMPSessionAdapter* adapter);
void NeighborSolicit(double t, const struct icmp* icmpp, int len, int caplen, const u_char*& data,
const IP_Hdr* ip_hdr, ICMPSessionAdapter* adapter);
void RouterSolicit(double t, const struct icmp* icmpp, int len, int caplen, const u_char*& data,
const IP_Hdr* ip_hdr, ICMPSessionAdapter* adapter);
RecordValPtr BuildInfo(const struct icmp* icmpp, int len, bool icmpv6, const IP_Hdr* ip_hdr);
RecordValPtr BuildInfo(const struct icmp* icmpp, int len, bool icmpv6, const IP_Hdr* ip_hdr);
RecordValPtr ExtractICMP4Context(int len, const u_char*& data);
RecordValPtr ExtractICMP4Context(int len, const u_char*& data);
void Context4(double t, const struct icmp* icmpp, int len, int caplen, const u_char*& data,
const IP_Hdr* ip_hdr, ICMPSessionAdapter* adapter);
void Context4(double t, const struct icmp* icmpp, int len, int caplen, const u_char*& data, const IP_Hdr* ip_hdr,
ICMPSessionAdapter* adapter);
TransportProto GetContextProtocol(const IP_Hdr* ip_hdr, uint32_t* src_port, uint32_t* dst_port);
TransportProto GetContextProtocol(const IP_Hdr* ip_hdr, uint32_t* src_port, uint32_t* dst_port);
RecordValPtr ExtractICMP6Context(int len, const u_char*& data);
RecordValPtr ExtractICMP6Context(int len, const u_char*& data);
void Context6(double t, const struct icmp* icmpp, int len, int caplen, const u_char*& data,
const IP_Hdr* ip_hdr, ICMPSessionAdapter* adapter);
void Context6(double t, const struct icmp* icmpp, int len, int caplen, const u_char*& data, const IP_Hdr* ip_hdr,
ICMPSessionAdapter* adapter);
// RFC 4861 Neighbor Discover message options
VectorValPtr BuildNDOptionsVal(int caplen, const u_char* data, ICMPSessionAdapter* adapter);
// RFC 4861 Neighbor Discover message options
VectorValPtr BuildNDOptionsVal(int caplen, const u_char* data, ICMPSessionAdapter* adapter);
void UpdateEndpointVal(const ValPtr& endp, bool is_orig);
};
void UpdateEndpointVal(const ValPtr& endp, bool is_orig);
};
// Returns the counterpart type to the given type (e.g., the counterpart
// to ICMP_ECHOREPLY is ICMP_ECHO).
extern int ICMP4_counterpart(int icmp_type, int icmp_code, bool& is_one_way);
extern int ICMP6_counterpart(int icmp_type, int icmp_code, bool& is_one_way);
} // namespace packet_analysis::ICMP
} // namespace zeek
} // namespace packet_analysis::ICMP
} // namespace zeek

View file

@ -8,77 +8,66 @@
using namespace zeek::packet_analysis::ICMP;
using namespace zeek::packet_analysis::IP;
enum ICMP_EndpointState
{
ICMP_INACTIVE, // no packet seen
ICMP_ACTIVE, // packets seen
};
enum ICMP_EndpointState {
ICMP_INACTIVE, // no packet seen
ICMP_ACTIVE, // packets seen
};
void ICMPSessionAdapter::AddExtraAnalyzers(Connection* conn)
{
static zeek::Tag analyzer_connsize = analyzer_mgr->GetComponentTag("CONNSIZE");
void ICMPSessionAdapter::AddExtraAnalyzers(Connection* conn) {
static zeek::Tag analyzer_connsize = analyzer_mgr->GetComponentTag("CONNSIZE");
if ( analyzer_mgr->IsEnabled(analyzer_connsize) )
// Add ConnSize analyzer. Needs to see packets, not stream.
AddChildAnalyzer(new analyzer::conn_size::ConnSize_Analyzer(conn));
}
if ( analyzer_mgr->IsEnabled(analyzer_connsize) )
// Add ConnSize analyzer. Needs to see packets, not stream.
AddChildAnalyzer(new analyzer::conn_size::ConnSize_Analyzer(conn));
}
void ICMPSessionAdapter::UpdateConnVal(zeek::RecordVal* conn_val)
{
const auto& orig_endp = conn_val->GetField("orig");
const auto& resp_endp = conn_val->GetField("resp");
void ICMPSessionAdapter::UpdateConnVal(zeek::RecordVal* conn_val) {
const auto& orig_endp = conn_val->GetField("orig");
const auto& resp_endp = conn_val->GetField("resp");
UpdateEndpointVal(orig_endp, true);
UpdateEndpointVal(resp_endp, false);
UpdateEndpointVal(orig_endp, true);
UpdateEndpointVal(resp_endp, false);
analyzer::Analyzer::UpdateConnVal(conn_val);
}
analyzer::Analyzer::UpdateConnVal(conn_val);
}
void ICMPSessionAdapter::UpdateEndpointVal(const ValPtr& endp_arg, bool is_orig)
{
Conn()->EnableStatusUpdateTimer();
void ICMPSessionAdapter::UpdateEndpointVal(const ValPtr& endp_arg, bool is_orig) {
Conn()->EnableStatusUpdateTimer();
int size = is_orig ? request_len : reply_len;
auto endp = endp_arg->AsRecordVal();
int size = is_orig ? request_len : reply_len;
auto endp = endp_arg->AsRecordVal();
if ( size < 0 )
{
endp->Assign(0, val_mgr->Count(0));
endp->Assign(1, val_mgr->Count(int(ICMP_INACTIVE)));
}
else
{
endp->Assign(0, val_mgr->Count(size));
endp->Assign(1, val_mgr->Count(int(ICMP_ACTIVE)));
}
}
if ( size < 0 ) {
endp->Assign(0, val_mgr->Count(0));
endp->Assign(1, val_mgr->Count(int(ICMP_INACTIVE)));
}
else {
endp->Assign(0, val_mgr->Count(size));
endp->Assign(1, val_mgr->Count(int(ICMP_ACTIVE)));
}
}
void ICMPSessionAdapter::UpdateLength(bool is_orig, int len)
{
int& len_stat = is_orig ? request_len : reply_len;
if ( len_stat < 0 )
len_stat = len;
else
len_stat += len;
}
void ICMPSessionAdapter::UpdateLength(bool is_orig, int len) {
int& len_stat = is_orig ? request_len : reply_len;
if ( len_stat < 0 )
len_stat = len;
else
len_stat += len;
}
void ICMPSessionAdapter::InitEndpointMatcher(const IP_Hdr* ip_hdr, int len, bool is_orig)
{
if ( zeek::detail::rule_matcher )
{
if ( ! matcher_state.MatcherInitialized(is_orig) )
matcher_state.InitEndpointMatcher(this, ip_hdr, len, is_orig, nullptr);
}
}
void ICMPSessionAdapter::InitEndpointMatcher(const IP_Hdr* ip_hdr, int len, bool is_orig) {
if ( zeek::detail::rule_matcher ) {
if ( ! matcher_state.MatcherInitialized(is_orig) )
matcher_state.InitEndpointMatcher(this, ip_hdr, len, is_orig, nullptr);
}
}
void ICMPSessionAdapter::MatchEndpoint(const u_char* data, int len, bool is_orig)
{
if ( zeek::detail::rule_matcher )
matcher_state.Match(zeek::detail::Rule::PAYLOAD, data, len, is_orig, false, false, true);
}
void ICMPSessionAdapter::MatchEndpoint(const u_char* data, int len, bool is_orig) {
if ( zeek::detail::rule_matcher )
matcher_state.Match(zeek::detail::Rule::PAYLOAD, data, len, is_orig, false, false, true);
}
void ICMPSessionAdapter::Done()
{
SessionAdapter::Done();
matcher_state.FinishEndpointMatcher();
}
void ICMPSessionAdapter::Done() {
SessionAdapter::Done();
matcher_state.FinishEndpointMatcher();
}

View file

@ -5,29 +5,26 @@
#include "zeek/RuleMatcher.h"
#include "zeek/packet_analysis/protocol/ip/SessionAdapter.h"
namespace zeek::packet_analysis::ICMP
{
class ICMPSessionAdapter final : public IP::SessionAdapter
{
namespace zeek::packet_analysis::ICMP {
class ICMPSessionAdapter final : public IP::SessionAdapter {
public:
ICMPSessionAdapter(Connection* conn) : IP::SessionAdapter("ICMP", conn) { }
ICMPSessionAdapter(Connection* conn) : IP::SessionAdapter("ICMP", conn) {}
void AddExtraAnalyzers(Connection* conn) override;
void UpdateConnVal(RecordVal* conn_val) override;
void UpdateEndpointVal(const ValPtr& endp, bool is_orig);
void AddExtraAnalyzers(Connection* conn) override;
void UpdateConnVal(RecordVal* conn_val) override;
void UpdateEndpointVal(const ValPtr& endp, bool is_orig);
void UpdateLength(bool is_orig, int len);
void Done() override;
void UpdateLength(bool is_orig, int len);
void Done() override;
void InitEndpointMatcher(const IP_Hdr* ip_hdr, int len, bool is_orig);
void MatchEndpoint(const u_char* data, int len, bool is_orig);
void InitEndpointMatcher(const IP_Hdr* ip_hdr, int len, bool is_orig);
void MatchEndpoint(const u_char* data, int len, bool is_orig);
private:
detail::RuleMatcherState matcher_state;
int request_len = -1;
int reply_len = -1;
};
detail::RuleMatcherState matcher_state;
int request_len = -1;
int reply_len = -1;
};
} // namespace zeek::packet_analysis::ICMP
} // namespace zeek::packet_analysis::ICMP

View file

@ -7,24 +7,21 @@
#include "zeek/packet_analysis/protocol/icmp/ICMP.h"
#include "zeek/packet_analysis/protocol/icmp/ICMPSessionAdapter.h"
namespace zeek::plugin::Zeek_ICMP
{
namespace zeek::plugin::Zeek_ICMP {
class Plugin final : public zeek::plugin::Plugin
{
class Plugin final : public zeek::plugin::Plugin {
public:
zeek::plugin::Configuration Configure() override
{
AddComponent(new zeek::packet_analysis::Component(
"ICMP", zeek::packet_analysis::ICMP::ICMPAnalyzer::Instantiate));
AddComponent(new zeek::analyzer::Component("ICMP", nullptr, 0, true, false, true));
zeek::plugin::Configuration Configure() override {
AddComponent(
new zeek::packet_analysis::Component("ICMP", zeek::packet_analysis::ICMP::ICMPAnalyzer::Instantiate));
AddComponent(new zeek::analyzer::Component("ICMP", nullptr, 0, true, false, true));
zeek::plugin::Configuration config;
config.name = "Zeek::ICMP";
config.description = "Packet analyzer for ICMP";
return config;
}
zeek::plugin::Configuration config;
config.name = "Zeek::ICMP";
config.description = "Packet analyzer for ICMP";
return config;
}
} plugin;
} plugin;
}
} // namespace zeek::plugin::Zeek_ICMP

View file

@ -4,179 +4,160 @@
using namespace zeek::packet_analysis::IEEE802_11;
IEEE802_11Analyzer::IEEE802_11Analyzer() : zeek::packet_analysis::Analyzer("IEEE802_11") { }
IEEE802_11Analyzer::IEEE802_11Analyzer() : zeek::packet_analysis::Analyzer("IEEE802_11") {}
bool IEEE802_11Analyzer::AnalyzePacket(size_t len, const uint8_t* data, Packet* packet)
{
u_char len_80211 = 24; // minimal length of data frames
bool IEEE802_11Analyzer::AnalyzePacket(size_t len, const uint8_t* data, Packet* packet) {
u_char len_80211 = 24; // minimal length of data frames
if ( len_80211 >= len )
{
Weird("truncated_802_11_header", packet);
return false;
}
if ( len_80211 >= len ) {
Weird("truncated_802_11_header", packet);
return false;
}
u_char fc_80211 = data[0]; // Frame Control field
bool is_amsdu = false;
u_char fc_80211 = data[0]; // Frame Control field
bool is_amsdu = false;
// Skip non-data frame types (management & control).
if ( ! ((fc_80211 >> 2) & 0x02) )
return false;
// Skip non-data frame types (management & control).
if ( ! ((fc_80211 >> 2) & 0x02) )
return false;
// Skip subtypes without data.
if ( (fc_80211 >> 4) & 0x04 )
return false;
// Skip subtypes without data.
if ( (fc_80211 >> 4) & 0x04 )
return false;
// 'To DS' and 'From DS' flags set indicate use of the 4th address field.
if ( (data[1] & 0x03) == 0x03 )
len_80211 += packet->L2_ADDR_LEN;
// 'To DS' and 'From DS' flags set indicate use of the 4th address field.
if ( (data[1] & 0x03) == 0x03 )
len_80211 += packet->L2_ADDR_LEN;
if ( len_80211 >= len )
{
Weird("truncated_802_11_header", packet);
return false;
}
if ( len_80211 >= len ) {
Weird("truncated_802_11_header", packet);
return false;
}
// Look for the QoS indicator bit.
if ( (fc_80211 >> 4) & 0x08 )
{
// Store off whether this is an A-MSDU header, which indicates that there are
// multiple packets following the 802.11 header.
is_amsdu = (data[len_80211] & 0x80) == 0x80;
// Look for the QoS indicator bit.
if ( (fc_80211 >> 4) & 0x08 ) {
// Store off whether this is an A-MSDU header, which indicates that there are
// multiple packets following the 802.11 header.
is_amsdu = (data[len_80211] & 0x80) == 0x80;
// Check for the protected bit. This means the data is encrypted and we can't
// do anything with it.
if ( data[1] & 0x40 )
return true;
// Check for the protected bit. This means the data is encrypted and we can't
// do anything with it.
if ( data[1] & 0x40 )
return true;
len_80211 += 2;
}
len_80211 += 2;
}
if ( len_80211 >= len )
{
Weird("truncated_802_11_header", packet);
return false;
}
if ( len_80211 >= len ) {
Weird("truncated_802_11_header", packet);
return false;
}
// Determine link-layer addresses based on 'To DS' and 'From DS' flags
switch ( data[1] & 0x03 )
{
case 0x00:
packet->l2_src = data + 10;
packet->l2_dst = data + 4;
break;
// Determine link-layer addresses based on 'To DS' and 'From DS' flags
switch ( data[1] & 0x03 ) {
case 0x00:
packet->l2_src = data + 10;
packet->l2_dst = data + 4;
break;
case 0x01:
packet->l2_src = data + 10;
packet->l2_dst = data + 16;
break;
case 0x01:
packet->l2_src = data + 10;
packet->l2_dst = data + 16;
break;
case 0x02:
packet->l2_src = data + 16;
packet->l2_dst = data + 4;
break;
case 0x02:
packet->l2_src = data + 16;
packet->l2_dst = data + 4;
break;
case 0x03:
packet->l2_src = data + 24;
packet->l2_dst = data + 16;
break;
}
case 0x03:
packet->l2_src = data + 24;
packet->l2_dst = data + 16;
break;
}
// skip the 802.11 data header
data += len_80211;
len -= len_80211;
// skip the 802.11 data header
data += len_80211;
len -= len_80211;
if ( ! is_amsdu )
{
return HandleInnerPacket(len, data, packet);
}
else
{
size_t amsdu_padding = 0;
size_t encap_index = packet->encap ? packet->encap->Depth() : 0;
if ( ! is_amsdu ) {
return HandleInnerPacket(len, data, packet);
}
else {
size_t amsdu_padding = 0;
size_t encap_index = packet->encap ? packet->encap->Depth() : 0;
while ( len > 0 )
{
if ( len < 14 )
{
Weird("truncated_802_11_amsdu_header", packet);
return false;
}
while ( len > 0 ) {
if ( len < 14 ) {
Weird("truncated_802_11_amsdu_header", packet);
return false;
}
// This is the length of everything after the A-MSDU subframe header.
size_t amsdu_len = (data[12] << 8) + data[13];
if ( len < amsdu_len + 14 )
{
Weird("truncated_802_11_amsdu_packet", packet);
return false;
}
// This is the length of everything after the A-MSDU subframe header.
size_t amsdu_len = (data[12] << 8) + data[13];
if ( len < amsdu_len + 14 ) {
Weird("truncated_802_11_amsdu_packet", packet);
return false;
}
// Skip the A-MSDU subframe header. This should place us at the start of an LLC header.
data += 14;
len -= 14;
// Skip the A-MSDU subframe header. This should place us at the start of an LLC header.
data += 14;
len -= 14;
if ( ! HandleInnerPacket(amsdu_len, data, packet) )
{
Weird("invalid_802_11_amsdu_inner_packet", packet);
return false;
}
if ( ! HandleInnerPacket(amsdu_len, data, packet) ) {
Weird("invalid_802_11_amsdu_inner_packet", packet);
return false;
}
data += amsdu_len;
len -= amsdu_len;
data += amsdu_len;
len -= amsdu_len;
// Each A-MSDU subframe is padded by up to 3 bytes to make a multiple of 4. This padding
// isn't included in the length field value. The padding also doesn't happen with the
// last subframe, so check to see that we can even subtract it. Unfortunately, there
// isn't a frame counter in the header so we just have trust that it all works out.
amsdu_padding = amsdu_len % 4;
if ( len >= amsdu_padding )
{
data += amsdu_padding;
len -= amsdu_padding;
}
// Each A-MSDU subframe is padded by up to 3 bytes to make a multiple of 4. This padding
// isn't included in the length field value. The padding also doesn't happen with the
// last subframe, so check to see that we can even subtract it. Unfortunately, there
// isn't a frame counter in the header so we just have trust that it all works out.
amsdu_padding = amsdu_len % 4;
if ( len >= amsdu_padding ) {
data += amsdu_padding;
len -= amsdu_padding;
}
// Pop encapsuations back up to the level where we started processing so that the next
// subframe gets the same encapsulation stack.
if ( packet->encap )
{
while ( packet->encap->Depth() > encap_index )
packet->encap->Pop();
}
}
// Pop encapsuations back up to the level where we started processing so that the next
// subframe gets the same encapsulation stack.
if ( packet->encap ) {
while ( packet->encap->Depth() > encap_index )
packet->encap->Pop();
}
}
return true;
}
}
return true;
}
}
bool IEEE802_11Analyzer::HandleInnerPacket(size_t len, const uint8_t* data, Packet* packet) const
{
// Make sure there's room for an LLC header.
if ( len < 8 )
{
Weird("truncated_802_11_llc_header", packet);
return false;
}
bool IEEE802_11Analyzer::HandleInnerPacket(size_t len, const uint8_t* data, Packet* packet) const {
// Make sure there's room for an LLC header.
if ( len < 8 ) {
Weird("truncated_802_11_llc_header", packet);
return false;
}
// Check that the DSAP and SSAP are both SNAP and that the control field indicates that this is
// an unnumbered frame. The organization code (24bits) needs to also be zero to indicate that
// this is encapsulated ethernet.
if ( data[0] == 0xAA && data[1] == 0xAA && data[2] == 0x03 && data[3] == 0 && data[4] == 0 &&
data[5] == 0 )
{
data += 6;
len -= 6;
}
else
{
// If this is a logical link control frame without the possibility of having a protocol we
// care about, we'll just skip it for now.
return false;
}
// Check that the DSAP and SSAP are both SNAP and that the control field indicates that this is
// an unnumbered frame. The organization code (24bits) needs to also be zero to indicate that
// this is encapsulated ethernet.
if ( data[0] == 0xAA && data[1] == 0xAA && data[2] == 0x03 && data[3] == 0 && data[4] == 0 && data[5] == 0 ) {
data += 6;
len -= 6;
}
else {
// If this is a logical link control frame without the possibility of having a protocol we
// care about, we'll just skip it for now.
return false;
}
// Get the protocol and skip the rest of the LLC header.
uint32_t protocol = (data[0] << 8) + data[1];
data += 2;
len -= 2;
// Get the protocol and skip the rest of the LLC header.
uint32_t protocol = (data[0] << 8) + data[1];
data += 2;
len -= 2;
return ForwardPacket(len, data, packet, protocol);
}
return ForwardPacket(len, data, packet, protocol);
}

View file

@ -5,24 +5,19 @@
#include "zeek/packet_analysis/Analyzer.h"
#include "zeek/packet_analysis/Component.h"
namespace zeek::packet_analysis::IEEE802_11
{
namespace zeek::packet_analysis::IEEE802_11 {
class IEEE802_11Analyzer : public Analyzer
{
class IEEE802_11Analyzer : public Analyzer {
public:
IEEE802_11Analyzer();
~IEEE802_11Analyzer() override = default;
IEEE802_11Analyzer();
~IEEE802_11Analyzer() override = default;
bool AnalyzePacket(size_t len, const uint8_t* data, Packet* packet) override;
bool AnalyzePacket(size_t len, const uint8_t* data, Packet* packet) override;
static zeek::packet_analysis::AnalyzerPtr Instantiate()
{
return std::make_shared<IEEE802_11Analyzer>();
}
static zeek::packet_analysis::AnalyzerPtr Instantiate() { return std::make_shared<IEEE802_11Analyzer>(); }
private:
bool HandleInnerPacket(size_t len, const uint8_t* data, Packet* packet) const;
};
bool HandleInnerPacket(size_t len, const uint8_t* data, Packet* packet) const;
};
}
} // namespace zeek::packet_analysis::IEEE802_11

View file

@ -5,23 +5,21 @@
#include "zeek/packet_analysis/Component.h"
#include "zeek/packet_analysis/protocol/ieee802_11/IEEE802_11.h"
namespace zeek::plugin::Zeek_IEEE802_11
{
namespace zeek::plugin::Zeek_IEEE802_11 {
class Plugin final : public zeek::plugin::Plugin
{
class Plugin final : public zeek::plugin::Plugin {
public:
zeek::plugin::Configuration Configure() override
{
AddComponent(new zeek::packet_analysis::Component(
"IEEE802_11", zeek::packet_analysis::IEEE802_11::IEEE802_11Analyzer::Instantiate));
zeek::plugin::Configuration Configure() override {
AddComponent(
new zeek::packet_analysis::Component("IEEE802_11",
zeek::packet_analysis::IEEE802_11::IEEE802_11Analyzer::Instantiate));
zeek::plugin::Configuration config;
config.name = "Zeek::IEEE802_11";
config.description = "IEEE 802.11 packet analyzer";
return config;
}
zeek::plugin::Configuration config;
config.name = "Zeek::IEEE802_11";
config.description = "IEEE 802.11 packet analyzer";
return config;
}
} plugin;
} plugin;
}
} // namespace zeek::plugin::Zeek_IEEE802_11

View file

@ -6,27 +6,21 @@
using namespace zeek::packet_analysis::IEEE802_11_Radio;
IEEE802_11_RadioAnalyzer::IEEE802_11_RadioAnalyzer()
: zeek::packet_analysis::Analyzer("IEEE802_11_Radio")
{
}
IEEE802_11_RadioAnalyzer::IEEE802_11_RadioAnalyzer() : zeek::packet_analysis::Analyzer("IEEE802_11_Radio") {}
bool IEEE802_11_RadioAnalyzer::AnalyzePacket(size_t len, const uint8_t* data, Packet* packet)
{
if ( 3 >= len )
{
Weird("truncated_radiotap_header", packet);
return false;
}
bool IEEE802_11_RadioAnalyzer::AnalyzePacket(size_t len, const uint8_t* data, Packet* packet) {
if ( 3 >= len ) {
Weird("truncated_radiotap_header", packet);
return false;
}
// Skip over the RadioTap header
size_t rtheader_len = (data[3] << 8) + data[2];
// Skip over the RadioTap header
size_t rtheader_len = (data[3] << 8) + data[2];
if ( rtheader_len >= len )
{
Weird("truncated_radiotap_header", packet);
return false;
}
if ( rtheader_len >= len ) {
Weird("truncated_radiotap_header", packet);
return false;
}
return ForwardPacket(len - rtheader_len, data + rtheader_len, packet, DLT_IEEE802_11);
}
return ForwardPacket(len - rtheader_len, data + rtheader_len, packet, DLT_IEEE802_11);
}

View file

@ -5,21 +5,16 @@
#include "zeek/packet_analysis/Analyzer.h"
#include "zeek/packet_analysis/Component.h"
namespace zeek::packet_analysis::IEEE802_11_Radio
{
namespace zeek::packet_analysis::IEEE802_11_Radio {
class IEEE802_11_RadioAnalyzer : public Analyzer
{
class IEEE802_11_RadioAnalyzer : public Analyzer {
public:
IEEE802_11_RadioAnalyzer();
~IEEE802_11_RadioAnalyzer() override = default;
IEEE802_11_RadioAnalyzer();
~IEEE802_11_RadioAnalyzer() override = default;
bool AnalyzePacket(size_t len, const uint8_t* data, Packet* packet) override;
bool AnalyzePacket(size_t len, const uint8_t* data, Packet* packet) override;
static zeek::packet_analysis::AnalyzerPtr Instantiate()
{
return std::make_shared<IEEE802_11_RadioAnalyzer>();
}
};
static zeek::packet_analysis::AnalyzerPtr Instantiate() { return std::make_shared<IEEE802_11_RadioAnalyzer>(); }
};
}
} // namespace zeek::packet_analysis::IEEE802_11_Radio

View file

@ -5,23 +5,19 @@
#include "zeek/packet_analysis/Component.h"
#include "zeek/packet_analysis/protocol/ieee802_11_radio/IEEE802_11_Radio.h"
namespace zeek::plugin::Zeek_IEEE802_11_Radio
{
namespace zeek::plugin::Zeek_IEEE802_11_Radio {
class Plugin final : public zeek::plugin::Plugin
{
class Plugin final : public zeek::plugin::Plugin {
public:
zeek::plugin::Configuration Configure() override
{
AddComponent(new zeek::packet_analysis::Component(
"IEEE802_11_Radio",
zeek::packet_analysis::IEEE802_11_Radio::IEEE802_11_RadioAnalyzer::Instantiate));
zeek::plugin::Configuration Configure() override {
AddComponent(new zeek::packet_analysis::Component(
"IEEE802_11_Radio", zeek::packet_analysis::IEEE802_11_Radio::IEEE802_11_RadioAnalyzer::Instantiate));
zeek::plugin::Configuration config;
config.name = "Zeek::IEEE802_11_Radio";
config.description = "IEEE 802.11 Radiotap packet analyzer";
return config;
}
zeek::plugin::Configuration config;
config.name = "Zeek::IEEE802_11_Radio";
config.description = "IEEE 802.11 Radiotap packet analyzer";
return config;
}
} plugin;
}
} plugin;
} // namespace zeek::plugin::Zeek_IEEE802_11_Radio

View file

@ -18,326 +18,288 @@
using namespace zeek::packet_analysis::IP;
IPAnalyzer::IPAnalyzer() : zeek::packet_analysis::Analyzer("IP")
{
discarder = new detail::Discarder();
if ( ! discarder->IsActive() )
{
delete discarder;
discarder = nullptr;
}
}
IPAnalyzer::IPAnalyzer() : zeek::packet_analysis::Analyzer("IP") {
discarder = new detail::Discarder();
if ( ! discarder->IsActive() ) {
delete discarder;
discarder = nullptr;
}
}
IPAnalyzer::~IPAnalyzer()
{
delete discarder;
}
IPAnalyzer::~IPAnalyzer() { delete discarder; }
bool IPAnalyzer::AnalyzePacket(size_t len, const uint8_t* data, Packet* packet)
{
// Check to make sure we have enough data left for an IP header to be here. Note we only
// check ipv4 here. We'll check ipv6 later once we determine we have an ipv6 header.
if ( len < sizeof(struct ip) )
{
Weird("truncated_IP", packet);
return false;
}
bool IPAnalyzer::AnalyzePacket(size_t len, const uint8_t* data, Packet* packet) {
// Check to make sure we have enough data left for an IP header to be here. Note we only
// check ipv4 here. We'll check ipv6 later once we determine we have an ipv6 header.
if ( len < sizeof(struct ip) ) {
Weird("truncated_IP", packet);
return false;
}
int32_t hdr_size = static_cast<int32_t>(data - packet->data);
int32_t hdr_size = static_cast<int32_t>(data - packet->data);
// Cast the current data pointer to an IP header pointer so we can use it to get some
// data about the header.
auto ip = (const struct ip*)data;
uint32_t protocol = ip->ip_v;
std::shared_ptr<IP_Hdr> ip_hdr;
// Cast the current data pointer to an IP header pointer so we can use it to get some
// data about the header.
auto ip = (const struct ip*)data;
uint32_t protocol = ip->ip_v;
std::shared_ptr<IP_Hdr> ip_hdr;
if ( protocol == 4 )
{
ip_hdr = std::make_shared<IP_Hdr>(ip, false);
packet->l3_proto = L3_IPV4;
}
else if ( protocol == 6 )
{
if ( len < sizeof(struct ip6_hdr) )
{
Weird("truncated_IP", packet);
return false;
}
if ( protocol == 4 ) {
ip_hdr = std::make_shared<IP_Hdr>(ip, false);
packet->l3_proto = L3_IPV4;
}
else if ( protocol == 6 ) {
if ( len < sizeof(struct ip6_hdr) ) {
Weird("truncated_IP", packet);
return false;
}
ip_hdr = std::make_shared<IP_Hdr>((const struct ip6_hdr*)data, false,
static_cast<int>(len));
packet->l3_proto = L3_IPV6;
}
else
{
Weird("unknown_ip_version", packet);
return false;
}
ip_hdr = std::make_shared<IP_Hdr>((const struct ip6_hdr*)data, false, static_cast<int>(len));
packet->l3_proto = L3_IPV6;
}
else {
Weird("unknown_ip_version", packet);
return false;
}
// TotalLen() returns the full length of the IP portion of the packet, including
// the IP header and payload.
uint32_t total_len = ip_hdr->TotalLen();
if ( total_len == 0 )
{
// TCP segmentation offloading can zero out the ip_len field.
Weird("ip_hdr_len_zero", packet);
// TotalLen() returns the full length of the IP portion of the packet, including
// the IP header and payload.
uint32_t total_len = ip_hdr->TotalLen();
if ( total_len == 0 ) {
// TCP segmentation offloading can zero out the ip_len field.
Weird("ip_hdr_len_zero", packet);
if ( detail::ignore_checksums )
// Cope with the zero'd out ip_len field by using the caplen.
total_len = packet->cap_len - hdr_size;
else
// If this is caused by segmentation offloading, the checksum will
// also be incorrect. If checksum validation is enabled - just bail here.
return false;
}
if ( detail::ignore_checksums )
// Cope with the zero'd out ip_len field by using the caplen.
total_len = packet->cap_len - hdr_size;
else
// If this is caused by segmentation offloading, the checksum will
// also be incorrect. If checksum validation is enabled - just bail here.
return false;
}
if ( packet->len < total_len + hdr_size )
{
Weird("truncated_IP_len", packet);
return false;
}
if ( packet->len < total_len + hdr_size ) {
Weird("truncated_IP_len", packet);
return false;
}
// For both of these it is safe to pass ip_hdr because the presence
// is guaranteed for the functions that pass data to us.
uint16_t ip_hdr_len = ip_hdr->HdrLen();
if ( ip_hdr_len > total_len )
{
Weird("invalid_IP_header_size", packet);
return false;
}
// For both of these it is safe to pass ip_hdr because the presence
// is guaranteed for the functions that pass data to us.
uint16_t ip_hdr_len = ip_hdr->HdrLen();
if ( ip_hdr_len > total_len ) {
Weird("invalid_IP_header_size", packet);
return false;
}
if ( ip_hdr_len > len )
{
Weird("internally_truncated_header", packet);
return false;
}
if ( ip_hdr_len > len ) {
Weird("internally_truncated_header", packet);
return false;
}
const struct ip* ip4 = ip_hdr->IP4_Hdr();
const struct ip* ip4 = ip_hdr->IP4_Hdr();
if ( ip4 )
{
if ( ip_hdr_len < sizeof(struct ip) )
{
Weird("IPv4_min_header_size", packet);
return false;
}
}
else
{
if ( ip_hdr_len < sizeof(struct ip6_hdr) )
{
Weird("IPv6_min_header_size", packet);
return false;
}
}
if ( ip4 ) {
if ( ip_hdr_len < sizeof(struct ip) ) {
Weird("IPv4_min_header_size", packet);
return false;
}
}
else {
if ( ip_hdr_len < sizeof(struct ip6_hdr) ) {
Weird("IPv6_min_header_size", packet);
return false;
}
}
// If we got here, the IP_Hdr is most likely valid and safe to use.
packet->ip_hdr = ip_hdr;
// If we got here, the IP_Hdr is most likely valid and safe to use.
packet->ip_hdr = ip_hdr;
// If there's an encapsulation stack in this packet, meaning this packet is part of a chain
// of tunnels, make sure to store the IP header in the last flow in the stack so it can be
// used by previous analyzers as we return up the chain.
if ( packet->encap )
{
if ( auto* ec = packet->encap->Last() )
ec->ip_hdr = packet->ip_hdr;
}
// If there's an encapsulation stack in this packet, meaning this packet is part of a chain
// of tunnels, make sure to store the IP header in the last flow in the stack so it can be
// used by previous analyzers as we return up the chain.
if ( packet->encap ) {
if ( auto* ec = packet->encap->Last() )
ec->ip_hdr = packet->ip_hdr;
}
// Ignore if packet matches packet filter.
detail::PacketFilter* packet_filter = packet_mgr->GetPacketFilter(false);
if ( packet_filter && packet_filter->Match(packet->ip_hdr, total_len, len) )
return false;
// Ignore if packet matches packet filter.
detail::PacketFilter* packet_filter = packet_mgr->GetPacketFilter(false);
if ( packet_filter && packet_filter->Match(packet->ip_hdr, total_len, len) )
return false;
if ( ! packet->l3_checksummed && ! detail::ignore_checksums && ip4 &&
! IPBasedAnalyzer::GetIgnoreChecksumsNets()->Contains(packet->ip_hdr->IPHeaderSrcAddr()) &&
detail::in_cksum(reinterpret_cast<const uint8_t*>(ip4), ip_hdr_len) != 0xffff )
{
Weird("bad_IP_checksum", packet);
return false;
}
if ( ! packet->l3_checksummed && ! detail::ignore_checksums && ip4 &&
! IPBasedAnalyzer::GetIgnoreChecksumsNets()->Contains(packet->ip_hdr->IPHeaderSrcAddr()) &&
detail::in_cksum(reinterpret_cast<const uint8_t*>(ip4), ip_hdr_len) != 0xffff ) {
Weird("bad_IP_checksum", packet);
return false;
}
if ( discarder && discarder->NextPacket(packet->ip_hdr, total_len, len) )
return false;
if ( discarder && discarder->NextPacket(packet->ip_hdr, total_len, len) )
return false;
detail::FragReassembler* f = nullptr;
detail::FragReassembler* f = nullptr;
// Store this off so that it can be reset back to the original value before returning from
// this method.
size_t orig_cap_len = packet->cap_len;
// Store this off so that it can be reset back to the original value before returning from
// this method.
size_t orig_cap_len = packet->cap_len;
if ( packet->ip_hdr->IsFragment() )
{
packet->dump_packet = true; // always record fragments
if ( packet->ip_hdr->IsFragment() ) {
packet->dump_packet = true; // always record fragments
if ( len < total_len )
{
Weird("incompletely_captured_fragment", packet);
if ( len < total_len ) {
Weird("incompletely_captured_fragment", packet);
// Don't try to reassemble, that's doomed.
// Discard all except the first fragment (which
// is useful in analyzing header-only traces)
if ( packet->ip_hdr->FragOffset() != 0 )
return false;
}
else
{
f = detail::fragment_mgr->NextFragment(run_state::processing_start_time, packet->ip_hdr,
packet->data + hdr_size);
std::shared_ptr<IP_Hdr> ih = f->ReassembledPkt();
// Don't try to reassemble, that's doomed.
// Discard all except the first fragment (which
// is useful in analyzing header-only traces)
if ( packet->ip_hdr->FragOffset() != 0 )
return false;
}
else {
f = detail::fragment_mgr->NextFragment(run_state::processing_start_time, packet->ip_hdr,
packet->data + hdr_size);
std::shared_ptr<IP_Hdr> ih = f->ReassembledPkt();
if ( ! ih )
// It didn't reassemble into anything yet.
return true;
if ( ! ih )
// It didn't reassemble into anything yet.
return true;
ip4 = ih->IP4_Hdr();
ip4 = ih->IP4_Hdr();
// Switch the stored ip header over to the one from the
// fragmented packet.
packet->ip_hdr = std::move(ih);
// Switch the stored ip header over to the one from the
// fragmented packet.
packet->ip_hdr = std::move(ih);
len = total_len = packet->ip_hdr->TotalLen();
ip_hdr_len = packet->ip_hdr->HdrLen();
len = total_len = packet->ip_hdr->TotalLen();
ip_hdr_len = packet->ip_hdr->HdrLen();
if ( ip_hdr_len > total_len )
{
Weird("invalid_IP_header_size", packet);
return false;
}
if ( ip_hdr_len > total_len ) {
Weird("invalid_IP_header_size", packet);
return false;
}
packet->cap_len = total_len + hdr_size;
// Assumes reassembled packet has wire length == capture length.
packet->len = packet->cap_len;
}
}
packet->cap_len = total_len + hdr_size;
// Assumes reassembled packet has wire length == capture length.
packet->len = packet->cap_len;
}
}
detail::FragReassemblerTracker frt(f);
detail::FragReassemblerTracker frt(f);
// We stop building the chain when seeing IPPROTO_ESP so if it's
// there, it's always the last.
if ( packet->ip_hdr->LastHeader() == IPPROTO_ESP )
{
packet->dump_packet = true;
if ( esp_packet )
event_mgr.Enqueue(esp_packet, packet->ip_hdr->ToPktHdrVal());
// We stop building the chain when seeing IPPROTO_ESP so if it's
// there, it's always the last.
if ( packet->ip_hdr->LastHeader() == IPPROTO_ESP ) {
packet->dump_packet = true;
if ( esp_packet )
event_mgr.Enqueue(esp_packet, packet->ip_hdr->ToPktHdrVal());
// Can't do more since upper-layer payloads are going to be encrypted.
packet->cap_len = orig_cap_len;
return true;
}
// Can't do more since upper-layer payloads are going to be encrypted.
packet->cap_len = orig_cap_len;
return true;
}
// We stop building the chain when seeing IPPROTO_MOBILITY so it's always
// last if present.
if ( packet->ip_hdr->LastHeader() == IPPROTO_MOBILITY )
{
packet->dump_packet = true;
// We stop building the chain when seeing IPPROTO_MOBILITY so it's always
// last if present.
if ( packet->ip_hdr->LastHeader() == IPPROTO_MOBILITY ) {
packet->dump_packet = true;
if ( ! detail::ignore_checksums &&
mobility_header_checksum(packet->ip_hdr.get()) != 0xffff )
{
Weird("bad_MH_checksum", packet);
packet->cap_len = orig_cap_len;
return false;
}
if ( ! detail::ignore_checksums && mobility_header_checksum(packet->ip_hdr.get()) != 0xffff ) {
Weird("bad_MH_checksum", packet);
packet->cap_len = orig_cap_len;
return false;
}
if ( mobile_ipv6_message )
event_mgr.Enqueue(mobile_ipv6_message, packet->ip_hdr->ToPktHdrVal());
if ( mobile_ipv6_message )
event_mgr.Enqueue(mobile_ipv6_message, packet->ip_hdr->ToPktHdrVal());
if ( packet->ip_hdr->NextProto() != IPPROTO_NONE )
Weird("mobility_piggyback", packet);
if ( packet->ip_hdr->NextProto() != IPPROTO_NONE )
Weird("mobility_piggyback", packet);
packet->cap_len = orig_cap_len;
return true;
}
packet->cap_len = orig_cap_len;
return true;
}
// Set the data pointer to match the payload from the IP header. This makes sure that it's also
// pointing at the reassembled data for a fragmented packet.
data = packet->ip_hdr->Payload();
len -= ip_hdr_len;
// Set the data pointer to match the payload from the IP header. This makes sure that it's also
// pointing at the reassembled data for a fragmented packet.
data = packet->ip_hdr->Payload();
len -= ip_hdr_len;
// Session analysis assumes that the header size stored in the packet does not include the IP
// header size. There are two reasons for this: 1) Packet::ToRawPktHdrVal() wants to look at the
// IP header for reporting, and 2) The VXLAN analyzer uses the header position to create the
// next packet in the tunnel chain. Once the TCP/UDP work is done and the VXLAN analyzer can
// move into packet analysis, this can change, but for now we leave it as it is.
// Session analysis assumes that the header size stored in the packet does not include the IP
// header size. There are two reasons for this: 1) Packet::ToRawPktHdrVal() wants to look at the
// IP header for reporting, and 2) The VXLAN analyzer uses the header position to create the
// next packet in the tunnel chain. Once the TCP/UDP work is done and the VXLAN analyzer can
// move into packet analysis, this can change, but for now we leave it as it is.
bool return_val = true;
int proto = packet->ip_hdr->NextProto();
bool return_val = true;
int proto = packet->ip_hdr->NextProto();
packet->proto = proto;
packet->proto = proto;
// Double check the lengths one more time before forwarding this on.
if ( total_len < packet->ip_hdr->HdrLen() )
{
Weird("bogus_IP_header_lengths", packet);
packet->cap_len = orig_cap_len;
return false;
}
// Double check the lengths one more time before forwarding this on.
if ( total_len < packet->ip_hdr->HdrLen() ) {
Weird("bogus_IP_header_lengths", packet);
packet->cap_len = orig_cap_len;
return false;
}
// If the next protocol is a tunneled type, set the tunnel_type field in the packet to IP
// so that it gets handled correctly.
if ( proto == IPPROTO_IPV4 || proto == IPPROTO_IPV6 )
packet->tunnel_type = BifEnum::Tunnel::IP;
// If the next protocol is a tunneled type, set the tunnel_type field in the packet to IP
// so that it gets handled correctly.
if ( proto == IPPROTO_IPV4 || proto == IPPROTO_IPV6 )
packet->tunnel_type = BifEnum::Tunnel::IP;
switch ( proto )
{
case IPPROTO_NONE:
// If the packet is encapsulated in Teredo, then it was a bubble and
// the Teredo analyzer may have raised an event for that, else we're
// not sure the reason for the No Next header in the packet.
if ( ! (packet->encap && packet->encap->LastType() == BifEnum::Tunnel::TEREDO) )
{
Weird("ipv6_no_next", packet);
return_val = false;
}
break;
default:
packet->proto = proto;
switch ( proto ) {
case IPPROTO_NONE:
// If the packet is encapsulated in Teredo, then it was a bubble and
// the Teredo analyzer may have raised an event for that, else we're
// not sure the reason for the No Next header in the packet.
if ( ! (packet->encap && packet->encap->LastType() == BifEnum::Tunnel::TEREDO) ) {
Weird("ipv6_no_next", packet);
return_val = false;
}
break;
default:
packet->proto = proto;
// For everything else, pass it on to another analyzer. If there's no one to handle
// that, it'll report a Weird.
return_val = ForwardPacket(len, data, packet, proto);
break;
}
// For everything else, pass it on to another analyzer. If there's no one to handle
// that, it'll report a Weird.
return_val = ForwardPacket(len, data, packet, proto);
break;
}
if ( f )
f->DeleteTimer();
if ( f )
f->DeleteTimer();
packet->cap_len = orig_cap_len;
return return_val;
}
packet->cap_len = orig_cap_len;
return return_val;
}
ParseResult zeek::packet_analysis::IP::ParsePacket(int caplen, const u_char* const pkt, int proto,
std::shared_ptr<zeek::IP_Hdr>& inner)
{
if ( proto == IPPROTO_IPV6 )
{
if ( caplen < (int)sizeof(struct ip6_hdr) )
return ParseResult::CaplenTooSmall;
std::shared_ptr<zeek::IP_Hdr>& inner) {
if ( proto == IPPROTO_IPV6 ) {
if ( caplen < (int)sizeof(struct ip6_hdr) )
return ParseResult::CaplenTooSmall;
const struct ip6_hdr* ip6 = (const struct ip6_hdr*)pkt;
inner = std::make_shared<zeek::IP_Hdr>(ip6, false, caplen);
if ( (ip6->ip6_ctlun.ip6_un2_vfc & 0xF0) != 0x60 )
return ParseResult::BadProtocol;
}
const struct ip6_hdr* ip6 = (const struct ip6_hdr*)pkt;
inner = std::make_shared<zeek::IP_Hdr>(ip6, false, caplen);
if ( (ip6->ip6_ctlun.ip6_un2_vfc & 0xF0) != 0x60 )
return ParseResult::BadProtocol;
}
else if ( proto == IPPROTO_IPV4 )
{
if ( caplen < (int)sizeof(struct ip) )
return ParseResult::BadProtocol;
else if ( proto == IPPROTO_IPV4 ) {
if ( caplen < (int)sizeof(struct ip) )
return ParseResult::BadProtocol;
const struct ip* ip4 = (const struct ip*)pkt;
inner = std::make_shared<zeek::IP_Hdr>(ip4, false);
if ( ip4->ip_v != 4 )
return ParseResult::BadProtocol;
}
else
{
return ParseResult::BadProtocol;
}
const struct ip* ip4 = (const struct ip*)pkt;
inner = std::make_shared<zeek::IP_Hdr>(ip4, false);
if ( ip4->ip_v != 4 )
return ParseResult::BadProtocol;
}
else {
return ParseResult::BadProtocol;
}
if ( (uint32_t)caplen != inner->TotalLen() )
return (uint32_t)caplen < inner->TotalLen() ? ParseResult::CaplenTooSmall
: ParseResult::CaplenTooLarge;
if ( (uint32_t)caplen != inner->TotalLen() )
return (uint32_t)caplen < inner->TotalLen() ? ParseResult::CaplenTooSmall : ParseResult::CaplenTooLarge;
return ParseResult::Ok;
}
return ParseResult::Ok;
}

View file

@ -6,42 +6,30 @@
#include "zeek/packet_analysis/Analyzer.h"
#include "zeek/packet_analysis/Component.h"
namespace zeek::detail
{
namespace zeek::detail {
class Discarder;
}
}
namespace zeek::packet_analysis::IP
{
namespace zeek::packet_analysis::IP {
class IPAnalyzer : public Analyzer
{
class IPAnalyzer : public Analyzer {
public:
IPAnalyzer();
~IPAnalyzer() override;
IPAnalyzer();
~IPAnalyzer() override;
bool AnalyzePacket(size_t len, const uint8_t* data, Packet* packet) override;
bool AnalyzePacket(size_t len, const uint8_t* data, Packet* packet) override;
static zeek::packet_analysis::AnalyzerPtr Instantiate()
{
return std::make_shared<IPAnalyzer>();
}
static zeek::packet_analysis::AnalyzerPtr Instantiate() { return std::make_shared<IPAnalyzer>(); }
private:
// Returns a reassembled packet, or nil if there are still
// some missing fragments.
zeek::detail::FragReassembler* NextFragment(double t, const IP_Hdr* ip, const u_char* pkt);
// Returns a reassembled packet, or nil if there are still
// some missing fragments.
zeek::detail::FragReassembler* NextFragment(double t, const IP_Hdr* ip, const u_char* pkt);
zeek::detail::Discarder* discarder = nullptr;
};
zeek::detail::Discarder* discarder = nullptr;
};
enum class ParseResult
{
Ok = 0,
CaplenTooSmall = -1,
BadProtocol = -2,
CaplenTooLarge = 1
};
enum class ParseResult { Ok = 0, CaplenTooSmall = -1, BadProtocol = -2, CaplenTooLarge = 1 };
/**
* Returns a wrapper IP_Hdr object if \a pkt appears to be a valid IPv4
@ -67,7 +55,6 @@ enum class ParseResult
* or IPPROTO_IPV6 or if \a proto does not match the protocol
* in the header's version field.
*/
ParseResult ParsePacket(int caplen, const u_char* const pkt, int proto,
std::shared_ptr<IP_Hdr>& inner);
ParseResult ParsePacket(int caplen, const u_char* const pkt, int proto, std::shared_ptr<IP_Hdr>& inner);
}
} // namespace zeek::packet_analysis::IP

View file

@ -13,297 +13,260 @@
using namespace zeek;
using namespace zeek::packet_analysis::IP;
IPBasedAnalyzer::IPBasedAnalyzer(const char* name, TransportProto proto, uint32_t mask,
bool report_unknown_protocols)
: zeek::packet_analysis::Analyzer(name, report_unknown_protocols), transport(proto),
server_port_mask(mask)
{
}
IPBasedAnalyzer::IPBasedAnalyzer(const char* name, TransportProto proto, uint32_t mask, bool report_unknown_protocols)
: zeek::packet_analysis::Analyzer(name, report_unknown_protocols), transport(proto), server_port_mask(mask) {}
IPBasedAnalyzer::~IPBasedAnalyzer()
{
for ( const auto& mapping : analyzers_by_port )
delete mapping.second;
}
IPBasedAnalyzer::~IPBasedAnalyzer() {
for ( const auto& mapping : analyzers_by_port )
delete mapping.second;
}
bool IPBasedAnalyzer::AnalyzePacket(size_t len, const uint8_t* data, Packet* pkt)
{
ConnTuple tuple;
if ( ! BuildConnTuple(len, data, pkt, tuple) )
return false;
bool IPBasedAnalyzer::AnalyzePacket(size_t len, const uint8_t* data, Packet* pkt) {
ConnTuple tuple;
if ( ! BuildConnTuple(len, data, pkt, tuple) )
return false;
const std::shared_ptr<IP_Hdr>& ip_hdr = pkt->ip_hdr;
detail::ConnKey key(tuple);
const std::shared_ptr<IP_Hdr>& ip_hdr = pkt->ip_hdr;
detail::ConnKey key(tuple);
Connection* conn = session_mgr->FindConnection(key);
Connection* conn = session_mgr->FindConnection(key);
if ( ! conn )
{
conn = NewConn(&tuple, key, pkt);
if ( conn )
session_mgr->Insert(conn, false);
}
else
{
if ( conn->IsReuse(run_state::processing_start_time, ip_hdr->Payload()) )
{
conn->Event(connection_reused, nullptr);
if ( ! conn ) {
conn = NewConn(&tuple, key, pkt);
if ( conn )
session_mgr->Insert(conn, false);
}
else {
if ( conn->IsReuse(run_state::processing_start_time, ip_hdr->Payload()) ) {
conn->Event(connection_reused, nullptr);
session_mgr->Remove(conn);
conn = NewConn(&tuple, key, pkt);
if ( conn )
session_mgr->Insert(conn, false);
}
else
{
conn->CheckEncapsulation(pkt->encap);
}
}
session_mgr->Remove(conn);
conn = NewConn(&tuple, key, pkt);
if ( conn )
session_mgr->Insert(conn, false);
}
else {
conn->CheckEncapsulation(pkt->encap);
}
}
if ( ! conn )
return false;
if ( ! conn )
return false;
// If we successfully made a connection for this packet that means it'll eventually
// get logged, which means we can mark this packet as having been processed.
pkt->processed = true;
// If we successfully made a connection for this packet that means it'll eventually
// get logged, which means we can mark this packet as having been processed.
pkt->processed = true;
bool is_orig = (tuple.src_addr == conn->OrigAddr()) && (tuple.src_port == conn->OrigPort());
pkt->is_orig = is_orig;
bool is_orig = (tuple.src_addr == conn->OrigAddr()) && (tuple.src_port == conn->OrigPort());
pkt->is_orig = is_orig;
conn->CheckFlowLabel(is_orig, ip_hdr->FlowLabel());
conn->CheckFlowLabel(is_orig, ip_hdr->FlowLabel());
zeek::ValPtr pkt_hdr_val;
zeek::ValPtr pkt_hdr_val;
if ( ipv6_ext_headers && ip_hdr->NumHeaders() > 1 )
{
pkt_hdr_val = ip_hdr->ToPktHdrVal();
conn->EnqueueEvent(ipv6_ext_headers, nullptr, conn->GetVal(), pkt_hdr_val);
}
if ( ipv6_ext_headers && ip_hdr->NumHeaders() > 1 ) {
pkt_hdr_val = ip_hdr->ToPktHdrVal();
conn->EnqueueEvent(ipv6_ext_headers, nullptr, conn->GetVal(), pkt_hdr_val);
}
if ( new_packet )
conn->EnqueueEvent(new_packet, nullptr, conn->GetVal(),
pkt_hdr_val ? std::move(pkt_hdr_val) : ip_hdr->ToPktHdrVal());
if ( new_packet )
conn->EnqueueEvent(new_packet, nullptr, conn->GetVal(),
pkt_hdr_val ? std::move(pkt_hdr_val) : ip_hdr->ToPktHdrVal());
conn->SetRecordPackets(true);
conn->SetRecordContents(true);
conn->SetRecordPackets(true);
conn->SetRecordContents(true);
const u_char* payload = pkt->ip_hdr->Payload();
const u_char* payload = pkt->ip_hdr->Payload();
run_state::current_timestamp = run_state::processing_start_time;
run_state::current_pkt = pkt;
run_state::current_timestamp = run_state::processing_start_time;
run_state::current_pkt = pkt;
// TODO: Does this actually mean anything?
if ( conn->GetSessionAdapter()->Skipping() )
return true;
// TODO: Does this actually mean anything?
if ( conn->GetSessionAdapter()->Skipping() )
return true;
DeliverPacket(conn, run_state::processing_start_time, is_orig, len, pkt);
DeliverPacket(conn, run_state::processing_start_time, is_orig, len, pkt);
run_state::current_timestamp = 0;
run_state::current_pkt = nullptr;
run_state::current_timestamp = 0;
run_state::current_pkt = nullptr;
// If the packet is reassembled, disable packet dumping because the
// pointer math to dump the data wouldn't work.
if ( pkt->ip_hdr->Reassembled() )
pkt->dump_packet = false;
else if ( conn->RecordPackets() )
{
pkt->dump_packet = true;
// If the packet is reassembled, disable packet dumping because the
// pointer math to dump the data wouldn't work.
if ( pkt->ip_hdr->Reassembled() )
pkt->dump_packet = false;
else if ( conn->RecordPackets() ) {
pkt->dump_packet = true;
// If we don't want the content, set the dump size to include just
// the header.
if ( ! conn->RecordContents() )
pkt->dump_size = payload - pkt->data;
}
// If we don't want the content, set the dump size to include just
// the header.
if ( ! conn->RecordContents() )
pkt->dump_size = payload - pkt->data;
}
return true;
}
return true;
}
bool IPBasedAnalyzer::CheckHeaderTrunc(size_t min_hdr_len, size_t remaining, Packet* packet)
{
// If segment offloading or similar is enabled, the payload len will return 0.
// Thus, let's ignore that case.
if ( packet->ip_hdr->PayloadLen() && packet->ip_hdr->PayloadLen() < min_hdr_len )
{
Weird("truncated_header", packet);
return false;
}
else if ( remaining < min_hdr_len )
{
Weird("internally_truncated_header", packet);
return false;
}
bool IPBasedAnalyzer::CheckHeaderTrunc(size_t min_hdr_len, size_t remaining, Packet* packet) {
// If segment offloading or similar is enabled, the payload len will return 0.
// Thus, let's ignore that case.
if ( packet->ip_hdr->PayloadLen() && packet->ip_hdr->PayloadLen() < min_hdr_len ) {
Weird("truncated_header", packet);
return false;
}
else if ( remaining < min_hdr_len ) {
Weird("internally_truncated_header", packet);
return false;
}
return true;
}
return true;
}
bool IPBasedAnalyzer::IsLikelyServerPort(uint32_t port) const
{
// We keep a cached in-core version of the table to speed up the lookup.
static std::set<zeek_uint_t> port_cache;
static bool have_cache = false;
bool IPBasedAnalyzer::IsLikelyServerPort(uint32_t port) const {
// We keep a cached in-core version of the table to speed up the lookup.
static std::set<zeek_uint_t> port_cache;
static bool have_cache = false;
if ( ! have_cache )
{
auto likely_server_ports = id::find_val<TableVal>("likely_server_ports");
auto lv = likely_server_ports->ToPureListVal();
for ( int i = 0; i < lv->Length(); i++ )
port_cache.insert(lv->Idx(i)->InternalUnsigned());
have_cache = true;
}
if ( ! have_cache ) {
auto likely_server_ports = id::find_val<TableVal>("likely_server_ports");
auto lv = likely_server_ports->ToPureListVal();
for ( int i = 0; i < lv->Length(); i++ )
port_cache.insert(lv->Idx(i)->InternalUnsigned());
have_cache = true;
}
// We exploit our knowledge of PortVal's internal storage mechanism here.
port |= server_port_mask;
// We exploit our knowledge of PortVal's internal storage mechanism here.
port |= server_port_mask;
return port_cache.find(port) != port_cache.end();
}
return port_cache.find(port) != port_cache.end();
}
zeek::Connection* IPBasedAnalyzer::NewConn(const ConnTuple* id, const detail::ConnKey& key,
const Packet* pkt)
{
int src_h = ntohs(id->src_port);
int dst_h = ntohs(id->dst_port);
bool flip = false;
zeek::Connection* IPBasedAnalyzer::NewConn(const ConnTuple* id, const detail::ConnKey& key, const Packet* pkt) {
int src_h = ntohs(id->src_port);
int dst_h = ntohs(id->dst_port);
bool flip = false;
if ( ! WantConnection(src_h, dst_h, pkt->ip_hdr->Payload(), flip) )
return nullptr;
if ( ! WantConnection(src_h, dst_h, pkt->ip_hdr->Payload(), flip) )
return nullptr;
Connection* conn = new Connection(key, run_state::processing_start_time, id,
pkt->ip_hdr->FlowLabel(), pkt);
conn->SetTransport(transport);
Connection* conn = new Connection(key, run_state::processing_start_time, id, pkt->ip_hdr->FlowLabel(), pkt);
conn->SetTransport(transport);
if ( flip && ! id->dst_addr.IsBroadcast() )
conn->FlipRoles();
if ( flip && ! id->dst_addr.IsBroadcast() )
conn->FlipRoles();
BuildSessionAnalyzerTree(conn);
BuildSessionAnalyzerTree(conn);
if ( new_connection )
conn->Event(new_connection, nullptr);
if ( new_connection )
conn->Event(new_connection, nullptr);
return conn;
}
return conn;
}
void IPBasedAnalyzer::BuildSessionAnalyzerTree(Connection* conn)
{
SessionAdapter* root = MakeSessionAdapter(conn);
analyzer::pia::PIA* pia = MakePIA(conn);
void IPBasedAnalyzer::BuildSessionAnalyzerTree(Connection* conn) {
SessionAdapter* root = MakeSessionAdapter(conn);
analyzer::pia::PIA* pia = MakePIA(conn);
bool scheduled = analyzer_mgr->ApplyScheduledAnalyzers(conn, false, root);
bool scheduled = analyzer_mgr->ApplyScheduledAnalyzers(conn, false, root);
// Hmm... Do we want *just* the expected analyzer, or all
// other potential analyzers as well? For now we only take
// the scheduled ones.
if ( ! scheduled )
{ // Let's see if it's a port we know.
if ( ! analyzers_by_port.empty() && ! zeek::detail::dpd_ignore_ports )
{
int resp_port = ntohs(conn->RespPort());
std::set<zeek::Tag>* ports = LookupPort(resp_port, false);
// Hmm... Do we want *just* the expected analyzer, or all
// other potential analyzers as well? For now we only take
// the scheduled ones.
if ( ! scheduled ) { // Let's see if it's a port we know.
if ( ! analyzers_by_port.empty() && ! zeek::detail::dpd_ignore_ports ) {
int resp_port = ntohs(conn->RespPort());
std::set<zeek::Tag>* ports = LookupPort(resp_port, false);
if ( ports )
{
for ( const auto& port : *ports )
{
analyzer::Analyzer* analyzer = analyzer_mgr->InstantiateAnalyzer(port, conn);
if ( ports ) {
for ( const auto& port : *ports ) {
analyzer::Analyzer* analyzer = analyzer_mgr->InstantiateAnalyzer(port, conn);
if ( ! analyzer )
continue;
if ( ! analyzer )
continue;
root->AddChildAnalyzer(analyzer, false);
DBG_ANALYZER_ARGS(conn, "activated %s analyzer due to port %d",
analyzer_mgr->GetComponentName(port).c_str(), resp_port);
}
}
}
}
root->AddChildAnalyzer(analyzer, false);
DBG_ANALYZER_ARGS(conn, "activated %s analyzer due to port %d",
analyzer_mgr->GetComponentName(port).c_str(), resp_port);
}
}
}
}
// Make analyzers added above through known ports visible via GetChildren()
root->AppendNewChildren();
// Make analyzers added above through known ports visible via GetChildren()
root->AppendNewChildren();
root->AddExtraAnalyzers(conn);
root->AddExtraAnalyzers(conn);
if ( pia )
root->AddChildAnalyzer(pia->AsAnalyzer());
if ( pia )
root->AddChildAnalyzer(pia->AsAnalyzer());
conn->SetSessionAdapter(root, pia);
root->Init();
root->InitChildren();
conn->SetSessionAdapter(root, pia);
root->Init();
root->InitChildren();
PLUGIN_HOOK_VOID(HOOK_SETUP_ANALYZER_TREE, HookSetupAnalyzerTree(conn));
}
PLUGIN_HOOK_VOID(HOOK_SETUP_ANALYZER_TREE, HookSetupAnalyzerTree(conn));
}
bool IPBasedAnalyzer::RegisterAnalyzerForPort(const zeek::Tag& tag, uint32_t port)
{
tag_set* l = LookupPort(port, true);
bool IPBasedAnalyzer::RegisterAnalyzerForPort(const zeek::Tag& tag, uint32_t port) {
tag_set* l = LookupPort(port, true);
if ( ! l )
return false;
if ( ! l )
return false;
#ifdef DEBUG
const char* name = analyzer_mgr->GetComponentName(tag).c_str();
DBG_LOG(DBG_ANALYZER, "Registering analyzer %s for port %" PRIu32 "/%d", name, port, transport);
const char* name = analyzer_mgr->GetComponentName(tag).c_str();
DBG_LOG(DBG_ANALYZER, "Registering analyzer %s for port %" PRIu32 "/%d", name, port, transport);
#endif
l->insert(tag);
return true;
}
l->insert(tag);
return true;
}
bool IPBasedAnalyzer::UnregisterAnalyzerForPort(const zeek::Tag& tag, uint32_t port)
{
tag_set* l = LookupPort(port, true);
bool IPBasedAnalyzer::UnregisterAnalyzerForPort(const zeek::Tag& tag, uint32_t port) {
tag_set* l = LookupPort(port, true);
if ( ! l )
return true; // still a "successful" unregistration
if ( ! l )
return true; // still a "successful" unregistration
#ifdef DEBUG
const char* name = analyzer_mgr->GetComponentName(tag).c_str();
DBG_LOG(DBG_ANALYZER, "Unregistering analyzer %s for port %" PRIu32 "/%d", name, port,
transport);
const char* name = analyzer_mgr->GetComponentName(tag).c_str();
DBG_LOG(DBG_ANALYZER, "Unregistering analyzer %s for port %" PRIu32 "/%d", name, port, transport);
#endif
l->erase(tag);
return true;
}
l->erase(tag);
return true;
}
IPBasedAnalyzer::tag_set* IPBasedAnalyzer::LookupPort(uint32_t port, bool add_if_not_found)
{
analyzer_map_by_port::const_iterator i = analyzers_by_port.find(port);
IPBasedAnalyzer::tag_set* IPBasedAnalyzer::LookupPort(uint32_t port, bool add_if_not_found) {
analyzer_map_by_port::const_iterator i = analyzers_by_port.find(port);
if ( i != analyzers_by_port.end() )
return i->second;
if ( i != analyzers_by_port.end() )
return i->second;
if ( ! add_if_not_found )
return nullptr;
if ( ! add_if_not_found )
return nullptr;
tag_set* l = new tag_set{};
analyzers_by_port.insert(std::make_pair(port, l));
return l;
}
tag_set* l = new tag_set{};
analyzers_by_port.insert(std::make_pair(port, l));
return l;
}
void IPBasedAnalyzer::DumpPortDebug()
{
for ( const auto& mapping : analyzers_by_port )
{
std::string s;
void IPBasedAnalyzer::DumpPortDebug() {
for ( const auto& mapping : analyzers_by_port ) {
std::string s;
for ( const auto& tag : *(mapping.second) )
s += std::string(analyzer_mgr->GetComponentName(tag)) + " ";
for ( const auto& tag : *(mapping.second) )
s += std::string(analyzer_mgr->GetComponentName(tag)) + " ";
DBG_LOG(DBG_ANALYZER, " %d/%s: %s", mapping.first, transport_proto_string(transport),
s.c_str());
}
}
DBG_LOG(DBG_ANALYZER, " %d/%s: %s", mapping.first, transport_proto_string(transport), s.c_str());
}
}
TableValPtr IPBasedAnalyzer::ignore_checksums_nets_table = nullptr;
void IPBasedAnalyzer::SetIgnoreChecksumsNets(TableValPtr t)
{
IPBasedAnalyzer::ignore_checksums_nets_table = t;
}
void IPBasedAnalyzer::SetIgnoreChecksumsNets(TableValPtr t) { IPBasedAnalyzer::ignore_checksums_nets_table = t; }
TableValPtr IPBasedAnalyzer::GetIgnoreChecksumsNets()
{
if ( ! IPBasedAnalyzer::ignore_checksums_nets_table )
IPBasedAnalyzer::ignore_checksums_nets_table = zeek::id::find_val<TableVal>(
"ignore_checksums_nets");
return IPBasedAnalyzer::ignore_checksums_nets_table;
}
TableValPtr IPBasedAnalyzer::GetIgnoreChecksumsNets() {
if ( ! IPBasedAnalyzer::ignore_checksums_nets_table )
IPBasedAnalyzer::ignore_checksums_nets_table = zeek::id::find_val<TableVal>("ignore_checksums_nets");
return IPBasedAnalyzer::ignore_checksums_nets_table;
}

View file

@ -9,13 +9,11 @@
#include "zeek/Tag.h"
#include "zeek/packet_analysis/Analyzer.h"
namespace zeek::analyzer::pia
{
namespace zeek::analyzer::pia {
class PIA;
}
}
namespace zeek::packet_analysis::IP
{
namespace zeek::packet_analysis::IP {
class SessionAdapter;
@ -24,183 +22,176 @@ class SessionAdapter;
* by the TCP, UDP, and ICMP analyzers to reduce a large amount of duplicated code
* that those plugins have in common.
*/
class IPBasedAnalyzer : public Analyzer
{
class IPBasedAnalyzer : public Analyzer {
public:
~IPBasedAnalyzer() override;
~IPBasedAnalyzer() override;
bool AnalyzePacket(size_t len, const uint8_t* data, Packet* packet) override;
bool AnalyzePacket(size_t len, const uint8_t* data, Packet* packet) override;
/**
* Returns true if the analyzer determines that in fact a new
* connection has started without the connection statement having
* terminated the previous one, i.e., the new data is arriving at
* what's the analyzer for the previous instance. This is used only
* for TCP.
*/
virtual bool IsReuse(double t, const u_char* pkt) { return false; }
/**
* Returns true if the analyzer determines that in fact a new
* connection has started without the connection statement having
* terminated the previous one, i.e., the new data is arriving at
* what's the analyzer for the previous instance. This is used only
* for TCP.
*/
virtual bool IsReuse(double t, const u_char* pkt) { return false; }
/**
* Registers a well-known port for an analyzer. Once registered,
* connection on that port will start with a corresponding analyzer
* assigned.
*
* @param tag The analyzer's tag.
* @param port The port's number.
* @return True if successful.
*/
bool RegisterAnalyzerForPort(const zeek::Tag& tag, uint32_t port);
/**
* Registers a well-known port for an analyzer. Once registered,
* connection on that port will start with a corresponding analyzer
* assigned.
*
* @param tag The analyzer's tag.
* @param port The port's number.
* @return True if successful.
*/
bool RegisterAnalyzerForPort(const zeek::Tag& tag, uint32_t port);
/**
* Unregisters a well-known port for an analyzer.
*
* @param tag The analyzer's tag.
* @param port The port's number.
* @param tag The analyzer's tag as an enum of script type \c
* Tag.
*/
bool UnregisterAnalyzerForPort(const zeek::Tag& tag, uint32_t port);
/**
* Unregisters a well-known port for an analyzer.
*
* @param tag The analyzer's tag.
* @param port The port's number.
* @param tag The analyzer's tag as an enum of script type \c
* Tag.
*/
bool UnregisterAnalyzerForPort(const zeek::Tag& tag, uint32_t port);
/**
* Dumps information about the registered session analyzers per port.
* Used by analyzer::Manager.
*/
void DumpPortDebug();
/**
* Dumps information about the registered session analyzers per port.
* Used by analyzer::Manager.
*/
void DumpPortDebug();
/**
* Updates the internal pointer to the script-level variable `ignore_checksums_nets`.
* This is used to prevent repeated (costly) lookup of the script-level variable
* by IP-based analyzers.
*
* @param t New value of ignore_checksums_nets
*/
static void SetIgnoreChecksumsNets(TableValPtr t);
/**
* Updates the internal pointer to the script-level variable `ignore_checksums_nets`.
* This is used to prevent repeated (costly) lookup of the script-level variable
* by IP-based analyzers.
*
* @param t New value of ignore_checksums_nets
*/
static void SetIgnoreChecksumsNets(TableValPtr t);
/**
* Gets the internal pointer to the script-level variable `ignore_checksums_nets`.
* This is used to prevent repeated (costly) lookup of the script-level variable
* by IP-based analyzers.
*
* @return Current value of `ignore_checksums_nets`.
*/
static TableValPtr GetIgnoreChecksumsNets();
/**
* Gets the internal pointer to the script-level variable `ignore_checksums_nets`.
* This is used to prevent repeated (costly) lookup of the script-level variable
* by IP-based analyzers.
*
* @return Current value of `ignore_checksums_nets`.
*/
static TableValPtr GetIgnoreChecksumsNets();
protected:
/**
* Construct a new IP-based analyzer.
*
* @param name The name for the type of analyzer. The name must match
* the one the corresponding Component registers.
* @param proto The transport protocol implemented by this analyzer.
* @param mask The mask used to determine if a port is a server port
* for this protocol. This is used by IsLikelyServerPort().
* @param report_unknown_protocols Flag for whether to report unknown
* protocols during packet forwarding. This is typically false for IP
* protocols since packets may go into the session analysis framework
* as well.
*/
IPBasedAnalyzer(const char* name, TransportProto proto, uint32_t mask,
bool report_unknown_protocols);
/**
* Construct a new IP-based analyzer.
*
* @param name The name for the type of analyzer. The name must match
* the one the corresponding Component registers.
* @param proto The transport protocol implemented by this analyzer.
* @param mask The mask used to determine if a port is a server port
* for this protocol. This is used by IsLikelyServerPort().
* @param report_unknown_protocols Flag for whether to report unknown
* protocols during packet forwarding. This is typically false for IP
* protocols since packets may go into the session analysis framework
* as well.
*/
IPBasedAnalyzer(const char* name, TransportProto proto, uint32_t mask, bool report_unknown_protocols);
/**
* Parse the header from the packet into a ConnTuple object.
*/
virtual bool BuildConnTuple(size_t len, const uint8_t* data, Packet* packet,
ConnTuple& tuple) = 0;
/**
* Parse the header from the packet into a ConnTuple object.
*/
virtual bool BuildConnTuple(size_t len, const uint8_t* data, Packet* packet, ConnTuple& tuple) = 0;
/**
* Continues process of packet after the connection has been inserted into the
* session manager. This should be implemented by all child classes.
*
* @param conn The connection currently being processed.
* @param t The timestamp for the current packet.
* @param is_orig Flag denoting whether this packet is from the originator of
* the connection.
* @param remaining The remaining about of data in the packet.
* @param pkt The packet being processed.
*/
virtual void DeliverPacket(Connection* conn, double t, bool is_orig, int remaining, Packet* pkt)
{
}
/**
* Continues process of packet after the connection has been inserted into the
* session manager. This should be implemented by all child classes.
*
* @param conn The connection currently being processed.
* @param t The timestamp for the current packet.
* @param is_orig Flag denoting whether this packet is from the originator of
* the connection.
* @param remaining The remaining about of data in the packet.
* @param pkt The packet being processed.
*/
virtual void DeliverPacket(Connection* conn, double t, bool is_orig, int remaining, Packet* pkt) {}
/**
* Upon seeing the first packet of a connection, checks whether we want
* to analyze it (e.g. we may not want to look at partial connections)
* and, if yes, whether we should flip the roles of originator and
* responder based on known ports and such.
*
* @param src_port The source port of the connection.
* @param dst_port The destination port of the connection.
* @param data The payload data for the packet being processed.
* @param flip_roles Return value if the roles should be flipped.
* @return True if the connection is wanted. False otherwise.
*/
virtual bool WantConnection(uint16_t src_port, uint16_t dst_port, const u_char* data,
bool& flip_roles) const
{
flip_roles = false;
return true;
}
/**
* Upon seeing the first packet of a connection, checks whether we want
* to analyze it (e.g. we may not want to look at partial connections)
* and, if yes, whether we should flip the roles of originator and
* responder based on known ports and such.
*
* @param src_port The source port of the connection.
* @param dst_port The destination port of the connection.
* @param data The payload data for the packet being processed.
* @param flip_roles Return value if the roles should be flipped.
* @return True if the connection is wanted. False otherwise.
*/
virtual bool WantConnection(uint16_t src_port, uint16_t dst_port, const u_char* data, bool& flip_roles) const {
flip_roles = false;
return true;
}
/**
* Returns an analyzer adapter appropriate for this IP-based analyzer. This adapter
* is used to hook into the session analyzer framework. This function can also be used
* to do any extra initialization of connection timers, etc.
*/
virtual SessionAdapter* MakeSessionAdapter(Connection* conn) = 0;
/**
* Returns an analyzer adapter appropriate for this IP-based analyzer. This adapter
* is used to hook into the session analyzer framework. This function can also be used
* to do any extra initialization of connection timers, etc.
*/
virtual SessionAdapter* MakeSessionAdapter(Connection* conn) = 0;
/**
* Returns a PIA appropriate for this IP-based analyzer. This method is optional to
* override in child classes, as not all analyzers need a PIA.
*/
virtual analyzer::pia::PIA* MakePIA(Connection* conn) { return nullptr; }
/**
* Returns a PIA appropriate for this IP-based analyzer. This method is optional to
* override in child classes, as not all analyzers need a PIA.
*/
virtual analyzer::pia::PIA* MakePIA(Connection* conn) { return nullptr; }
/**
* Verifies that there is enough data in the packet to process the header
* length requested.
*
* @param min_hdr_len The minimum data in bytes that needs to exist.
* @param remaining The remaining number of bytes in the packet reported by
* previous analyzer.
* @param packet The packet being processed. This will be used to pull out the
* number of bytes the IP header says we have remaining.
*/
bool CheckHeaderTrunc(size_t min_hdr_len, size_t remaining, Packet* packet);
/**
* Verifies that there is enough data in the packet to process the header
* length requested.
*
* @param min_hdr_len The minimum data in bytes that needs to exist.
* @param remaining The remaining number of bytes in the packet reported by
* previous analyzer.
* @param packet The packet being processed. This will be used to pull out the
* number of bytes the IP header says we have remaining.
*/
bool CheckHeaderTrunc(size_t min_hdr_len, size_t remaining, Packet* packet);
/**
* Returns true if the port corresponds to an application for which there
* is a Zeek analyzer (even if it might not be used by the present policy
* script) or if it's generally a likely server port.
*
* @param port The port number to check, in host order.
*/
bool IsLikelyServerPort(uint32_t port) const;
/**
* Returns true if the port corresponds to an application for which there
* is a Zeek analyzer (even if it might not be used by the present policy
* script) or if it's generally a likely server port.
*
* @param port The port number to check, in host order.
*/
bool IsLikelyServerPort(uint32_t port) const;
private:
// While this is storing session analyzer tags, we store it here since packet analyzers
// are persistent objects. We can't do this in the adapters because those get created
// and destroyed for each connection.
using tag_set = std::set<zeek::Tag>;
using analyzer_map_by_port = std::map<uint32_t, tag_set*>;
analyzer_map_by_port analyzers_by_port;
// While this is storing session analyzer tags, we store it here since packet analyzers
// are persistent objects. We can't do this in the adapters because those get created
// and destroyed for each connection.
using tag_set = std::set<zeek::Tag>;
using analyzer_map_by_port = std::map<uint32_t, tag_set*>;
analyzer_map_by_port analyzers_by_port;
tag_set* LookupPort(uint32_t port, bool add_if_not_found);
tag_set* LookupPort(uint32_t port, bool add_if_not_found);
/**
* Creates a new Connection object from data gleaned from the current packet.
*
* @param id A connection ID generated from the packet data. This should have been
* passed in from a child analyzer.
* @param key A connection ID key generated from the ID.
* @param pkt The packet associated with the new connection.
*/
zeek::Connection* NewConn(const ConnTuple* id, const detail::ConnKey& key, const Packet* pkt);
/**
* Creates a new Connection object from data gleaned from the current packet.
*
* @param id A connection ID generated from the packet data. This should have been
* passed in from a child analyzer.
* @param key A connection ID key generated from the ID.
* @param pkt The packet associated with the new connection.
*/
zeek::Connection* NewConn(const ConnTuple* id, const detail::ConnKey& key, const Packet* pkt);
void BuildSessionAnalyzerTree(Connection* conn);
void BuildSessionAnalyzerTree(Connection* conn);
TransportProto transport;
uint32_t server_port_mask;
static TableValPtr ignore_checksums_nets_table;
};
TransportProto transport;
uint32_t server_port_mask;
static TableValPtr ignore_checksums_nets_table;
};
}
} // namespace zeek::packet_analysis::IP

View file

@ -5,23 +5,19 @@
#include "zeek/packet_analysis/Component.h"
#include "zeek/packet_analysis/protocol/ip/IP.h"
namespace zeek::plugin::Zeek_IP
{
namespace zeek::plugin::Zeek_IP {
class Plugin final : public zeek::plugin::Plugin
{
class Plugin final : public zeek::plugin::Plugin {
public:
zeek::plugin::Configuration Configure() override
{
AddComponent(new zeek::packet_analysis::Component(
"IP", zeek::packet_analysis::IP::IPAnalyzer::Instantiate));
zeek::plugin::Configuration Configure() override {
AddComponent(new zeek::packet_analysis::Component("IP", zeek::packet_analysis::IP::IPAnalyzer::Instantiate));
zeek::plugin::Configuration config;
config.name = "Zeek::IP";
config.description = "Packet analyzer for IP fallback (v4 or v6)";
return config;
}
zeek::plugin::Configuration config;
config.name = "Zeek::IP";
config.description = "Packet analyzer for IP fallback (v4 or v6)";
return config;
}
} plugin;
} plugin;
}
} // namespace zeek::plugin::Zeek_IP

View file

@ -6,33 +6,23 @@
using namespace zeek::packet_analysis::IP;
void SessionAdapter::Done()
{
Analyzer::Done();
}
void SessionAdapter::Done() { Analyzer::Done(); }
bool SessionAdapter::IsReuse(double t, const u_char* pkt)
{
return parent->IsReuse(t, pkt);
}
bool SessionAdapter::IsReuse(double t, const u_char* pkt) { return parent->IsReuse(t, pkt); }
void SessionAdapter::SetContentsFile(unsigned int /* direction */, FilePtr /* f */)
{
reporter->Error("analyzer type does not support writing to a contents file");
}
void SessionAdapter::SetContentsFile(unsigned int /* direction */, FilePtr /* f */) {
reporter->Error("analyzer type does not support writing to a contents file");
}
zeek::FilePtr SessionAdapter::GetContentsFile(unsigned int /* direction */) const
{
reporter->Error("analyzer type does not support writing to a contents file");
return nullptr;
}
zeek::FilePtr SessionAdapter::GetContentsFile(unsigned int /* direction */) const {
reporter->Error("analyzer type does not support writing to a contents file");
return nullptr;
}
void SessionAdapter::PacketContents(const u_char* data, int len)
{
if ( packet_contents && len > 0 )
{
zeek::String* cbs = new zeek::String(data, len, true);
auto contents = make_intrusive<StringVal>(cbs);
EnqueueConnEvent(packet_contents, ConnVal(), std::move(contents));
}
}
void SessionAdapter::PacketContents(const u_char* data, int len) {
if ( packet_contents && len > 0 ) {
zeek::String* cbs = new zeek::String(data, len, true);
auto contents = make_intrusive<StringVal>(cbs);
EnqueueConnEvent(packet_contents, ConnVal(), std::move(contents));
}
}

View file

@ -2,13 +2,11 @@
#include "zeek/analyzer/Analyzer.h"
namespace zeek::analyzer::pia
{
namespace zeek::analyzer::pia {
class PIA;
}
}
namespace zeek::packet_analysis::IP
{
namespace zeek::packet_analysis::IP {
class IPBasedAnalyzer;
@ -17,88 +15,86 @@ class IPBasedAnalyzer;
* the session analysis framework. One of these should be implemented for each
* packet analyzer that intends to forward into the session analysis.
*/
class SessionAdapter : public analyzer::Analyzer
{
class SessionAdapter : public analyzer::Analyzer {
public:
SessionAdapter(const char* name, Connection* conn) : analyzer::Analyzer(name, conn) { }
SessionAdapter(const char* name, Connection* conn) : analyzer::Analyzer(name, conn) {}
/**
* Overridden from parent class.
*/
virtual void Done() override;
/**
* Overridden from parent class.
*/
virtual void Done() override;
/**
* Sets the parent packet analyzer for this session adapter. This can't be passed to
* the constructor due to the way that SessionAdapter gets instantiated.
*
* @param p The parent packet analyzer to store
*/
void SetParent(IPBasedAnalyzer* p) { parent = p; }
/**
* Sets the parent packet analyzer for this session adapter. This can't be passed to
* the constructor due to the way that SessionAdapter gets instantiated.
*
* @param p The parent packet analyzer to store
*/
void SetParent(IPBasedAnalyzer* p) { parent = p; }
/**
* Returns true if the analyzer determines that in fact a new connection has started
* without the connection statement having terminated the previous one, i.e., the new
* data is arriving at what's the analyzer for the previous instance. This is used only
* for TCP.
*/
virtual bool IsReuse(double t, const u_char* pkt);
/**
* Returns true if the analyzer determines that in fact a new connection has started
* without the connection statement having terminated the previous one, i.e., the new
* data is arriving at what's the analyzer for the previous instance. This is used only
* for TCP.
*/
virtual bool IsReuse(double t, const u_char* pkt);
/**
* Pure virtual method to allow extra session analyzers to be added to this analyzer's
* tree of children. This is used by analyzer::Manager when creating the session analyzer
* tree.
*/
virtual void AddExtraAnalyzers(Connection* conn) = 0;
/**
* Pure virtual method to allow extra session analyzers to be added to this analyzer's
* tree of children. This is used by analyzer::Manager when creating the session analyzer
* tree.
*/
virtual void AddExtraAnalyzers(Connection* conn) = 0;
/**
* Associates a file with the analyzer in which to record all
* analyzed input. This must only be called with derived classes that
* override the method; the default implementation will abort.
*
* @param direction One of the CONTENTS_* constants indicating which
* direction of the input stream is to be recorded.
*
* @param f The file to record to.
*
*/
virtual void SetContentsFile(unsigned int direction, FilePtr f);
/**
* Associates a file with the analyzer in which to record all
* analyzed input. This must only be called with derived classes that
* override the method; the default implementation will abort.
*
* @param direction One of the CONTENTS_* constants indicating which
* direction of the input stream is to be recorded.
*
* @param f The file to record to.
*
*/
virtual void SetContentsFile(unsigned int direction, FilePtr f);
/**
* Returns an associated contents file, if any. This must only be
* called with derived classes that override the method; the default
* implementation will abort.
*
* @param direction One of the CONTENTS_* constants indicating which
* direction the query is for.
*/
virtual FilePtr GetContentsFile(unsigned int direction) const;
/**
* Returns an associated contents file, if any. This must only be
* called with derived classes that override the method; the default
* implementation will abort.
*
* @param direction One of the CONTENTS_* constants indicating which
* direction the query is for.
*/
virtual FilePtr GetContentsFile(unsigned int direction) const;
/**
* Associates a PIA with this analyzer. A PIA takes the
* transport-layer input and determine which protocol analyzer(s) to
* use for parsing it.
*/
void SetPIA(analyzer::pia::PIA* arg_PIA) { pia = arg_PIA; }
/**
* Associates a PIA with this analyzer. A PIA takes the
* transport-layer input and determine which protocol analyzer(s) to
* use for parsing it.
*/
void SetPIA(analyzer::pia::PIA* arg_PIA) { pia = arg_PIA; }
/**
* Returns the associated PIA, or null of none. Does not take
* ownership.
*/
analyzer::pia::PIA* GetPIA() const { return pia; }
/**
* Returns the associated PIA, or null of none. Does not take
* ownership.
*/
analyzer::pia::PIA* GetPIA() const { return pia; }
/**
* Helper to raise a \c packet_contents event.
*
* @param data The data to pass to the event.
*
* @param len The length of \a data.
*/
void PacketContents(const u_char* data, int len);
/**
* Helper to raise a \c packet_contents event.
*
* @param data The data to pass to the event.
*
* @param len The length of \a data.
*/
void PacketContents(const u_char* data, int len);
protected:
IPBasedAnalyzer* parent = nullptr;
analyzer::pia::PIA* pia = nullptr;
};
IPBasedAnalyzer* parent = nullptr;
analyzer::pia::PIA* pia = nullptr;
};
} // namespace zeek::packet_analysis::IP
} // namespace zeek::packet_analysis::IP

View file

@ -10,231 +10,207 @@
#include "zeek/TunnelEncapsulation.h"
#include "zeek/packet_analysis/protocol/ip/IP.h"
namespace zeek::packet_analysis::IPTunnel
{
namespace zeek::packet_analysis::IPTunnel {
IPTunnelAnalyzer* ip_tunnel_analyzer;
IPTunnelAnalyzer::IPTunnelAnalyzer() : zeek::packet_analysis::Analyzer("IPTunnel")
{
ip_tunnel_analyzer = this;
}
IPTunnelAnalyzer::IPTunnelAnalyzer() : zeek::packet_analysis::Analyzer("IPTunnel") { ip_tunnel_analyzer = this; }
bool IPTunnelAnalyzer::AnalyzePacket(size_t len, const uint8_t* data, Packet* packet)
{
if ( ! packet->ip_hdr )
{
reporter->InternalError("IPTunnelAnalyzer: null ip_hdr in packet");
return false;
}
bool IPTunnelAnalyzer::AnalyzePacket(size_t len, const uint8_t* data, Packet* packet) {
if ( ! packet->ip_hdr ) {
reporter->InternalError("IPTunnelAnalyzer: null ip_hdr in packet");
return false;
}
if ( packet->encap && packet->encap->Depth() >= BifConst::Tunnel::max_depth )
{
Weird("exceeded_tunnel_max_depth", packet);
return false;
}
if ( packet->encap && packet->encap->Depth() >= BifConst::Tunnel::max_depth ) {
Weird("exceeded_tunnel_max_depth", packet);
return false;
}
int proto = packet->proto;
int gre_version = packet->gre_version;
BifEnum::Tunnel::Type tunnel_type = packet->tunnel_type;
int gre_link_type = packet->gre_link_type;
int proto = packet->proto;
int gre_version = packet->gre_version;
BifEnum::Tunnel::Type tunnel_type = packet->tunnel_type;
int gre_link_type = packet->gre_link_type;
std::shared_ptr<IP_Hdr> inner = nullptr;
std::shared_ptr<IP_Hdr> inner = nullptr;
if ( gre_version != 0 )
{
// Check for a valid inner packet first.
auto result = packet_analysis::IP::ParsePacket(len, data, proto, inner);
if ( result == packet_analysis::IP::ParseResult::BadProtocol )
Weird("invalid_inner_IP_version", packet);
else if ( result < packet_analysis::IP::ParseResult::CaplenTooSmall )
Weird("truncated_inner_IP", packet);
else if ( result > packet_analysis::IP::ParseResult::CaplenTooLarge )
Weird("inner_IP_payload_length_mismatch", packet);
if ( gre_version != 0 ) {
// Check for a valid inner packet first.
auto result = packet_analysis::IP::ParsePacket(len, data, proto, inner);
if ( result == packet_analysis::IP::ParseResult::BadProtocol )
Weird("invalid_inner_IP_version", packet);
else if ( result < packet_analysis::IP::ParseResult::CaplenTooSmall )
Weird("truncated_inner_IP", packet);
else if ( result > packet_analysis::IP::ParseResult::CaplenTooLarge )
Weird("inner_IP_payload_length_mismatch", packet);
if ( result != packet_analysis::IP::ParseResult::Ok )
return false;
}
if ( result != packet_analysis::IP::ParseResult::Ok )
return false;
}
// Look up to see if we've already seen this IP tunnel, identified
// by the pair of IP addresses, so that we can always associate the
// same UID with it.
IPPair tunnel_idx;
if ( packet->ip_hdr->SrcAddr() < packet->ip_hdr->DstAddr() )
tunnel_idx = IPPair(packet->ip_hdr->SrcAddr(), packet->ip_hdr->DstAddr());
else
tunnel_idx = IPPair(packet->ip_hdr->DstAddr(), packet->ip_hdr->SrcAddr());
// Look up to see if we've already seen this IP tunnel, identified
// by the pair of IP addresses, so that we can always associate the
// same UID with it.
IPPair tunnel_idx;
if ( packet->ip_hdr->SrcAddr() < packet->ip_hdr->DstAddr() )
tunnel_idx = IPPair(packet->ip_hdr->SrcAddr(), packet->ip_hdr->DstAddr());
else
tunnel_idx = IPPair(packet->ip_hdr->DstAddr(), packet->ip_hdr->SrcAddr());
IPTunnelMap::iterator tunnel_it = ip_tunnels.find(tunnel_idx);
IPTunnelMap::iterator tunnel_it = ip_tunnels.find(tunnel_idx);
if ( tunnel_it == ip_tunnels.end() )
{
EncapsulatingConn ec(packet->ip_hdr->SrcAddr(), packet->ip_hdr->DstAddr(), tunnel_type);
ip_tunnels[tunnel_idx] = TunnelActivity(ec, run_state::network_time);
zeek::detail::timer_mgr->Add(
new detail::IPTunnelTimer(run_state::network_time, tunnel_idx, this));
}
else
tunnel_it->second.second = zeek::run_state::network_time;
if ( tunnel_it == ip_tunnels.end() ) {
EncapsulatingConn ec(packet->ip_hdr->SrcAddr(), packet->ip_hdr->DstAddr(), tunnel_type);
ip_tunnels[tunnel_idx] = TunnelActivity(ec, run_state::network_time);
zeek::detail::timer_mgr->Add(new detail::IPTunnelTimer(run_state::network_time, tunnel_idx, this));
}
else
tunnel_it->second.second = zeek::run_state::network_time;
if ( gre_version == 0 )
return ProcessEncapsulatedPacket(run_state::processing_start_time, packet, len, len, data,
gre_link_type, packet->encap,
ip_tunnels[tunnel_idx].first);
else
return ProcessEncapsulatedPacket(run_state::processing_start_time, packet, inner,
packet->encap, ip_tunnels[tunnel_idx].first);
}
if ( gre_version == 0 )
return ProcessEncapsulatedPacket(run_state::processing_start_time, packet, len, len, data, gre_link_type,
packet->encap, ip_tunnels[tunnel_idx].first);
else
return ProcessEncapsulatedPacket(run_state::processing_start_time, packet, inner, packet->encap,
ip_tunnels[tunnel_idx].first);
}
/**
* Handles a packet that contains an IP header directly after the tunnel header.
*/
bool IPTunnelAnalyzer::ProcessEncapsulatedPacket(double t, const Packet* pkt,
const std::shared_ptr<IP_Hdr>& inner,
bool IPTunnelAnalyzer::ProcessEncapsulatedPacket(double t, const Packet* pkt, const std::shared_ptr<IP_Hdr>& inner,
std::shared_ptr<EncapsulationStack> prev,
const EncapsulatingConn& ec)
{
uint32_t caplen, len;
caplen = len = inner->TotalLen();
const EncapsulatingConn& ec) {
uint32_t caplen, len;
caplen = len = inner->TotalLen();
pkt_timeval ts;
int link_type;
pkt_timeval ts;
int link_type;
if ( pkt )
ts = pkt->ts;
else
{
ts.tv_sec = (time_t)run_state::network_time;
ts.tv_usec = (suseconds_t)((run_state::network_time - (double)ts.tv_sec) * 1000000);
}
if ( pkt )
ts = pkt->ts;
else {
ts.tv_sec = (time_t)run_state::network_time;
ts.tv_usec = (suseconds_t)((run_state::network_time - (double)ts.tv_sec) * 1000000);
}
const u_char* data = nullptr;
const u_char* data = nullptr;
if ( inner->IP4_Hdr() )
data = (const u_char*)inner->IP4_Hdr();
else
data = (const u_char*)inner->IP6_Hdr();
if ( inner->IP4_Hdr() )
data = (const u_char*)inner->IP4_Hdr();
else
data = (const u_char*)inner->IP6_Hdr();
auto outer = prev ? prev : std::make_shared<EncapsulationStack>();
outer->Add(ec);
auto outer = prev ? prev : std::make_shared<EncapsulationStack>();
outer->Add(ec);
// Construct fake packet containing the inner packet so it can be processed
// like a normal one.
Packet p;
p.Init(DLT_RAW, &ts, caplen, len, data, false, "");
p.encap = outer;
// Construct fake packet containing the inner packet so it can be processed
// like a normal one.
Packet p;
p.Init(DLT_RAW, &ts, caplen, len, data, false, "");
p.encap = outer;
// Forward the packet back to the IP analyzer.
bool return_val = ForwardPacket(len, data, &p);
// Forward the packet back to the IP analyzer.
bool return_val = ForwardPacket(len, data, &p);
return return_val;
}
return return_val;
}
/**
* Handles a packet that contains a physical-layer header after the tunnel header.
*/
bool IPTunnelAnalyzer::ProcessEncapsulatedPacket(double t, const Packet* pkt, uint32_t caplen,
uint32_t len, const u_char* data, int link_type,
bool IPTunnelAnalyzer::ProcessEncapsulatedPacket(double t, const Packet* pkt, uint32_t caplen, uint32_t len,
const u_char* data, int link_type,
std::shared_ptr<EncapsulationStack> prev,
const EncapsulatingConn& ec)
{
pkt_timeval ts;
const EncapsulatingConn& ec) {
pkt_timeval ts;
if ( pkt )
ts = pkt->ts;
else
{
ts.tv_sec = (time_t)run_state::network_time;
ts.tv_usec = (suseconds_t)((run_state::network_time - (double)ts.tv_sec) * 1000000);
}
if ( pkt )
ts = pkt->ts;
else {
ts.tv_sec = (time_t)run_state::network_time;
ts.tv_usec = (suseconds_t)((run_state::network_time - (double)ts.tv_sec) * 1000000);
}
auto outer = prev ? prev : std::make_shared<EncapsulationStack>();
outer->Add(ec);
auto outer = prev ? prev : std::make_shared<EncapsulationStack>();
outer->Add(ec);
// Construct fake packet containing the inner packet so it can be processed
// like a normal one.
Packet p;
p.Init(link_type, &ts, caplen, len, data, false, "");
p.encap = outer;
// Construct fake packet containing the inner packet so it can be processed
// like a normal one.
Packet p;
p.Init(link_type, &ts, caplen, len, data, false, "");
p.encap = outer;
// Process the packet as if it was a brand new packet by passing it back
// to the packet manager.
bool return_val = packet_mgr->ProcessInnerPacket(&p);
// Process the packet as if it was a brand new packet by passing it back
// to the packet manager.
bool return_val = packet_mgr->ProcessInnerPacket(&p);
return return_val;
}
return return_val;
}
std::unique_ptr<Packet> build_inner_packet(Packet* outer_pkt, int* encap_index,
std::shared_ptr<EncapsulationStack> encap_stack,
uint32_t inner_cap_len, const u_char* data,
int link_type, BifEnum::Tunnel::Type tunnel_type,
const Tag& analyzer_tag)
{
auto inner_pkt = std::make_unique<Packet>();
std::shared_ptr<EncapsulationStack> encap_stack, uint32_t inner_cap_len,
const u_char* data, int link_type, BifEnum::Tunnel::Type tunnel_type,
const Tag& analyzer_tag) {
auto inner_pkt = std::make_unique<Packet>();
assert(outer_pkt->cap_len >= inner_cap_len);
assert(outer_pkt->len >= outer_pkt->cap_len - inner_cap_len);
assert(outer_pkt->cap_len >= inner_cap_len);
assert(outer_pkt->len >= outer_pkt->cap_len - inner_cap_len);
// Compute the wire length of the inner packet based on the wire length of
// the outer and the difference in capture lengths. This ensures that for
// truncated packets the wire length of the inner packet stays intact. Wire
// length may be greater than data available for truncated packets. However,
// analyzers do validate lengths found in headers with the wire length
// of the packet and keeping it consistent avoids violations.
uint32_t consumed_len = outer_pkt->cap_len - inner_cap_len;
uint32_t inner_wire_len = outer_pkt->len - consumed_len;
// Compute the wire length of the inner packet based on the wire length of
// the outer and the difference in capture lengths. This ensures that for
// truncated packets the wire length of the inner packet stays intact. Wire
// length may be greater than data available for truncated packets. However,
// analyzers do validate lengths found in headers with the wire length
// of the packet and keeping it consistent avoids violations.
uint32_t consumed_len = outer_pkt->cap_len - inner_cap_len;
uint32_t inner_wire_len = outer_pkt->len - consumed_len;
pkt_timeval ts;
ts.tv_sec = static_cast<time_t>(run_state::current_timestamp);
ts.tv_usec = static_cast<suseconds_t>(
(run_state::current_timestamp - static_cast<double>(ts.tv_sec)) * 1000000);
inner_pkt->Init(link_type, &ts, inner_cap_len, inner_wire_len, data);
pkt_timeval ts;
ts.tv_sec = static_cast<time_t>(run_state::current_timestamp);
ts.tv_usec = static_cast<suseconds_t>((run_state::current_timestamp - static_cast<double>(ts.tv_sec)) * 1000000);
inner_pkt->Init(link_type, &ts, inner_cap_len, inner_wire_len, data);
*encap_index = 0;
if ( outer_pkt->session )
{
EncapsulatingConn inner(static_cast<Connection*>(outer_pkt->session), tunnel_type);
*encap_index = 0;
if ( outer_pkt->session ) {
EncapsulatingConn inner(static_cast<Connection*>(outer_pkt->session), tunnel_type);
if ( ! outer_pkt->encap )
outer_pkt->encap = encap_stack != nullptr ? encap_stack
: std::make_shared<EncapsulationStack>();
if ( ! outer_pkt->encap )
outer_pkt->encap = encap_stack != nullptr ? encap_stack : std::make_shared<EncapsulationStack>();
outer_pkt->encap->Add(inner);
inner_pkt->encap = outer_pkt->encap;
*encap_index = outer_pkt->encap->Depth();
}
outer_pkt->encap->Add(inner);
inner_pkt->encap = outer_pkt->encap;
*encap_index = outer_pkt->encap->Depth();
}
return inner_pkt;
}
return inner_pkt;
}
namespace detail
{
namespace detail {
IPTunnelTimer::IPTunnelTimer(double t, IPTunnelAnalyzer::IPPair p, IPTunnelAnalyzer* analyzer)
: Timer(t + BifConst::Tunnel::ip_tunnel_timeout, zeek::detail::TIMER_IP_TUNNEL_INACTIVITY),
tunnel_idx(p), analyzer(analyzer)
{
}
: Timer(t + BifConst::Tunnel::ip_tunnel_timeout, zeek::detail::TIMER_IP_TUNNEL_INACTIVITY),
tunnel_idx(p),
analyzer(analyzer) {}
void IPTunnelTimer::Dispatch(double t, bool is_expire)
{
IPTunnelAnalyzer::IPTunnelMap::const_iterator it = analyzer->ip_tunnels.find(tunnel_idx);
void IPTunnelTimer::Dispatch(double t, bool is_expire) {
IPTunnelAnalyzer::IPTunnelMap::const_iterator it = analyzer->ip_tunnels.find(tunnel_idx);
if ( it == analyzer->ip_tunnels.end() )
return;
if ( it == analyzer->ip_tunnels.end() )
return;
double last_active = it->second.second;
double inactive_time = t > last_active ? t - last_active : 0;
double last_active = it->second.second;
double inactive_time = t > last_active ? t - last_active : 0;
if ( inactive_time >= BifConst::Tunnel::ip_tunnel_timeout )
// tunnel activity timed out, delete it from map
analyzer->ip_tunnels.erase(tunnel_idx);
if ( inactive_time >= BifConst::Tunnel::ip_tunnel_timeout )
// tunnel activity timed out, delete it from map
analyzer->ip_tunnels.erase(tunnel_idx);
else if ( ! is_expire )
// tunnel activity didn't timeout, schedule another timer
zeek::detail::timer_mgr->Add(new IPTunnelTimer(t, tunnel_idx, analyzer));
}
else if ( ! is_expire )
// tunnel activity didn't timeout, schedule another timer
zeek::detail::timer_mgr->Add(new IPTunnelTimer(t, tunnel_idx, analyzer));
}
} // namespace detail
} // namespace detail
} // namespace zeek::packet_analysis::IPTunnel
} // namespace zeek::packet_analysis::IPTunnel

View file

@ -7,76 +7,67 @@
#include "zeek/packet_analysis/Analyzer.h"
#include "zeek/packet_analysis/Component.h"
namespace zeek::packet_analysis::IPTunnel
{
namespace zeek::packet_analysis::IPTunnel {
namespace detail
{
namespace detail {
class IPTunnelTimer;
}
}
class IPTunnelAnalyzer : public Analyzer
{
class IPTunnelAnalyzer : public Analyzer {
public:
IPTunnelAnalyzer();
~IPTunnelAnalyzer() override = default;
IPTunnelAnalyzer();
~IPTunnelAnalyzer() override = default;
bool AnalyzePacket(size_t len, const uint8_t* data, Packet* packet) override;
bool AnalyzePacket(size_t len, const uint8_t* data, Packet* packet) override;
static zeek::packet_analysis::AnalyzerPtr Instantiate()
{
return std::make_shared<IPTunnelAnalyzer>();
}
static zeek::packet_analysis::AnalyzerPtr Instantiate() { return std::make_shared<IPTunnelAnalyzer>(); }
/**
* Wrapper that handles encapsulated IP packets and passes them back into
* packet analysis.
*
* @param t Network time.
* @param pkt If the outer pcap header is available, this pointer can be set
* so the fake pcap header passed to the next analyzer will use the
* same timeval. The caplen and len fields of the fake pcap header
* are always set to the TotalLength() of \a inner.
* @param inner Pointer to IP header wrapper of the inner packet, ownership
* of the pointer's memory is assumed by this function.
* @param prev Any previous encapsulation stack of the caller, not including
* the most-recently found depth of encapsulation.
* @param ec The most-recently found depth of encapsulation.
*/
bool ProcessEncapsulatedPacket(double t, const Packet* pkt,
const std::shared_ptr<IP_Hdr>& inner,
std::shared_ptr<EncapsulationStack> prev,
const EncapsulatingConn& ec);
/**
* Wrapper that handles encapsulated IP packets and passes them back into
* packet analysis.
*
* @param t Network time.
* @param pkt If the outer pcap header is available, this pointer can be set
* so the fake pcap header passed to the next analyzer will use the
* same timeval. The caplen and len fields of the fake pcap header
* are always set to the TotalLength() of \a inner.
* @param inner Pointer to IP header wrapper of the inner packet, ownership
* of the pointer's memory is assumed by this function.
* @param prev Any previous encapsulation stack of the caller, not including
* the most-recently found depth of encapsulation.
* @param ec The most-recently found depth of encapsulation.
*/
bool ProcessEncapsulatedPacket(double t, const Packet* pkt, const std::shared_ptr<IP_Hdr>& inner,
std::shared_ptr<EncapsulationStack> prev, const EncapsulatingConn& ec);
/**
* Wrapper that handles encapsulated Ethernet/IP packets and passes them back into
* packet analysis.
*
* @param t Network time.
* @param pkt If the outer pcap header is available, this pointer can be set
* so the fake pcap header passed to the next analyzer will use the
* same timeval.
* @param caplen Number of captured bytes remaining
* @param len Number of bytes remaining as claimed by outer framing
* @param data The remaining packet data
* @param link_type Layer 2 link type used for initializing inner packet
* @param prev Any previous encapsulation stack of the caller, not
* including the most-recently found depth of encapsulation.
* @param ec The most-recently found depth of encapsulation.
*/
bool ProcessEncapsulatedPacket(double t, const Packet* pkt, uint32_t caplen, uint32_t len,
const u_char* data, int link_type,
std::shared_ptr<EncapsulationStack> prev,
const EncapsulatingConn& ec);
/**
* Wrapper that handles encapsulated Ethernet/IP packets and passes them back into
* packet analysis.
*
* @param t Network time.
* @param pkt If the outer pcap header is available, this pointer can be set
* so the fake pcap header passed to the next analyzer will use the
* same timeval.
* @param caplen Number of captured bytes remaining
* @param len Number of bytes remaining as claimed by outer framing
* @param data The remaining packet data
* @param link_type Layer 2 link type used for initializing inner packet
* @param prev Any previous encapsulation stack of the caller, not
* including the most-recently found depth of encapsulation.
* @param ec The most-recently found depth of encapsulation.
*/
bool ProcessEncapsulatedPacket(double t, const Packet* pkt, uint32_t caplen, uint32_t len, const u_char* data,
int link_type, std::shared_ptr<EncapsulationStack> prev,
const EncapsulatingConn& ec);
protected:
friend class detail::IPTunnelTimer;
friend class detail::IPTunnelTimer;
using IPPair = std::pair<IPAddr, IPAddr>;
using TunnelActivity = std::pair<EncapsulatingConn, double>;
using IPTunnelMap = std::map<IPPair, TunnelActivity>;
IPTunnelMap ip_tunnels;
};
using IPPair = std::pair<IPAddr, IPAddr>;
using TunnelActivity = std::pair<EncapsulatingConn, double>;
using IPTunnelMap = std::map<IPPair, TunnelActivity>;
IPTunnelMap ip_tunnels;
};
/**
* Utility function for packet analyzers for encapsulation/tunnel protocols. This
@ -103,29 +94,26 @@ protected:
*/
extern std::unique_ptr<Packet> build_inner_packet(Packet* outer_pkt, int* encap_index,
std::shared_ptr<EncapsulationStack> encap_stack,
uint32_t inner_cap_len, const u_char* data,
int link_type, BifEnum::Tunnel::Type tunnel_type,
const Tag& analyzer_tag);
uint32_t inner_cap_len, const u_char* data, int link_type,
BifEnum::Tunnel::Type tunnel_type, const Tag& analyzer_tag);
namespace detail
{
namespace detail {
class IPTunnelTimer final : public zeek::detail::Timer
{
class IPTunnelTimer final : public zeek::detail::Timer {
public:
IPTunnelTimer(double t, IPTunnelAnalyzer::IPPair p, IPTunnelAnalyzer* analyzer);
~IPTunnelTimer() override = default;
IPTunnelTimer(double t, IPTunnelAnalyzer::IPPair p, IPTunnelAnalyzer* analyzer);
~IPTunnelTimer() override = default;
void Dispatch(double t, bool is_expire) override;
void Dispatch(double t, bool is_expire) override;
protected:
IPTunnelAnalyzer::IPPair tunnel_idx;
IPTunnelAnalyzer* analyzer;
};
IPTunnelAnalyzer::IPPair tunnel_idx;
IPTunnelAnalyzer* analyzer;
};
} // namespace detail
} // namespace detail
// This is temporary until the TCP and UDP analyzers are moved to be packet analyzers.
extern IPTunnelAnalyzer* ip_tunnel_analyzer;
}
} // namespace zeek::packet_analysis::IPTunnel

View file

@ -5,23 +5,21 @@
#include "zeek/packet_analysis/Component.h"
#include "zeek/packet_analysis/protocol/iptunnel/IPTunnel.h"
namespace zeek::plugin::Zeek_IPTunnel
{
namespace zeek::plugin::Zeek_IPTunnel {
class Plugin final : public zeek::plugin::Plugin
{
class Plugin final : public zeek::plugin::Plugin {
public:
zeek::plugin::Configuration Configure() override
{
AddComponent(new zeek::packet_analysis::Component(
"IPTunnel", zeek::packet_analysis::IPTunnel::IPTunnelAnalyzer::Instantiate));
zeek::plugin::Configuration Configure() override {
AddComponent(
new zeek::packet_analysis::Component("IPTunnel",
zeek::packet_analysis::IPTunnel::IPTunnelAnalyzer::Instantiate));
zeek::plugin::Configuration config;
config.name = "Zeek::IPTunnel";
config.description = "IPTunnel packet analyzer";
return config;
}
zeek::plugin::Configuration config;
config.name = "Zeek::IPTunnel";
config.description = "IPTunnel packet analyzer";
return config;
}
} plugin;
} plugin;
}
} // namespace zeek::plugin::Zeek_IPTunnel

View file

@ -4,27 +4,25 @@
using namespace zeek::packet_analysis::LinuxSLL;
LinuxSLLAnalyzer::LinuxSLLAnalyzer() : zeek::packet_analysis::Analyzer("LinuxSLL") { }
LinuxSLLAnalyzer::LinuxSLLAnalyzer() : zeek::packet_analysis::Analyzer("LinuxSLL") {}
bool LinuxSLLAnalyzer::AnalyzePacket(size_t len, const uint8_t* data, Packet* packet)
{
auto len_sll_hdr = sizeof(SLLHeader);
if ( len_sll_hdr >= len )
{
Weird("truncated_Linux_SLL_header", packet);
return false;
}
bool LinuxSLLAnalyzer::AnalyzePacket(size_t len, const uint8_t* data, Packet* packet) {
auto len_sll_hdr = sizeof(SLLHeader);
if ( len_sll_hdr >= len ) {
Weird("truncated_Linux_SLL_header", packet);
return false;
}
// Note: We assume to see an Ethertype and don't consider different ARPHRD_types
// (see https://www.tcpdump.org/linktypes/LINKTYPE_LINUX_SLL.html)
auto hdr = (const SLLHeader*)data;
// Note: We assume to see an Ethertype and don't consider different ARPHRD_types
// (see https://www.tcpdump.org/linktypes/LINKTYPE_LINUX_SLL.html)
auto hdr = (const SLLHeader*)data;
uint32_t protocol = ntohs(hdr->protocol_type);
packet->l2_src = (u_char*)&(hdr->addr);
uint32_t protocol = ntohs(hdr->protocol_type);
packet->l2_src = (u_char*)&(hdr->addr);
// SLL doesn't include a destination address in the header, but not setting l2_dst to something
// here will cause crashes elsewhere.
packet->l2_dst = Packet::L2_EMPTY_ADDR;
// SLL doesn't include a destination address in the header, but not setting l2_dst to something
// here will cause crashes elsewhere.
packet->l2_dst = Packet::L2_EMPTY_ADDR;
return ForwardPacket(len - len_sll_hdr, data + len_sll_hdr, packet, protocol);
}
return ForwardPacket(len - len_sll_hdr, data + len_sll_hdr, packet, protocol);
}

View file

@ -5,32 +5,26 @@
#include "zeek/packet_analysis/Analyzer.h"
#include "zeek/packet_analysis/Component.h"
namespace zeek::packet_analysis::LinuxSLL
{
namespace zeek::packet_analysis::LinuxSLL {
class LinuxSLLAnalyzer : public Analyzer
{
class LinuxSLLAnalyzer : public Analyzer {
public:
LinuxSLLAnalyzer();
~LinuxSLLAnalyzer() override = default;
LinuxSLLAnalyzer();
~LinuxSLLAnalyzer() override = default;
bool AnalyzePacket(size_t len, const uint8_t* data, Packet* packet) override;
bool AnalyzePacket(size_t len, const uint8_t* data, Packet* packet) override;
static zeek::packet_analysis::AnalyzerPtr Instantiate()
{
return std::make_shared<LinuxSLLAnalyzer>();
}
static zeek::packet_analysis::AnalyzerPtr Instantiate() { return std::make_shared<LinuxSLLAnalyzer>(); }
private:
// Structure layout is based on https://www.tcpdump.org/linktypes/LINKTYPE_LINUX_SLL.html
struct SLLHeader
{
uint16_t packet_type;
uint16_t arphrd_type;
uint16_t addr_len;
uint64_t addr;
uint16_t protocol_type;
} __attribute__((__packed__));
};
// Structure layout is based on https://www.tcpdump.org/linktypes/LINKTYPE_LINUX_SLL.html
struct SLLHeader {
uint16_t packet_type;
uint16_t arphrd_type;
uint16_t addr_len;
uint64_t addr;
uint16_t protocol_type;
} __attribute__((__packed__));
};
}
} // namespace zeek::packet_analysis::LinuxSLL

View file

@ -5,23 +5,21 @@
#include "zeek/packet_analysis/Component.h"
#include "zeek/packet_analysis/protocol/linux_sll/LinuxSLL.h"
namespace zeek::plugin::Zeek_LinuxSLL
{
namespace zeek::plugin::Zeek_LinuxSLL {
class Plugin final : public zeek::plugin::Plugin
{
class Plugin final : public zeek::plugin::Plugin {
public:
zeek::plugin::Configuration Configure() override
{
AddComponent(new zeek::packet_analysis::Component(
"LinuxSLL", zeek::packet_analysis::LinuxSLL::LinuxSLLAnalyzer::Instantiate));
zeek::plugin::Configuration Configure() override {
AddComponent(
new zeek::packet_analysis::Component("LinuxSLL",
zeek::packet_analysis::LinuxSLL::LinuxSLLAnalyzer::Instantiate));
zeek::plugin::Configuration config;
config.name = "Zeek::LinuxSLL";
config.description = "Linux cooked capture (SLL) packet analyzer";
return config;
}
zeek::plugin::Configuration config;
config.name = "Zeek::LinuxSLL";
config.description = "Linux cooked capture (SLL) packet analyzer";
return config;
}
} plugin;
} plugin;
}
} // namespace zeek::plugin::Zeek_LinuxSLL

View file

@ -4,27 +4,25 @@
using namespace zeek::packet_analysis::LinuxSLL2;
LinuxSLL2Analyzer::LinuxSLL2Analyzer() : zeek::packet_analysis::Analyzer("LinuxSLL2") { }
LinuxSLL2Analyzer::LinuxSLL2Analyzer() : zeek::packet_analysis::Analyzer("LinuxSLL2") {}
bool LinuxSLL2Analyzer::AnalyzePacket(size_t len, const uint8_t* data, Packet* packet)
{
auto len_sll2_hdr = sizeof(SLL2Header);
if ( len_sll2_hdr >= len )
{
Weird("truncated_Linux_SLL2_header", packet);
return false;
}
bool LinuxSLL2Analyzer::AnalyzePacket(size_t len, const uint8_t* data, Packet* packet) {
auto len_sll2_hdr = sizeof(SLL2Header);
if ( len_sll2_hdr >= len ) {
Weird("truncated_Linux_SLL2_header", packet);
return false;
}
// Note: We assume to see an Ethertype and don't consider different ARPHRD_types
// (see https://www.tcpdump.org/linktypes/LINKTYPE_LINUX_SLL2.html)
auto hdr = (const SLL2Header*)data;
// Note: We assume to see an Ethertype and don't consider different ARPHRD_types
// (see https://www.tcpdump.org/linktypes/LINKTYPE_LINUX_SLL2.html)
auto hdr = (const SLL2Header*)data;
uint32_t protocol = ntohs(hdr->protocol_type);
packet->l2_src = (u_char*)&(hdr->addr);
uint32_t protocol = ntohs(hdr->protocol_type);
packet->l2_src = (u_char*)&(hdr->addr);
// SLL doesn't include a destination address in the header, but not setting l2_dst to something
// here will cause crashes elsewhere.
packet->l2_dst = Packet::L2_EMPTY_ADDR;
// SLL doesn't include a destination address in the header, but not setting l2_dst to something
// here will cause crashes elsewhere.
packet->l2_dst = Packet::L2_EMPTY_ADDR;
return ForwardPacket(len - len_sll2_hdr, data + len_sll2_hdr, packet, protocol);
}
return ForwardPacket(len - len_sll2_hdr, data + len_sll2_hdr, packet, protocol);
}

View file

@ -5,34 +5,28 @@
#include "zeek/packet_analysis/Analyzer.h"
#include "zeek/packet_analysis/Component.h"
namespace zeek::packet_analysis::LinuxSLL2
{
namespace zeek::packet_analysis::LinuxSLL2 {
class LinuxSLL2Analyzer : public Analyzer
{
class LinuxSLL2Analyzer : public Analyzer {
public:
LinuxSLL2Analyzer();
~LinuxSLL2Analyzer() override = default;
LinuxSLL2Analyzer();
~LinuxSLL2Analyzer() override = default;
bool AnalyzePacket(size_t len, const uint8_t* data, Packet* packet) override;
bool AnalyzePacket(size_t len, const uint8_t* data, Packet* packet) override;
static zeek::packet_analysis::AnalyzerPtr Instantiate()
{
return std::make_shared<LinuxSLL2Analyzer>();
}
static zeek::packet_analysis::AnalyzerPtr Instantiate() { return std::make_shared<LinuxSLL2Analyzer>(); }
private:
// Structure layout is based on https://www.tcpdump.org/linktypes/LINKTYPE_LINUX_SLL2.html
struct SLL2Header
{
uint16_t protocol_type;
uint16_t reserved;
uint32_t interface_index;
uint16_t arphrd_type;
uint8_t packet_type;
uint8_t addr_len;
uint64_t addr;
} __attribute__((__packed__));
};
// Structure layout is based on https://www.tcpdump.org/linktypes/LINKTYPE_LINUX_SLL2.html
struct SLL2Header {
uint16_t protocol_type;
uint16_t reserved;
uint32_t interface_index;
uint16_t arphrd_type;
uint8_t packet_type;
uint8_t addr_len;
uint64_t addr;
} __attribute__((__packed__));
};
}
} // namespace zeek::packet_analysis::LinuxSLL2

View file

@ -5,23 +5,21 @@
#include "zeek/packet_analysis/Component.h"
#include "zeek/packet_analysis/protocol/linux_sll2/LinuxSLL2.h"
namespace zeek::plugin::Zeek_LinuxSLL2
{
namespace zeek::plugin::Zeek_LinuxSLL2 {
class Plugin final : public zeek::plugin::Plugin
{
class Plugin final : public zeek::plugin::Plugin {
public:
zeek::plugin::Configuration Configure() override
{
AddComponent(new zeek::packet_analysis::Component(
"LinuxSLL2", zeek::packet_analysis::LinuxSLL2::LinuxSLL2Analyzer::Instantiate));
zeek::plugin::Configuration Configure() override {
AddComponent(
new zeek::packet_analysis::Component("LinuxSLL2",
zeek::packet_analysis::LinuxSLL2::LinuxSLL2Analyzer::Instantiate));
zeek::plugin::Configuration config;
config.name = "Zeek::LinuxSLL2";
config.description = "Linux cooked capture version 2 (SLL2) packet analyzer";
return config;
}
zeek::plugin::Configuration config;
config.name = "Zeek::LinuxSLL2";
config.description = "Linux cooked capture version 2 (SLL2) packet analyzer";
return config;
}
} plugin;
} plugin;
}
} // namespace zeek::plugin::Zeek_LinuxSLL2

View file

@ -4,31 +4,28 @@
using namespace zeek::packet_analysis::LLC;
LLCAnalyzer::LLCAnalyzer() : zeek::packet_analysis::Analyzer("LLC") { }
LLCAnalyzer::LLCAnalyzer() : zeek::packet_analysis::Analyzer("LLC") {}
bool LLCAnalyzer::AnalyzePacket(size_t len, const uint8_t* data, Packet* packet)
{
// An LLC header is at least 3 bytes, check for that first.
if ( len < 3 )
{
Weird("truncated_llc_header", packet);
return false;
}
bool LLCAnalyzer::AnalyzePacket(size_t len, const uint8_t* data, Packet* packet) {
// An LLC header is at least 3 bytes, check for that first.
if ( len < 3 ) {
Weird("truncated_llc_header", packet);
return false;
}
// If the control field doesn't have an unnumbered PDU, the header is actually 4
// bytes long. Whether this is unnumbered is denoted by the last two bits being
// set.
size_t llc_header_len = 3;
if ( (data[2] & 0x03) != 0x03 )
llc_header_len++;
// If the control field doesn't have an unnumbered PDU, the header is actually 4
// bytes long. Whether this is unnumbered is denoted by the last two bits being
// set.
size_t llc_header_len = 3;
if ( (data[2] & 0x03) != 0x03 )
llc_header_len++;
if ( len < llc_header_len )
{
Weird("truncated_llc_header", packet);
return false;
}
if ( len < llc_header_len ) {
Weird("truncated_llc_header", packet);
return false;
}
// The destination SAP should be the next protocol in the chain, so forward
// based on that value. The DSAP is the first byte in header.
return ForwardPacket(len, data, packet, data[0]);
}
// The destination SAP should be the next protocol in the chain, so forward
// based on that value. The DSAP is the first byte in header.
return ForwardPacket(len, data, packet, data[0]);
}

View file

@ -5,21 +5,16 @@
#include "zeek/packet_analysis/Analyzer.h"
#include "zeek/packet_analysis/Component.h"
namespace zeek::packet_analysis::LLC
{
namespace zeek::packet_analysis::LLC {
class LLCAnalyzer : public Analyzer
{
class LLCAnalyzer : public Analyzer {
public:
LLCAnalyzer();
~LLCAnalyzer() override = default;
LLCAnalyzer();
~LLCAnalyzer() override = default;
bool AnalyzePacket(size_t len, const uint8_t* data, Packet* packet) override;
bool AnalyzePacket(size_t len, const uint8_t* data, Packet* packet) override;
static zeek::packet_analysis::AnalyzerPtr Instantiate()
{
return std::make_shared<LLCAnalyzer>();
}
};
static zeek::packet_analysis::AnalyzerPtr Instantiate() { return std::make_shared<LLCAnalyzer>(); }
};
}
} // namespace zeek::packet_analysis::LLC

View file

@ -5,23 +5,19 @@
#include "zeek/packet_analysis/Component.h"
#include "zeek/packet_analysis/protocol/llc/LLC.h"
namespace zeek::plugin::Zeek_LLC
{
namespace zeek::plugin::Zeek_LLC {
class Plugin final : public zeek::plugin::Plugin
{
class Plugin final : public zeek::plugin::Plugin {
public:
zeek::plugin::Configuration Configure() override
{
AddComponent(new zeek::packet_analysis::Component(
"LLC", zeek::packet_analysis::LLC::LLCAnalyzer::Instantiate));
zeek::plugin::Configuration Configure() override {
AddComponent(new zeek::packet_analysis::Component("LLC", zeek::packet_analysis::LLC::LLCAnalyzer::Instantiate));
zeek::plugin::Configuration config;
config.name = "Zeek::LLC";
config.description = "LLC packet analyzer";
return config;
}
zeek::plugin::Configuration config;
config.name = "Zeek::LLC";
config.description = "LLC packet analyzer";
return config;
}
} plugin;
} plugin;
}
} // namespace zeek::plugin::Zeek_LLC

View file

@ -4,27 +4,24 @@
using namespace zeek::packet_analysis::MPLS;
MPLSAnalyzer::MPLSAnalyzer() : zeek::packet_analysis::Analyzer("MPLS") { }
MPLSAnalyzer::MPLSAnalyzer() : zeek::packet_analysis::Analyzer("MPLS") {}
bool MPLSAnalyzer::AnalyzePacket(size_t len, const uint8_t* data, Packet* packet)
{
// Skip the MPLS label stack.
bool end_of_stack = false;
bool MPLSAnalyzer::AnalyzePacket(size_t len, const uint8_t* data, Packet* packet) {
// Skip the MPLS label stack.
bool end_of_stack = false;
while ( ! end_of_stack )
{
if ( 4 >= len )
{
Weird("truncated_link_header", packet);
return false;
}
while ( ! end_of_stack ) {
if ( 4 >= len ) {
Weird("truncated_link_header", packet);
return false;
}
end_of_stack = *(data + 2u) & 0x01;
data += 4;
len -= 4;
}
end_of_stack = *(data + 2u) & 0x01;
data += 4;
len -= 4;
}
// According to RFC3032 the encapsulated protocol is not encoded.
// We use the configured default analyzer.
return ForwardPacket(len, data, packet);
}
// According to RFC3032 the encapsulated protocol is not encoded.
// We use the configured default analyzer.
return ForwardPacket(len, data, packet);
}

View file

@ -5,21 +5,16 @@
#include "zeek/packet_analysis/Analyzer.h"
#include "zeek/packet_analysis/Component.h"
namespace zeek::packet_analysis::MPLS
{
namespace zeek::packet_analysis::MPLS {
class MPLSAnalyzer : public zeek::packet_analysis::Analyzer
{
class MPLSAnalyzer : public zeek::packet_analysis::Analyzer {
public:
MPLSAnalyzer();
~MPLSAnalyzer() override = default;
MPLSAnalyzer();
~MPLSAnalyzer() override = default;
bool AnalyzePacket(size_t len, const uint8_t* data, Packet* packet) override;
bool AnalyzePacket(size_t len, const uint8_t* data, Packet* packet) override;
static zeek::packet_analysis::AnalyzerPtr Instantiate()
{
return std::make_shared<MPLSAnalyzer>();
}
};
static zeek::packet_analysis::AnalyzerPtr Instantiate() { return std::make_shared<MPLSAnalyzer>(); }
};
}
} // namespace zeek::packet_analysis::MPLS

View file

@ -5,23 +5,20 @@
#include "zeek/packet_analysis/Component.h"
#include "zeek/packet_analysis/protocol/mpls/MPLS.h"
namespace zeek::plugin::Zeek_MPLS
{
namespace zeek::plugin::Zeek_MPLS {
class Plugin final : public zeek::plugin::Plugin
{
class Plugin final : public zeek::plugin::Plugin {
public:
zeek::plugin::Configuration Configure() override
{
AddComponent(new zeek::packet_analysis::Component(
"MPLS", zeek::packet_analysis::MPLS::MPLSAnalyzer::Instantiate));
zeek::plugin::Configuration Configure() override {
AddComponent(
new zeek::packet_analysis::Component("MPLS", zeek::packet_analysis::MPLS::MPLSAnalyzer::Instantiate));
zeek::plugin::Configuration config;
config.name = "Zeek::MPLS";
config.description = "MPLS packet analyzer";
return config;
}
zeek::plugin::Configuration config;
config.name = "Zeek::MPLS";
config.description = "MPLS packet analyzer";
return config;
}
} plugin;
} plugin;
}
} // namespace zeek::plugin::Zeek_MPLS

View file

@ -4,80 +4,71 @@
using namespace zeek::packet_analysis::NFLog;
NFLogAnalyzer::NFLogAnalyzer() : zeek::packet_analysis::Analyzer("NFLog") { }
NFLogAnalyzer::NFLogAnalyzer() : zeek::packet_analysis::Analyzer("NFLog") {}
bool NFLogAnalyzer::AnalyzePacket(size_t len, const uint8_t* data, Packet* packet)
{
if ( 4 >= len )
{
Weird("truncated_nflog_header", packet);
return false;
}
bool NFLogAnalyzer::AnalyzePacket(size_t len, const uint8_t* data, Packet* packet) {
if ( 4 >= len ) {
Weird("truncated_nflog_header", packet);
return false;
}
// See https://www.tcpdump.org/linktypes/LINKTYPE_NFLOG.html
uint32_t protocol = data[0];
uint8_t version = data[1];
// See https://www.tcpdump.org/linktypes/LINKTYPE_NFLOG.html
uint32_t protocol = data[0];
uint8_t version = data[1];
if ( version != 0 )
{
Weird("unknown_nflog_version", packet);
return false;
}
if ( version != 0 ) {
Weird("unknown_nflog_version", packet);
return false;
}
// Skip to TLVs.
data += 4;
len -= 4;
// Skip to TLVs.
data += 4;
len -= 4;
uint16_t tlv_len;
uint16_t tlv_type;
uint16_t tlv_len;
uint16_t tlv_type;
while ( true )
{
if ( 4 >= len )
{
Weird("nflog_no_pcap_payload", packet);
return false;
}
while ( true ) {
if ( 4 >= len ) {
Weird("nflog_no_pcap_payload", packet);
return false;
}
// TLV Type and Length values are specified in host byte order
// (libpcap should have done any needed byteswapping already).
// TLV Type and Length values are specified in host byte order
// (libpcap should have done any needed byteswapping already).
tlv_len = *(reinterpret_cast<const uint16_t*>(data));
tlv_type = *(reinterpret_cast<const uint16_t*>(data + 2));
tlv_len = *(reinterpret_cast<const uint16_t*>(data));
tlv_type = *(reinterpret_cast<const uint16_t*>(data + 2));
auto constexpr nflog_type_payload = 9;
auto constexpr nflog_type_payload = 9;
if ( tlv_type == nflog_type_payload )
{
// The raw packet payload follows this TLV.
data += 4;
len -= 4;
break;
}
else
{
// The Length value includes the 4 octets for the Type and
// Length values, but TLVs are also implicitly padded to
// 32-bit alignments (that padding may not be included in
// the Length value).
if ( tlv_type == nflog_type_payload ) {
// The raw packet payload follows this TLV.
data += 4;
len -= 4;
break;
}
else {
// The Length value includes the 4 octets for the Type and
// Length values, but TLVs are also implicitly padded to
// 32-bit alignments (that padding may not be included in
// the Length value).
if ( tlv_len < 4 )
{
Weird("nflog_bad_tlv_len", packet);
return false;
}
else
{
auto rem = tlv_len % 4;
if ( tlv_len < 4 ) {
Weird("nflog_bad_tlv_len", packet);
return false;
}
else {
auto rem = tlv_len % 4;
if ( rem != 0 )
tlv_len += 4 - rem;
}
if ( rem != 0 )
tlv_len += 4 - rem;
}
data += tlv_len;
len -= tlv_len;
}
}
data += tlv_len;
len -= tlv_len;
}
}
return ForwardPacket(len, data, packet, protocol);
}
return ForwardPacket(len, data, packet, protocol);
}

View file

@ -5,18 +5,16 @@
#include "zeek/packet_analysis/Analyzer.h"
#include "zeek/packet_analysis/Component.h"
namespace zeek::packet_analysis::NFLog
{
namespace zeek::packet_analysis::NFLog {
class NFLogAnalyzer : public Analyzer
{
class NFLogAnalyzer : public Analyzer {
public:
NFLogAnalyzer();
~NFLogAnalyzer() override = default;
NFLogAnalyzer();
~NFLogAnalyzer() override = default;
bool AnalyzePacket(size_t len, const uint8_t* data, Packet* packet) override;
bool AnalyzePacket(size_t len, const uint8_t* data, Packet* packet) override;
static AnalyzerPtr Instantiate() { return std::make_shared<NFLogAnalyzer>(); }
};
static AnalyzerPtr Instantiate() { return std::make_shared<NFLogAnalyzer>(); }
};
}
} // namespace zeek::packet_analysis::NFLog

View file

@ -5,22 +5,19 @@
#include "zeek/packet_analysis/Component.h"
#include "zeek/packet_analysis/protocol/nflog/NFLog.h"
namespace zeek::plugin::Zeek_NFLog
{
namespace zeek::plugin::Zeek_NFLog {
class Plugin final : public zeek::plugin::Plugin
{
class Plugin final : public zeek::plugin::Plugin {
public:
zeek::plugin::Configuration Configure() override
{
AddComponent(new zeek::packet_analysis::Component(
"NFLog", zeek::packet_analysis::NFLog::NFLogAnalyzer::Instantiate));
zeek::plugin::Configuration Configure() override {
AddComponent(
new zeek::packet_analysis::Component("NFLog", zeek::packet_analysis::NFLog::NFLogAnalyzer::Instantiate));
zeek::plugin::Configuration config;
config.name = "Zeek::NFLog";
config.description = "NFLog packet analyzer";
return config;
}
} plugin;
zeek::plugin::Configuration config;
config.name = "Zeek::NFLog";
config.description = "NFLog packet analyzer";
return config;
}
} plugin;
}
} // namespace zeek::plugin::Zeek_NFLog

View file

@ -4,11 +4,10 @@
using namespace zeek::packet_analysis::Novell_802_3;
Novell_802_3Analyzer::Novell_802_3Analyzer() : zeek::packet_analysis::Analyzer("Novell_802_3") { }
Novell_802_3Analyzer::Novell_802_3Analyzer() : zeek::packet_analysis::Analyzer("Novell_802_3") {}
bool Novell_802_3Analyzer::AnalyzePacket(size_t len, const uint8_t* data, Packet* packet)
{
// Attempt to forward into the default analyzer, if one exists. This should be an IPX analyzer,
// but one doesn't exist yet.
return ForwardPacket(len, data, packet);
}
bool Novell_802_3Analyzer::AnalyzePacket(size_t len, const uint8_t* data, Packet* packet) {
// Attempt to forward into the default analyzer, if one exists. This should be an IPX analyzer,
// but one doesn't exist yet.
return ForwardPacket(len, data, packet);
}

View file

@ -5,21 +5,16 @@
#include "zeek/packet_analysis/Analyzer.h"
#include "zeek/packet_analysis/Component.h"
namespace zeek::packet_analysis::Novell_802_3
{
namespace zeek::packet_analysis::Novell_802_3 {
class Novell_802_3Analyzer : public Analyzer
{
class Novell_802_3Analyzer : public Analyzer {
public:
Novell_802_3Analyzer();
~Novell_802_3Analyzer() override = default;
Novell_802_3Analyzer();
~Novell_802_3Analyzer() override = default;
bool AnalyzePacket(size_t len, const uint8_t* data, Packet* packet) override;
bool AnalyzePacket(size_t len, const uint8_t* data, Packet* packet) override;
static zeek::packet_analysis::AnalyzerPtr Instantiate()
{
return std::make_shared<Novell_802_3Analyzer>();
}
};
static zeek::packet_analysis::AnalyzerPtr Instantiate() { return std::make_shared<Novell_802_3Analyzer>(); }
};
}
} // namespace zeek::packet_analysis::Novell_802_3

View file

@ -5,24 +5,20 @@
#include "zeek/packet_analysis/Component.h"
#include "zeek/packet_analysis/protocol/novell_802_3/Novell_802_3.h"
namespace zeek::plugin::Zeek_Novell_802_3
{
namespace zeek::plugin::Zeek_Novell_802_3 {
class Plugin final : public zeek::plugin::Plugin
{
class Plugin final : public zeek::plugin::Plugin {
public:
zeek::plugin::Configuration Configure() override
{
AddComponent(new zeek::packet_analysis::Component(
"NOVELL_802_3",
zeek::packet_analysis::Novell_802_3::Novell_802_3Analyzer::Instantiate));
zeek::plugin::Configuration Configure() override {
AddComponent(new zeek::packet_analysis::Component("NOVELL_802_3", zeek::packet_analysis::Novell_802_3::
Novell_802_3Analyzer::Instantiate));
zeek::plugin::Configuration config;
config.name = "Zeek::NOVELL_802_3";
config.description = "Novell 802.3 variantx packet analyzer";
return config;
}
zeek::plugin::Configuration config;
config.name = "Zeek::NOVELL_802_3";
config.description = "Novell 802.3 variantx packet analyzer";
return config;
}
} plugin;
} plugin;
}
} // namespace zeek::plugin::Zeek_Novell_802_3

View file

@ -4,17 +4,15 @@
using namespace zeek::packet_analysis::Null;
NullAnalyzer::NullAnalyzer() : zeek::packet_analysis::Analyzer("Null") { }
NullAnalyzer::NullAnalyzer() : zeek::packet_analysis::Analyzer("Null") {}
bool NullAnalyzer::AnalyzePacket(size_t len, const uint8_t* data, Packet* packet)
{
if ( 4 >= len )
{
Weird("null_analyzer_failed", packet);
return false;
}
bool NullAnalyzer::AnalyzePacket(size_t len, const uint8_t* data, Packet* packet) {
if ( 4 >= len ) {
Weird("null_analyzer_failed", packet);
return false;
}
uint32_t protocol = (data[3] << 24) + (data[2] << 16) + (data[1] << 8) + data[0];
// skip link header
return ForwardPacket(len - 4, data + 4, packet, protocol);
}
uint32_t protocol = (data[3] << 24) + (data[2] << 16) + (data[1] << 8) + data[0];
// skip link header
return ForwardPacket(len - 4, data + 4, packet, protocol);
}

View file

@ -5,21 +5,16 @@
#include "zeek/packet_analysis/Analyzer.h"
#include "zeek/packet_analysis/Component.h"
namespace zeek::packet_analysis::Null
{
namespace zeek::packet_analysis::Null {
class NullAnalyzer : public Analyzer
{
class NullAnalyzer : public Analyzer {
public:
NullAnalyzer();
~NullAnalyzer() override = default;
NullAnalyzer();
~NullAnalyzer() override = default;
bool AnalyzePacket(size_t len, const uint8_t* data, Packet* packet) override;
bool AnalyzePacket(size_t len, const uint8_t* data, Packet* packet) override;
static zeek::packet_analysis::AnalyzerPtr Instantiate()
{
return std::make_shared<NullAnalyzer>();
}
};
static zeek::packet_analysis::AnalyzerPtr Instantiate() { return std::make_shared<NullAnalyzer>(); }
};
}
} // namespace zeek::packet_analysis::Null

View file

@ -5,23 +5,20 @@
#include "zeek/packet_analysis/Component.h"
#include "zeek/packet_analysis/protocol/null/Null.h"
namespace zeek::plugin::Zeek_Null
{
namespace zeek::plugin::Zeek_Null {
class Plugin final : public zeek::plugin::Plugin
{
class Plugin final : public zeek::plugin::Plugin {
public:
zeek::plugin::Configuration Configure() override
{
AddComponent(new zeek::packet_analysis::Component(
"Null", zeek::packet_analysis::Null::NullAnalyzer::Instantiate));
zeek::plugin::Configuration Configure() override {
AddComponent(
new zeek::packet_analysis::Component("Null", zeek::packet_analysis::Null::NullAnalyzer::Instantiate));
zeek::plugin::Configuration config;
config.name = "Zeek::Null";
config.description = "Null packet analyzer";
return config;
}
zeek::plugin::Configuration config;
config.name = "Zeek::Null";
config.description = "Null packet analyzer";
return config;
}
} plugin;
} plugin;
}
} // namespace zeek::plugin::Zeek_Null

View file

@ -7,16 +7,14 @@ using namespace zeek::packet_analysis::PBB;
constexpr int PBB_LEN = 18;
constexpr int PBB_C_DST_OFF = 4;
PBBAnalyzer::PBBAnalyzer() : zeek::packet_analysis::Analyzer("PBB") { }
PBBAnalyzer::PBBAnalyzer() : zeek::packet_analysis::Analyzer("PBB") {}
bool PBBAnalyzer::AnalyzePacket(size_t len, const uint8_t* data, Packet* packet)
{
if ( PBB_LEN >= len )
{
Weird("truncated_PBB_header", packet);
return false;
}
bool PBBAnalyzer::AnalyzePacket(size_t len, const uint8_t* data, Packet* packet) {
if ( PBB_LEN >= len ) {
Weird("truncated_PBB_header", packet);
return false;
}
// pass this on to the ethernet analyzer
return ForwardPacket(len - PBB_C_DST_OFF, data + PBB_C_DST_OFF, packet);
}
// pass this on to the ethernet analyzer
return ForwardPacket(len - PBB_C_DST_OFF, data + PBB_C_DST_OFF, packet);
}

View file

@ -5,21 +5,16 @@
#include "zeek/packet_analysis/Analyzer.h"
#include "zeek/packet_analysis/Component.h"
namespace zeek::packet_analysis::PBB
{
namespace zeek::packet_analysis::PBB {
class PBBAnalyzer : public Analyzer
{
class PBBAnalyzer : public Analyzer {
public:
PBBAnalyzer();
~PBBAnalyzer() override = default;
PBBAnalyzer();
~PBBAnalyzer() override = default;
bool AnalyzePacket(size_t len, const uint8_t* data, Packet* packet) override;
bool AnalyzePacket(size_t len, const uint8_t* data, Packet* packet) override;
static zeek::packet_analysis::AnalyzerPtr Instantiate()
{
return std::make_shared<PBBAnalyzer>();
}
};
static zeek::packet_analysis::AnalyzerPtr Instantiate() { return std::make_shared<PBBAnalyzer>(); }
};
}
} // namespace zeek::packet_analysis::PBB

View file

@ -5,23 +5,19 @@
#include "zeek/packet_analysis/Component.h"
#include "zeek/packet_analysis/protocol/pbb/PBB.h"
namespace zeek::plugin::Zeek_PBB
{
namespace zeek::plugin::Zeek_PBB {
class Plugin final : public zeek::plugin::Plugin
{
class Plugin final : public zeek::plugin::Plugin {
public:
zeek::plugin::Configuration Configure() override
{
AddComponent(new zeek::packet_analysis::Component(
"PBB", zeek::packet_analysis::PBB::PBBAnalyzer::Instantiate));
zeek::plugin::Configuration Configure() override {
AddComponent(new zeek::packet_analysis::Component("PBB", zeek::packet_analysis::PBB::PBBAnalyzer::Instantiate));
zeek::plugin::Configuration config;
config.name = "Zeek::PBB";
config.description = "PBB packet analyzer";
return config;
}
zeek::plugin::Configuration config;
config.name = "Zeek::PBB";
config.description = "PBB packet analyzer";
return config;
}
} plugin;
} plugin;
}
} // namespace zeek::plugin::Zeek_PBB

View file

@ -4,37 +4,33 @@
using namespace zeek::packet_analysis::PPP;
PPPAnalyzer::PPPAnalyzer() : zeek::packet_analysis::Analyzer("PPP") { }
PPPAnalyzer::PPPAnalyzer() : zeek::packet_analysis::Analyzer("PPP") {}
bool PPPAnalyzer::AnalyzePacket(size_t len, const uint8_t* data, Packet* packet)
{
// Analyzer is meant to handle DLT_PPP.
//
// From https://www.tcpdump.org/linktypes.html for LINKTYPE_PPP (0x9):
//
// PPP, as per RFC 1661 and RFC 1662; if the first 2 bytes are 0xff and 0x03,
// it's PPP in HDLC-like framing, with the PPP header following those two bytes,
// otherwise it's PPP without framing, and the packet begins with the PPP header.
// The data in the frame is not octet-stuffed or bit-stuffed.
if ( 2 >= len )
{
Weird("truncated_ppp_header", packet);
return false;
}
bool PPPAnalyzer::AnalyzePacket(size_t len, const uint8_t* data, Packet* packet) {
// Analyzer is meant to handle DLT_PPP.
//
// From https://www.tcpdump.org/linktypes.html for LINKTYPE_PPP (0x9):
//
// PPP, as per RFC 1661 and RFC 1662; if the first 2 bytes are 0xff and 0x03,
// it's PPP in HDLC-like framing, with the PPP header following those two bytes,
// otherwise it's PPP without framing, and the packet begins with the PPP header.
// The data in the frame is not octet-stuffed or bit-stuffed.
if ( 2 >= len ) {
Weird("truncated_ppp_header", packet);
return false;
}
if ( data[0] == 0xff && data[1] == 0x03 )
{
// HDLC-Framing
if ( 4 >= len )
{
Weird("truncated_ppp_hdlc_header", packet);
return false;
}
if ( data[0] == 0xff && data[1] == 0x03 ) {
// HDLC-Framing
if ( 4 >= len ) {
Weird("truncated_ppp_hdlc_header", packet);
return false;
}
uint32_t protocol = (data[2] << 8) + data[3];
return ForwardPacket(len - 4, data + 4, packet, protocol);
}
uint32_t protocol = (data[2] << 8) + data[3];
return ForwardPacket(len - 4, data + 4, packet, protocol);
}
uint32_t protocol = (data[0] << 8) + data[1];
return ForwardPacket(len - 2, data + 2, packet, protocol);
}
uint32_t protocol = (data[0] << 8) + data[1];
return ForwardPacket(len - 2, data + 2, packet, protocol);
}

View file

@ -5,21 +5,16 @@
#include "zeek/packet_analysis/Analyzer.h"
#include "zeek/packet_analysis/Component.h"
namespace zeek::packet_analysis::PPP
{
namespace zeek::packet_analysis::PPP {
class PPPAnalyzer : public Analyzer
{
class PPPAnalyzer : public Analyzer {
public:
PPPAnalyzer();
~PPPAnalyzer() override = default;
PPPAnalyzer();
~PPPAnalyzer() override = default;
bool AnalyzePacket(size_t len, const uint8_t* data, Packet* packet) override;
bool AnalyzePacket(size_t len, const uint8_t* data, Packet* packet) override;
static zeek::packet_analysis::AnalyzerPtr Instantiate()
{
return std::make_shared<PPPAnalyzer>();
}
};
static zeek::packet_analysis::AnalyzerPtr Instantiate() { return std::make_shared<PPPAnalyzer>(); }
};
}
} // namespace zeek::packet_analysis::PPP

View file

@ -5,23 +5,19 @@
#include "zeek/packet_analysis/Component.h"
#include "zeek/packet_analysis/protocol/ppp/PPP.h"
namespace zeek::plugin::Zeek_PPP
{
namespace zeek::plugin::Zeek_PPP {
class Plugin final : public zeek::plugin::Plugin
{
class Plugin final : public zeek::plugin::Plugin {
public:
zeek::plugin::Configuration Configure() override
{
AddComponent(new zeek::packet_analysis::Component(
"PPP", zeek::packet_analysis::PPP::PPPAnalyzer::Instantiate));
zeek::plugin::Configuration Configure() override {
AddComponent(new zeek::packet_analysis::Component("PPP", zeek::packet_analysis::PPP::PPPAnalyzer::Instantiate));
zeek::plugin::Configuration config;
config.name = "Zeek::PPP";
config.description = "PPP packet analyzer";
return config;
}
zeek::plugin::Configuration config;
config.name = "Zeek::PPP";
config.description = "PPP packet analyzer";
return config;
}
} plugin;
} plugin;
}
} // namespace zeek::plugin::Zeek_PPP

View file

@ -4,18 +4,16 @@
using namespace zeek::packet_analysis::PPPSerial;
PPPSerialAnalyzer::PPPSerialAnalyzer() : zeek::packet_analysis::Analyzer("PPPSerial") { }
PPPSerialAnalyzer::PPPSerialAnalyzer() : zeek::packet_analysis::Analyzer("PPPSerial") {}
bool PPPSerialAnalyzer::AnalyzePacket(size_t len, const uint8_t* data, Packet* packet)
{
if ( 4 >= len )
{
Weird("truncated_ppp_serial_header", packet);
return false;
}
bool PPPSerialAnalyzer::AnalyzePacket(size_t len, const uint8_t* data, Packet* packet) {
if ( 4 >= len ) {
Weird("truncated_ppp_serial_header", packet);
return false;
}
// Extract protocol identifier
uint32_t protocol = (data[2] << 8) + data[3];
// skip link header
return ForwardPacket(len - 4, data + 4, packet, protocol);
}
// Extract protocol identifier
uint32_t protocol = (data[2] << 8) + data[3];
// skip link header
return ForwardPacket(len - 4, data + 4, packet, protocol);
}

View file

@ -5,21 +5,16 @@
#include "zeek/packet_analysis/Analyzer.h"
#include "zeek/packet_analysis/Component.h"
namespace zeek::packet_analysis::PPPSerial
{
namespace zeek::packet_analysis::PPPSerial {
class PPPSerialAnalyzer : public Analyzer
{
class PPPSerialAnalyzer : public Analyzer {
public:
PPPSerialAnalyzer();
~PPPSerialAnalyzer() override = default;
PPPSerialAnalyzer();
~PPPSerialAnalyzer() override = default;
bool AnalyzePacket(size_t len, const uint8_t* data, Packet* packet) override;
bool AnalyzePacket(size_t len, const uint8_t* data, Packet* packet) override;
static zeek::packet_analysis::AnalyzerPtr Instantiate()
{
return std::make_shared<PPPSerialAnalyzer>();
}
};
static zeek::packet_analysis::AnalyzerPtr Instantiate() { return std::make_shared<PPPSerialAnalyzer>(); }
};
}
} // namespace zeek::packet_analysis::PPPSerial

View file

@ -5,23 +5,21 @@
#include "zeek/packet_analysis/Component.h"
#include "zeek/packet_analysis/protocol/ppp_serial/PPPSerial.h"
namespace zeek::plugin::Zeek_PPPSerial
{
namespace zeek::plugin::Zeek_PPPSerial {
class Plugin final : public zeek::plugin::Plugin
{
class Plugin final : public zeek::plugin::Plugin {
public:
zeek::plugin::Configuration Configure() override
{
AddComponent(new zeek::packet_analysis::Component(
"PPPSerial", zeek::packet_analysis::PPPSerial::PPPSerialAnalyzer::Instantiate));
zeek::plugin::Configuration Configure() override {
AddComponent(
new zeek::packet_analysis::Component("PPPSerial",
zeek::packet_analysis::PPPSerial::PPPSerialAnalyzer::Instantiate));
zeek::plugin::Configuration config;
config.name = "Zeek::PPPSerial";
config.description = "PPPSerial packet analyzer";
return config;
}
zeek::plugin::Configuration config;
config.name = "Zeek::PPPSerial";
config.description = "PPPSerial packet analyzer";
return config;
}
} plugin;
} plugin;
}
} // namespace zeek::plugin::Zeek_PPPSerial

View file

@ -4,18 +4,16 @@
using namespace zeek::packet_analysis::PPPoE;
PPPoEAnalyzer::PPPoEAnalyzer() : zeek::packet_analysis::Analyzer("PPPoE") { }
PPPoEAnalyzer::PPPoEAnalyzer() : zeek::packet_analysis::Analyzer("PPPoE") {}
bool PPPoEAnalyzer::AnalyzePacket(size_t len, const uint8_t* data, Packet* packet)
{
if ( 8 >= len )
{
Weird("truncated_pppoe_header", packet);
return false;
}
bool PPPoEAnalyzer::AnalyzePacket(size_t len, const uint8_t* data, Packet* packet) {
if ( 8 >= len ) {
Weird("truncated_pppoe_header", packet);
return false;
}
// Extract protocol identifier
uint32_t protocol = (data[6] << 8u) + data[7];
// Skip the PPPoE session and PPP header
return ForwardPacket(len - 8, data + 8, packet, protocol);
}
// Extract protocol identifier
uint32_t protocol = (data[6] << 8u) + data[7];
// Skip the PPPoE session and PPP header
return ForwardPacket(len - 8, data + 8, packet, protocol);
}

View file

@ -5,21 +5,16 @@
#include "zeek/packet_analysis/Analyzer.h"
#include "zeek/packet_analysis/Component.h"
namespace zeek::packet_analysis::PPPoE
{
namespace zeek::packet_analysis::PPPoE {
class PPPoEAnalyzer : public Analyzer
{
class PPPoEAnalyzer : public Analyzer {
public:
PPPoEAnalyzer();
~PPPoEAnalyzer() override = default;
PPPoEAnalyzer();
~PPPoEAnalyzer() override = default;
bool AnalyzePacket(size_t len, const uint8_t* data, Packet* packet) override;
bool AnalyzePacket(size_t len, const uint8_t* data, Packet* packet) override;
static zeek::packet_analysis::AnalyzerPtr Instantiate()
{
return std::make_shared<PPPoEAnalyzer>();
}
};
static zeek::packet_analysis::AnalyzerPtr Instantiate() { return std::make_shared<PPPoEAnalyzer>(); }
};
}
} // namespace zeek::packet_analysis::PPPoE

View file

@ -5,23 +5,20 @@
#include "zeek/packet_analysis/Component.h"
#include "zeek/packet_analysis/protocol/pppoe/PPPoE.h"
namespace zeek::plugin::Zeek_PPPoE
{
namespace zeek::plugin::Zeek_PPPoE {
class Plugin final : public zeek::plugin::Plugin
{
class Plugin final : public zeek::plugin::Plugin {
public:
zeek::plugin::Configuration Configure() override
{
AddComponent(new zeek::packet_analysis::Component(
"PPPoE", zeek::packet_analysis::PPPoE::PPPoEAnalyzer::Instantiate));
zeek::plugin::Configuration Configure() override {
AddComponent(
new zeek::packet_analysis::Component("PPPoE", zeek::packet_analysis::PPPoE::PPPoEAnalyzer::Instantiate));
zeek::plugin::Configuration config;
config.name = "Zeek::PPPoE";
config.description = "PPPoE packet analyzer";
return config;
}
zeek::plugin::Configuration config;
config.name = "Zeek::PPPoE";
config.description = "PPPoE packet analyzer";
return config;
}
} plugin;
} plugin;
}
} // namespace zeek::plugin::Zeek_PPPoE

View file

@ -5,23 +5,20 @@
#include "zeek/packet_analysis/Component.h"
#include "zeek/packet_analysis/protocol/root/Root.h"
namespace zeek::plugin::Zeek_Root
{
namespace zeek::plugin::Zeek_Root {
class Plugin final : public zeek::plugin::Plugin
{
class Plugin final : public zeek::plugin::Plugin {
public:
zeek::plugin::Configuration Configure() override
{
AddComponent(new zeek::packet_analysis::Component(
"Root", zeek::packet_analysis::Root::RootAnalyzer::Instantiate));
zeek::plugin::Configuration Configure() override {
AddComponent(
new zeek::packet_analysis::Component("Root", zeek::packet_analysis::Root::RootAnalyzer::Instantiate));
zeek::plugin::Configuration config;
config.name = "Zeek::Root";
config.description = "Root packet analyzer";
return config;
}
zeek::plugin::Configuration config;
config.name = "Zeek::Root";
config.description = "Root packet analyzer";
return config;
}
} plugin;
} plugin;
}
} // namespace zeek::plugin::Zeek_Root

View file

@ -4,9 +4,8 @@
using namespace zeek::packet_analysis::Root;
RootAnalyzer::RootAnalyzer() : zeek::packet_analysis::Analyzer("Root") { }
RootAnalyzer::RootAnalyzer() : zeek::packet_analysis::Analyzer("Root") {}
bool RootAnalyzer::AnalyzePacket(size_t len, const uint8_t* data, Packet* packet)
{
reporter->InternalError("AnalyzePacket() was called for the root analyzer.");
}
bool RootAnalyzer::AnalyzePacket(size_t len, const uint8_t* data, Packet* packet) {
reporter->InternalError("AnalyzePacket() was called for the root analyzer.");
}

View file

@ -5,21 +5,16 @@
#include "zeek/packet_analysis/Analyzer.h"
#include "zeek/packet_analysis/Component.h"
namespace zeek::packet_analysis::Root
{
namespace zeek::packet_analysis::Root {
class RootAnalyzer : public Analyzer
{
class RootAnalyzer : public Analyzer {
public:
RootAnalyzer();
~RootAnalyzer() override = default;
RootAnalyzer();
~RootAnalyzer() override = default;
bool AnalyzePacket(size_t len, const uint8_t* data, Packet* packet) override;
bool AnalyzePacket(size_t len, const uint8_t* data, Packet* packet) override;
static zeek::packet_analysis::AnalyzerPtr Instantiate()
{
return std::make_shared<RootAnalyzer>();
}
};
static zeek::packet_analysis::AnalyzerPtr Instantiate() { return std::make_shared<RootAnalyzer>(); }
};
}
} // namespace zeek::packet_analysis::Root

View file

@ -5,23 +5,20 @@
#include "zeek/packet_analysis/Component.h"
#include "zeek/packet_analysis/protocol/skip/Skip.h"
namespace zeek::plugin::Zeek_Skip
{
namespace zeek::plugin::Zeek_Skip {
class Plugin final : public zeek::plugin::Plugin
{
class Plugin final : public zeek::plugin::Plugin {
public:
zeek::plugin::Configuration Configure() override
{
AddComponent(new zeek::packet_analysis::Component(
"Skip", zeek::packet_analysis::Skip::SkipAnalyzer::Instantiate));
zeek::plugin::Configuration Configure() override {
AddComponent(
new zeek::packet_analysis::Component("Skip", zeek::packet_analysis::Skip::SkipAnalyzer::Instantiate));
zeek::plugin::Configuration config;
config.name = "Zeek::Skip";
config.description = "Skip packet analyzer";
return config;
}
zeek::plugin::Configuration config;
config.name = "Zeek::Skip";
config.description = "Skip packet analyzer";
return config;
}
} plugin;
} plugin;
}
} // namespace zeek::plugin::Zeek_Skip

View file

@ -4,20 +4,18 @@
using namespace zeek::packet_analysis::Skip;
SkipAnalyzer::SkipAnalyzer() : zeek::packet_analysis::Analyzer("Skip") { }
SkipAnalyzer::SkipAnalyzer() : zeek::packet_analysis::Analyzer("Skip") {}
void SkipAnalyzer::Initialize()
{
Analyzer::Initialize();
void SkipAnalyzer::Initialize() {
Analyzer::Initialize();
auto& skip_val = zeek::id::find_val("PacketAnalyzer::SKIP::skip_bytes");
if ( ! skip_val )
return;
auto& skip_val = zeek::id::find_val("PacketAnalyzer::SKIP::skip_bytes");
if ( ! skip_val )
return;
skip_bytes = skip_val->AsCount();
}
skip_bytes = skip_val->AsCount();
}
bool SkipAnalyzer::AnalyzePacket(size_t len, const uint8_t* data, Packet* packet)
{
return ForwardPacket(len - skip_bytes, data + skip_bytes, packet);
}
bool SkipAnalyzer::AnalyzePacket(size_t len, const uint8_t* data, Packet* packet) {
return ForwardPacket(len - skip_bytes, data + skip_bytes, packet);
}

View file

@ -5,25 +5,20 @@
#include "zeek/packet_analysis/Analyzer.h"
#include "zeek/packet_analysis/Component.h"
namespace zeek::packet_analysis::Skip
{
namespace zeek::packet_analysis::Skip {
class SkipAnalyzer : public Analyzer
{
class SkipAnalyzer : public Analyzer {
public:
SkipAnalyzer();
~SkipAnalyzer() override = default;
SkipAnalyzer();
~SkipAnalyzer() override = default;
void Initialize() override;
bool AnalyzePacket(size_t len, const uint8_t* data, Packet* packet) override;
void Initialize() override;
bool AnalyzePacket(size_t len, const uint8_t* data, Packet* packet) override;
static zeek::packet_analysis::AnalyzerPtr Instantiate()
{
return std::make_shared<SkipAnalyzer>();
}
static zeek::packet_analysis::AnalyzerPtr Instantiate() { return std::make_shared<SkipAnalyzer>(); }
private:
zeek_uint_t skip_bytes = 0;
};
zeek_uint_t skip_bytes = 0;
};
}
} // namespace zeek::packet_analysis::Skip

View file

@ -5,23 +5,20 @@
#include "zeek/packet_analysis/Component.h"
#include "zeek/packet_analysis/protocol/snap/SNAP.h"
namespace zeek::plugin::Zeek_SNAP
{
namespace zeek::plugin::Zeek_SNAP {
class Plugin final : public zeek::plugin::Plugin
{
class Plugin final : public zeek::plugin::Plugin {
public:
zeek::plugin::Configuration Configure() override
{
AddComponent(new zeek::packet_analysis::Component(
"SNAP", zeek::packet_analysis::SNAP::SNAPAnalyzer::Instantiate));
zeek::plugin::Configuration Configure() override {
AddComponent(
new zeek::packet_analysis::Component("SNAP", zeek::packet_analysis::SNAP::SNAPAnalyzer::Instantiate));
zeek::plugin::Configuration config;
config.name = "Zeek::SNAP";
config.description = "SNAP packet analyzer";
return config;
}
zeek::plugin::Configuration config;
config.name = "Zeek::SNAP";
config.description = "SNAP packet analyzer";
return config;
}
} plugin;
} plugin;
}
} // namespace zeek::plugin::Zeek_SNAP

View file

@ -4,47 +4,43 @@
using namespace zeek::packet_analysis::SNAP;
SNAPAnalyzer::SNAPAnalyzer() : zeek::packet_analysis::Analyzer("SNAP") { }
SNAPAnalyzer::SNAPAnalyzer() : zeek::packet_analysis::Analyzer("SNAP") {}
bool SNAPAnalyzer::AnalyzePacket(size_t len, const uint8_t* data, Packet* packet)
{
// The first part of the header is an LLC header, which we need to determine the
// length of the full header. Check to see if the shorter 3-byte version will fit.
if ( len < 3 )
{
Weird("truncated_snap_llc_header", packet);
return false;
}
bool SNAPAnalyzer::AnalyzePacket(size_t len, const uint8_t* data, Packet* packet) {
// The first part of the header is an LLC header, which we need to determine the
// length of the full header. Check to see if the shorter 3-byte version will fit.
if ( len < 3 ) {
Weird("truncated_snap_llc_header", packet);
return false;
}
// If the control field doesn't have an unnumbered PDU, the header is actually 4
// bytes long. Whether this is unnumbered is denoted by the last two bits being
// set.
size_t llc_header_len = 3;
if ( (data[2] & 0x03) != 0x03 )
llc_header_len++;
// If the control field doesn't have an unnumbered PDU, the header is actually 4
// bytes long. Whether this is unnumbered is denoted by the last two bits being
// set.
size_t llc_header_len = 3;
if ( (data[2] & 0x03) != 0x03 )
llc_header_len++;
// Check the full length of the SNAP header, which is the LLC header plus 5 bytes.
if ( len < llc_header_len + 5 )
{
Weird("truncated_snap_header", packet);
return false;
}
// Check the full length of the SNAP header, which is the LLC header plus 5 bytes.
if ( len < llc_header_len + 5 ) {
Weird("truncated_snap_header", packet);
return false;
}
data += llc_header_len;
len -= llc_header_len;
data += llc_header_len;
len -= llc_header_len;
int oui = (data[0] << 16) | (data[1] << 8) | data[2];
int protocol = (data[3] << 8) | data[4];
int oui = (data[0] << 16) | (data[1] << 8) | data[2];
int protocol = (data[3] << 8) | data[4];
data += 5;
len -= 5;
data += 5;
len -= 5;
if ( oui == 0 )
{
// If the OUI is zero, the protocol is a standard ethertype and can be
// forwarded as such.
return ForwardPacket(len, data, packet, protocol);
}
if ( oui == 0 ) {
// If the OUI is zero, the protocol is a standard ethertype and can be
// forwarded as such.
return ForwardPacket(len, data, packet, protocol);
}
return true;
}
return true;
}

View file

@ -5,21 +5,16 @@
#include "zeek/packet_analysis/Analyzer.h"
#include "zeek/packet_analysis/Component.h"
namespace zeek::packet_analysis::SNAP
{
namespace zeek::packet_analysis::SNAP {
class SNAPAnalyzer : public Analyzer
{
class SNAPAnalyzer : public Analyzer {
public:
SNAPAnalyzer();
~SNAPAnalyzer() override = default;
SNAPAnalyzer();
~SNAPAnalyzer() override = default;
bool AnalyzePacket(size_t len, const uint8_t* data, Packet* packet) override;
bool AnalyzePacket(size_t len, const uint8_t* data, Packet* packet) override;
static zeek::packet_analysis::AnalyzerPtr Instantiate()
{
return std::make_shared<SNAPAnalyzer>();
}
};
static zeek::packet_analysis::AnalyzerPtr Instantiate() { return std::make_shared<SNAPAnalyzer>(); }
};
}
} // namespace zeek::packet_analysis::SNAP

View file

@ -7,24 +7,20 @@
#include "zeek/packet_analysis/protocol/tcp/TCP.h"
#include "zeek/packet_analysis/protocol/tcp/TCPSessionAdapter.h"
namespace zeek::plugin::Zeek_TCP
{
namespace zeek::plugin::Zeek_TCP {
class Plugin final : public zeek::plugin::Plugin
{
class Plugin final : public zeek::plugin::Plugin {
public:
zeek::plugin::Configuration Configure() override
{
AddComponent(new zeek::packet_analysis::Component(
"TCP", zeek::packet_analysis::TCP::TCPAnalyzer::Instantiate));
AddComponent(new zeek::analyzer::Component("TCP", nullptr, 0, true, false, true));
zeek::plugin::Configuration Configure() override {
AddComponent(new zeek::packet_analysis::Component("TCP", zeek::packet_analysis::TCP::TCPAnalyzer::Instantiate));
AddComponent(new zeek::analyzer::Component("TCP", nullptr, 0, true, false, true));
zeek::plugin::Configuration config;
config.name = "Zeek::TCP_PKT";
config.description = "Packet analyzer for TCP";
return config;
}
zeek::plugin::Configuration config;
config.name = "Zeek::TCP_PKT";
config.description = "Packet analyzer for TCP";
return config;
}
} plugin;
} plugin;
}
} // namespace zeek::plugin::Zeek_TCP

View file

@ -5,85 +5,70 @@
#include "zeek/File.h"
#include "zeek/analyzer/protocol/tcp/events.bif.h"
namespace zeek::packet_analysis::TCP
{
namespace zeek::packet_analysis::TCP {
TCPStateStats::TCPStateStats()
{
for ( int i = 0; i < analyzer::tcp::TCP_ENDPOINT_RESET + 1; ++i )
for ( int j = 0; j < analyzer::tcp::TCP_ENDPOINT_RESET + 1; ++j )
state_cnt[i][j] = 0;
}
TCPStateStats::TCPStateStats() {
for ( int i = 0; i < analyzer::tcp::TCP_ENDPOINT_RESET + 1; ++i )
for ( int j = 0; j < analyzer::tcp::TCP_ENDPOINT_RESET + 1; ++j )
state_cnt[i][j] = 0;
}
void TCPStateStats::ChangeState(analyzer::tcp::EndpointState o_prev,
analyzer::tcp::EndpointState o_now,
analyzer::tcp::EndpointState r_prev,
analyzer::tcp::EndpointState r_now)
{
--state_cnt[o_prev][r_prev];
++state_cnt[o_now][r_now];
}
void TCPStateStats::ChangeState(analyzer::tcp::EndpointState o_prev, analyzer::tcp::EndpointState o_now,
analyzer::tcp::EndpointState r_prev, analyzer::tcp::EndpointState r_now) {
--state_cnt[o_prev][r_prev];
++state_cnt[o_now][r_now];
}
void TCPStateStats::FlipState(analyzer::tcp::EndpointState orig, analyzer::tcp::EndpointState resp)
{
--state_cnt[orig][resp];
++state_cnt[resp][orig];
}
void TCPStateStats::FlipState(analyzer::tcp::EndpointState orig, analyzer::tcp::EndpointState resp) {
--state_cnt[orig][resp];
++state_cnt[resp][orig];
}
unsigned int TCPStateStats::NumStatePartial() const
{
unsigned int sum = 0;
for ( int i = 0; i < analyzer::tcp::TCP_ENDPOINT_RESET + 1; ++i )
{
sum += state_cnt[analyzer::tcp::TCP_ENDPOINT_PARTIAL][i];
sum += state_cnt[i][analyzer::tcp::TCP_ENDPOINT_PARTIAL];
}
unsigned int TCPStateStats::NumStatePartial() const {
unsigned int sum = 0;
for ( int i = 0; i < analyzer::tcp::TCP_ENDPOINT_RESET + 1; ++i ) {
sum += state_cnt[analyzer::tcp::TCP_ENDPOINT_PARTIAL][i];
sum += state_cnt[i][analyzer::tcp::TCP_ENDPOINT_PARTIAL];
}
return sum;
}
return sum;
}
void TCPStateStats::PrintStats(File* file, const char* prefix)
{
file->Write(prefix);
file->Write(" Inact. Syn. SA Part. Est. Fin. Rst.\n");
void TCPStateStats::PrintStats(File* file, const char* prefix) {
file->Write(prefix);
file->Write(" Inact. Syn. SA Part. Est. Fin. Rst.\n");
for ( int i = 0; i < analyzer::tcp::TCP_ENDPOINT_RESET + 1; ++i )
{
file->Write(prefix);
for ( int i = 0; i < analyzer::tcp::TCP_ENDPOINT_RESET + 1; ++i ) {
file->Write(prefix);
switch ( i )
{
#define STATE_STRING(state, str) \
case state: \
file->Write(str); \
break;
switch ( i ) {
#define STATE_STRING(state, str) \
case state: file->Write(str); break;
STATE_STRING(analyzer::tcp::TCP_ENDPOINT_INACTIVE, "Inact.");
STATE_STRING(analyzer::tcp::TCP_ENDPOINT_SYN_SENT, "Syn. ");
STATE_STRING(analyzer::tcp::TCP_ENDPOINT_SYN_ACK_SENT, "SA ");
STATE_STRING(analyzer::tcp::TCP_ENDPOINT_PARTIAL, "Part. ");
STATE_STRING(analyzer::tcp::TCP_ENDPOINT_ESTABLISHED, "Est. ");
STATE_STRING(analyzer::tcp::TCP_ENDPOINT_CLOSED, "Fin. ");
STATE_STRING(analyzer::tcp::TCP_ENDPOINT_RESET, "Rst. ");
}
STATE_STRING(analyzer::tcp::TCP_ENDPOINT_INACTIVE, "Inact.");
STATE_STRING(analyzer::tcp::TCP_ENDPOINT_SYN_SENT, "Syn. ");
STATE_STRING(analyzer::tcp::TCP_ENDPOINT_SYN_ACK_SENT, "SA ");
STATE_STRING(analyzer::tcp::TCP_ENDPOINT_PARTIAL, "Part. ");
STATE_STRING(analyzer::tcp::TCP_ENDPOINT_ESTABLISHED, "Est. ");
STATE_STRING(analyzer::tcp::TCP_ENDPOINT_CLOSED, "Fin. ");
STATE_STRING(analyzer::tcp::TCP_ENDPOINT_RESET, "Rst. ");
}
file->Write(" ");
file->Write(" ");
for ( int j = 0; j < analyzer::tcp::TCP_ENDPOINT_RESET + 1; ++j )
{
unsigned int n = state_cnt[i][j];
if ( n > 0 )
{
char buf[32];
snprintf(buf, sizeof(buf), "%-8d", state_cnt[i][j]);
file->Write(buf);
}
else
file->Write(" ");
}
for ( int j = 0; j < analyzer::tcp::TCP_ENDPOINT_RESET + 1; ++j ) {
unsigned int n = state_cnt[i][j];
if ( n > 0 ) {
char buf[32];
snprintf(buf, sizeof(buf), "%-8d", state_cnt[i][j]);
file->Write(buf);
}
else
file->Write(" ");
}
file->Write("\n");
}
}
file->Write("\n");
}
}
} // namespace zeek::packet_analysis::TCP
} // namespace zeek::packet_analysis::TCP

View file

@ -4,77 +4,62 @@
#include "zeek/analyzer/protocol/tcp/TCP_Endpoint.h"
namespace zeek::packet_analysis::TCP
{
namespace zeek::packet_analysis::TCP {
/**
* A TCPStateStats object tracks the distribution of TCP states for
* the currently active connections.
*/
class TCPStateStats
{
class TCPStateStats {
public:
TCPStateStats();
~TCPStateStats() = default;
TCPStateStats();
~TCPStateStats() = default;
void ChangeState(analyzer::tcp::EndpointState o_prev, analyzer::tcp::EndpointState o_now,
analyzer::tcp::EndpointState r_prev, analyzer::tcp::EndpointState r_now);
void FlipState(analyzer::tcp::EndpointState orig, analyzer::tcp::EndpointState resp);
void ChangeState(analyzer::tcp::EndpointState o_prev, analyzer::tcp::EndpointState o_now,
analyzer::tcp::EndpointState r_prev, analyzer::tcp::EndpointState r_now);
void FlipState(analyzer::tcp::EndpointState orig, analyzer::tcp::EndpointState resp);
void StateEntered(analyzer::tcp::EndpointState o_state, analyzer::tcp::EndpointState r_state)
{
++state_cnt[o_state][r_state];
}
void StateLeft(analyzer::tcp::EndpointState o_state, analyzer::tcp::EndpointState r_state)
{
--state_cnt[o_state][r_state];
}
void StateEntered(analyzer::tcp::EndpointState o_state, analyzer::tcp::EndpointState r_state) {
++state_cnt[o_state][r_state];
}
void StateLeft(analyzer::tcp::EndpointState o_state, analyzer::tcp::EndpointState r_state) {
--state_cnt[o_state][r_state];
}
unsigned int Cnt(analyzer::tcp::EndpointState state) const { return Cnt(state, state); }
unsigned int Cnt(analyzer::tcp::EndpointState state1, analyzer::tcp::EndpointState state2) const
{
return state_cnt[state1][state2];
}
unsigned int Cnt(analyzer::tcp::EndpointState state) const { return Cnt(state, state); }
unsigned int Cnt(analyzer::tcp::EndpointState state1, analyzer::tcp::EndpointState state2) const {
return state_cnt[state1][state2];
}
unsigned int NumStateEstablished() const
{
return Cnt(analyzer::tcp::TCP_ENDPOINT_ESTABLISHED);
}
unsigned int NumStateHalfClose() const
{ // corresponds to S2,S3
return Cnt(analyzer::tcp::TCP_ENDPOINT_ESTABLISHED, analyzer::tcp::TCP_ENDPOINT_CLOSED) +
Cnt(analyzer::tcp::TCP_ENDPOINT_CLOSED, analyzer::tcp::TCP_ENDPOINT_ESTABLISHED);
}
unsigned int NumStateHalfRst() const
{
return Cnt(analyzer::tcp::TCP_ENDPOINT_ESTABLISHED, analyzer::tcp::TCP_ENDPOINT_RESET) +
Cnt(analyzer::tcp::TCP_ENDPOINT_RESET, analyzer::tcp::TCP_ENDPOINT_ESTABLISHED);
}
unsigned int NumStateClosed() const { return Cnt(analyzer::tcp::TCP_ENDPOINT_CLOSED); }
unsigned int NumStateRequest() const
{
assert(Cnt(analyzer::tcp::TCP_ENDPOINT_INACTIVE, analyzer::tcp::TCP_ENDPOINT_SYN_SENT) ==
0);
return Cnt(analyzer::tcp::TCP_ENDPOINT_SYN_SENT, analyzer::tcp::TCP_ENDPOINT_INACTIVE);
}
unsigned int NumStateSuccRequest() const
{
return Cnt(analyzer::tcp::TCP_ENDPOINT_SYN_SENT, analyzer::tcp::TCP_ENDPOINT_SYN_ACK_SENT) +
Cnt(analyzer::tcp::TCP_ENDPOINT_SYN_ACK_SENT, analyzer::tcp::TCP_ENDPOINT_SYN_SENT);
}
unsigned int NumStateRstRequest() const
{
return Cnt(analyzer::tcp::TCP_ENDPOINT_SYN_SENT, analyzer::tcp::TCP_ENDPOINT_RESET) +
Cnt(analyzer::tcp::TCP_ENDPOINT_RESET, analyzer::tcp::TCP_ENDPOINT_SYN_SENT);
}
unsigned int NumStateInactive() const { return Cnt(analyzer::tcp::TCP_ENDPOINT_INACTIVE); }
unsigned int NumStatePartial() const;
unsigned int NumStateEstablished() const { return Cnt(analyzer::tcp::TCP_ENDPOINT_ESTABLISHED); }
unsigned int NumStateHalfClose() const { // corresponds to S2,S3
return Cnt(analyzer::tcp::TCP_ENDPOINT_ESTABLISHED, analyzer::tcp::TCP_ENDPOINT_CLOSED) +
Cnt(analyzer::tcp::TCP_ENDPOINT_CLOSED, analyzer::tcp::TCP_ENDPOINT_ESTABLISHED);
}
unsigned int NumStateHalfRst() const {
return Cnt(analyzer::tcp::TCP_ENDPOINT_ESTABLISHED, analyzer::tcp::TCP_ENDPOINT_RESET) +
Cnt(analyzer::tcp::TCP_ENDPOINT_RESET, analyzer::tcp::TCP_ENDPOINT_ESTABLISHED);
}
unsigned int NumStateClosed() const { return Cnt(analyzer::tcp::TCP_ENDPOINT_CLOSED); }
unsigned int NumStateRequest() const {
assert(Cnt(analyzer::tcp::TCP_ENDPOINT_INACTIVE, analyzer::tcp::TCP_ENDPOINT_SYN_SENT) == 0);
return Cnt(analyzer::tcp::TCP_ENDPOINT_SYN_SENT, analyzer::tcp::TCP_ENDPOINT_INACTIVE);
}
unsigned int NumStateSuccRequest() const {
return Cnt(analyzer::tcp::TCP_ENDPOINT_SYN_SENT, analyzer::tcp::TCP_ENDPOINT_SYN_ACK_SENT) +
Cnt(analyzer::tcp::TCP_ENDPOINT_SYN_ACK_SENT, analyzer::tcp::TCP_ENDPOINT_SYN_SENT);
}
unsigned int NumStateRstRequest() const {
return Cnt(analyzer::tcp::TCP_ENDPOINT_SYN_SENT, analyzer::tcp::TCP_ENDPOINT_RESET) +
Cnt(analyzer::tcp::TCP_ENDPOINT_RESET, analyzer::tcp::TCP_ENDPOINT_SYN_SENT);
}
unsigned int NumStateInactive() const { return Cnt(analyzer::tcp::TCP_ENDPOINT_INACTIVE); }
unsigned int NumStatePartial() const;
void PrintStats(File* file, const char* prefix);
void PrintStats(File* file, const char* prefix);
private:
unsigned int state_cnt[analyzer::tcp::TCP_ENDPOINT_RESET + 1]
[analyzer::tcp::TCP_ENDPOINT_RESET + 1];
};
unsigned int state_cnt[analyzer::tcp::TCP_ENDPOINT_RESET + 1][analyzer::tcp::TCP_ENDPOINT_RESET + 1];
};
} // namespace zeek::packet_analysis::TCP
} // namespace zeek::packet_analysis::TCP

View file

@ -12,166 +12,149 @@ using namespace zeek;
using namespace zeek::packet_analysis::TCP;
using namespace zeek::packet_analysis::IP;
TCPAnalyzer::TCPAnalyzer() : IPBasedAnalyzer("TCP", TRANSPORT_TCP, TCP_PORT_MASK, false) { }
TCPAnalyzer::TCPAnalyzer() : IPBasedAnalyzer("TCP", TRANSPORT_TCP, TCP_PORT_MASK, false) {}
void TCPAnalyzer::Initialize() { }
void TCPAnalyzer::Initialize() {}
SessionAdapter* TCPAnalyzer::MakeSessionAdapter(Connection* conn)
{
auto* root = new TCPSessionAdapter(conn);
root->SetParent(this);
SessionAdapter* TCPAnalyzer::MakeSessionAdapter(Connection* conn) {
auto* root = new TCPSessionAdapter(conn);
root->SetParent(this);
conn->EnableStatusUpdateTimer();
conn->SetInactivityTimeout(zeek::detail::udp_inactivity_timeout);
conn->EnableStatusUpdateTimer();
conn->SetInactivityTimeout(zeek::detail::udp_inactivity_timeout);
return root;
}
return root;
}
zeek::analyzer::pia::PIA* TCPAnalyzer::MakePIA(Connection* conn)
{
return new analyzer::pia::PIA_TCP(conn);
}
zeek::analyzer::pia::PIA* TCPAnalyzer::MakePIA(Connection* conn) { return new analyzer::pia::PIA_TCP(conn); }
bool TCPAnalyzer::BuildConnTuple(size_t len, const uint8_t* data, Packet* packet, ConnTuple& tuple)
{
uint32_t min_hdr_len = sizeof(struct tcphdr);
if ( ! CheckHeaderTrunc(min_hdr_len, len, packet) )
return false;
bool TCPAnalyzer::BuildConnTuple(size_t len, const uint8_t* data, Packet* packet, ConnTuple& tuple) {
uint32_t min_hdr_len = sizeof(struct tcphdr);
if ( ! CheckHeaderTrunc(min_hdr_len, len, packet) )
return false;
tuple.src_addr = packet->ip_hdr->SrcAddr();
tuple.dst_addr = packet->ip_hdr->DstAddr();
tuple.src_addr = packet->ip_hdr->SrcAddr();
tuple.dst_addr = packet->ip_hdr->DstAddr();
data = packet->ip_hdr->Payload();
data = packet->ip_hdr->Payload();
const struct tcphdr* tp = (const struct tcphdr*)data;
tuple.src_port = tp->th_sport;
tuple.dst_port = tp->th_dport;
tuple.is_one_way = false;
tuple.proto = TRANSPORT_TCP;
const struct tcphdr* tp = (const struct tcphdr*)data;
tuple.src_port = tp->th_sport;
tuple.dst_port = tp->th_dport;
tuple.is_one_way = false;
tuple.proto = TRANSPORT_TCP;
return true;
}
return true;
}
bool TCPAnalyzer::WantConnection(uint16_t src_port, uint16_t dst_port, const u_char* data,
bool& flip_roles) const
{
flip_roles = false;
const struct tcphdr* tp = (const struct tcphdr*)data;
uint8_t tcp_flags = tp->th_flags;
bool TCPAnalyzer::WantConnection(uint16_t src_port, uint16_t dst_port, const u_char* data, bool& flip_roles) const {
flip_roles = false;
const struct tcphdr* tp = (const struct tcphdr*)data;
uint8_t tcp_flags = tp->th_flags;
if ( ! (tcp_flags & TH_SYN) || (tcp_flags & TH_ACK) )
{
// The new connection is starting either without a SYN,
// or with a SYN ack. This means it's a partial connection.
if ( ! zeek::detail::partial_connection_ok )
return false;
if ( ! (tcp_flags & TH_SYN) || (tcp_flags & TH_ACK) ) {
// The new connection is starting either without a SYN,
// or with a SYN ack. This means it's a partial connection.
if ( ! zeek::detail::partial_connection_ok )
return false;
if ( tcp_flags & TH_SYN && ! zeek::detail::tcp_SYN_ack_ok )
return false;
if ( tcp_flags & TH_SYN && ! zeek::detail::tcp_SYN_ack_ok )
return false;
// Try to guess true responder by the port numbers.
// (We might also think that for SYN acks we could
// safely flip the roles, but that doesn't work
// for stealth scans.)
if ( IsLikelyServerPort(src_port) )
{ // connection is a candidate for flipping
if ( IsLikelyServerPort(dst_port) )
// Hmmm, both source and destination
// are plausible. Heuristic: flip only
// if (1) this isn't a SYN ACK (to avoid
// confusing stealth scans) and
// (2) dest port > src port (to favor
// more plausible servers).
flip_roles = ! (tcp_flags & TH_SYN) && src_port < dst_port;
else
// Source is plausible, destination isn't.
flip_roles = true;
}
}
// Try to guess true responder by the port numbers.
// (We might also think that for SYN acks we could
// safely flip the roles, but that doesn't work
// for stealth scans.)
if ( IsLikelyServerPort(src_port) ) { // connection is a candidate for flipping
if ( IsLikelyServerPort(dst_port) )
// Hmmm, both source and destination
// are plausible. Heuristic: flip only
// if (1) this isn't a SYN ACK (to avoid
// confusing stealth scans) and
// (2) dest port > src port (to favor
// more plausible servers).
flip_roles = ! (tcp_flags & TH_SYN) && src_port < dst_port;
else
// Source is plausible, destination isn't.
flip_roles = true;
}
}
return true;
}
return true;
}
void TCPAnalyzer::DeliverPacket(Connection* c, double t, bool is_orig, int remaining, Packet* pkt)
{
const u_char* data = pkt->ip_hdr->Payload();
int len = pkt->ip_hdr->PayloadLen();
// If the header length is zero, tcp checksum offloading is probably enabled
// In this case, let's fix up the length.
if ( pkt->ip_hdr->TotalLen() == 0 )
len = remaining;
auto* adapter = static_cast<TCPSessionAdapter*>(c->GetSessionAdapter());
void TCPAnalyzer::DeliverPacket(Connection* c, double t, bool is_orig, int remaining, Packet* pkt) {
const u_char* data = pkt->ip_hdr->Payload();
int len = pkt->ip_hdr->PayloadLen();
// If the header length is zero, tcp checksum offloading is probably enabled
// In this case, let's fix up the length.
if ( pkt->ip_hdr->TotalLen() == 0 )
len = remaining;
auto* adapter = static_cast<TCPSessionAdapter*>(c->GetSessionAdapter());
const struct tcphdr* tp = ExtractTCP_Header(data, len, remaining, adapter);
if ( ! tp )
return;
const struct tcphdr* tp = ExtractTCP_Header(data, len, remaining, adapter);
if ( ! tp )
return;
// We need the min() here because Ethernet frame padding can lead to
// remaining > len.
if ( packet_contents )
adapter->PacketContents(data, std::min(len, remaining));
// We need the min() here because Ethernet frame padding can lead to
// remaining > len.
if ( packet_contents )
adapter->PacketContents(data, std::min(len, remaining));
analyzer::tcp::TCP_Endpoint* endpoint = is_orig ? adapter->orig : adapter->resp;
analyzer::tcp::TCP_Endpoint* peer = endpoint->peer;
const std::shared_ptr<IP_Hdr>& ip = pkt->ip_hdr;
analyzer::tcp::TCP_Endpoint* endpoint = is_orig ? adapter->orig : adapter->resp;
analyzer::tcp::TCP_Endpoint* peer = endpoint->peer;
const std::shared_ptr<IP_Hdr>& ip = pkt->ip_hdr;
if ( ! ValidateChecksum(ip.get(), tp, endpoint, len, remaining, adapter) )
return;
if ( ! ValidateChecksum(ip.get(), tp, endpoint, len, remaining, adapter) )
return;
adapter->Process(is_orig, tp, len, ip, data, remaining);
adapter->Process(is_orig, tp, len, ip, data, remaining);
// Store the session in the packet in case we get an encapsulation here. We need it for
// handling those properly.
pkt->session = c;
// Store the session in the packet in case we get an encapsulation here. We need it for
// handling those properly.
pkt->session = c;
// Send the packet back into the packet analysis framework.
ForwardPacket(std::min(len, remaining), data, pkt);
// Send the packet back into the packet analysis framework.
ForwardPacket(std::min(len, remaining), data, pkt);
// Call DeliverPacket on the adapter directly here. Normally we'd call ForwardPacket
// but this adapter does some other things in its DeliverPacket with the packet children
// analyzers.
adapter->DeliverPacket(std::min(len, remaining), data, is_orig, adapter->LastRelDataSeq(),
ip.get(), pkt->cap_len);
}
// Call DeliverPacket on the adapter directly here. Normally we'd call ForwardPacket
// but this adapter does some other things in its DeliverPacket with the packet children
// analyzers.
adapter->DeliverPacket(std::min(len, remaining), data, is_orig, adapter->LastRelDataSeq(), ip.get(), pkt->cap_len);
}
const struct tcphdr* TCPAnalyzer::ExtractTCP_Header(const u_char*& data, int& len, int& remaining,
TCPSessionAdapter* adapter)
{
const struct tcphdr* tp = (const struct tcphdr*)data;
uint32_t tcp_hdr_len = tp->th_off * 4;
TCPSessionAdapter* adapter) {
const struct tcphdr* tp = (const struct tcphdr*)data;
uint32_t tcp_hdr_len = tp->th_off * 4;
if ( tcp_hdr_len < sizeof(struct tcphdr) )
{
adapter->Weird("bad_TCP_header_len");
return nullptr;
}
if ( tcp_hdr_len < sizeof(struct tcphdr) ) {
adapter->Weird("bad_TCP_header_len");
return nullptr;
}
if ( tcp_hdr_len > uint32_t(len) || tcp_hdr_len > uint32_t(remaining) )
{
// This can happen even with the above test, due to TCP options.
adapter->Weird("truncated_header");
return nullptr;
}
if ( tcp_hdr_len > uint32_t(len) || tcp_hdr_len > uint32_t(remaining) ) {
// This can happen even with the above test, due to TCP options.
adapter->Weird("truncated_header");
return nullptr;
}
len -= tcp_hdr_len; // remove TCP header
remaining -= tcp_hdr_len;
data += tcp_hdr_len;
len -= tcp_hdr_len; // remove TCP header
remaining -= tcp_hdr_len;
data += tcp_hdr_len;
return tp;
}
return tp;
}
bool TCPAnalyzer::ValidateChecksum(const IP_Hdr* ip, const struct tcphdr* tp,
analyzer::tcp::TCP_Endpoint* endpoint, int len, int caplen,
TCPSessionAdapter* adapter)
{
if ( ! run_state::current_pkt->l4_checksummed && ! detail::ignore_checksums &&
! GetIgnoreChecksumsNets()->Contains(ip->IPHeaderSrcAddr()) && caplen >= len &&
! endpoint->ValidChecksum(tp, len, ip->IP4_Hdr()) )
{
adapter->Weird("bad_TCP_checksum");
endpoint->ChecksumError();
return false;
}
else
return true;
}
bool TCPAnalyzer::ValidateChecksum(const IP_Hdr* ip, const struct tcphdr* tp, analyzer::tcp::TCP_Endpoint* endpoint,
int len, int caplen, TCPSessionAdapter* adapter) {
if ( ! run_state::current_pkt->l4_checksummed && ! detail::ignore_checksums &&
! GetIgnoreChecksumsNets()->Contains(ip->IPHeaderSrcAddr()) && caplen >= len &&
! endpoint->ValidChecksum(tp, len, ip->IP4_Hdr()) ) {
adapter->Weird("bad_TCP_checksum");
endpoint->ChecksumError();
return false;
}
else
return true;
}

View file

@ -8,85 +8,75 @@
#include "zeek/packet_analysis/protocol/ip/IPBasedAnalyzer.h"
#include "zeek/packet_analysis/protocol/tcp/Stats.h"
namespace zeek::analyzer::tcp
{
namespace zeek::analyzer::tcp {
class TCP_Endpoint;
}
}
namespace zeek::packet_analysis::TCP
{
namespace zeek::packet_analysis::TCP {
class TCPSessionAdapter;
class TCPAnalyzer final : public IP::IPBasedAnalyzer
{
class TCPAnalyzer final : public IP::IPBasedAnalyzer {
public:
TCPAnalyzer();
~TCPAnalyzer() override = default;
TCPAnalyzer();
~TCPAnalyzer() override = default;
static zeek::packet_analysis::AnalyzerPtr Instantiate()
{
return std::make_shared<TCPAnalyzer>();
}
static zeek::packet_analysis::AnalyzerPtr Instantiate() { return std::make_shared<TCPAnalyzer>(); }
/*
* Initialize the analyzer. This method is called after the configuration
* was read. Derived classes can override this method to implement custom
* initialization.
*/
void Initialize() override;
/*
* Initialize the analyzer. This method is called after the configuration
* was read. Derived classes can override this method to implement custom
* initialization.
*/
void Initialize() override;
static TCPStateStats& GetStats()
{
static TCPStateStats stats;
return stats;
}
static TCPStateStats& GetStats() {
static TCPStateStats stats;
return stats;
}
protected:
/**
* Parse the header from the packet into a ConnTuple object.
*/
bool BuildConnTuple(size_t len, const uint8_t* data, Packet* packet, ConnTuple& tuple) override;
/**
* Parse the header from the packet into a ConnTuple object.
*/
bool BuildConnTuple(size_t len, const uint8_t* data, Packet* packet, ConnTuple& tuple) override;
void DeliverPacket(Connection* c, double t, bool is_orig, int remaining, Packet* pkt) override;
void DeliverPacket(Connection* c, double t, bool is_orig, int remaining, Packet* pkt) override;
/**
* Upon seeing the first packet of a connection, checks whether we want
* to analyze it (e.g. we may not want to look at partial connections)
* and, if yes, whether we should flip the roles of originator and
* responder based on known ports and such.
*
* @param src_port The source port of the connection.
* @param dst_port The destination port of the connection.
* @param data The payload data for the packet being processed.
* @param flip_roles Return value if the roles should be flipped.
* @return True if the connection is wanted. False otherwise.
*/
bool WantConnection(uint16_t src_port, uint16_t dst_port, const u_char* data,
bool& flip_roles) const override;
/**
* Upon seeing the first packet of a connection, checks whether we want
* to analyze it (e.g. we may not want to look at partial connections)
* and, if yes, whether we should flip the roles of originator and
* responder based on known ports and such.
*
* @param src_port The source port of the connection.
* @param dst_port The destination port of the connection.
* @param data The payload data for the packet being processed.
* @param flip_roles Return value if the roles should be flipped.
* @return True if the connection is wanted. False otherwise.
*/
bool WantConnection(uint16_t src_port, uint16_t dst_port, const u_char* data, bool& flip_roles) const override;
/**
* Returns an analyzer adapter appropriate for this IP-based analyzer. This adapter
* is used to hook into the session analyzer framework. This function can also be used
* to do any extra initialization of connection timers, etc.
*/
packet_analysis::IP::SessionAdapter* MakeSessionAdapter(Connection* conn) override;
/**
* Returns an analyzer adapter appropriate for this IP-based analyzer. This adapter
* is used to hook into the session analyzer framework. This function can also be used
* to do any extra initialization of connection timers, etc.
*/
packet_analysis::IP::SessionAdapter* MakeSessionAdapter(Connection* conn) override;
/**
* Returns a PIA appropriate for this IP-based analyzer. This method is optional to
* override in child classes, as not all analyzers need a PIA.
*/
analyzer::pia::PIA* MakePIA(Connection* conn) override;
/**
* Returns a PIA appropriate for this IP-based analyzer. This method is optional to
* override in child classes, as not all analyzers need a PIA.
*/
analyzer::pia::PIA* MakePIA(Connection* conn) override;
private:
const struct tcphdr* ExtractTCP_Header(const u_char*& data, int& len, int& remaining,
TCPSessionAdapter* adapter);
const struct tcphdr* ExtractTCP_Header(const u_char*& data, int& len, int& remaining, TCPSessionAdapter* adapter);
// Returns true if the checksum is valid, false if not (and in which
// case also updates the status history of the endpoint).
bool ValidateChecksum(const IP_Hdr* ip, const struct tcphdr* tp,
analyzer::tcp::TCP_Endpoint* endpoint, int len, int caplen,
TCPSessionAdapter* adapter);
};
// Returns true if the checksum is valid, false if not (and in which
// case also updates the status history of the endpoint).
bool ValidateChecksum(const IP_Hdr* ip, const struct tcphdr* tp, analyzer::tcp::TCP_Endpoint* endpoint, int len,
int caplen, TCPSessionAdapter* adapter);
};
}
} // namespace zeek::packet_analysis::TCP

File diff suppressed because it is too large Load diff

View file

@ -10,185 +10,173 @@
#include "zeek/packet_analysis/protocol/ip/SessionAdapter.h"
#include "zeek/session/Manager.h"
namespace zeek::analyzer::pia
{
namespace zeek::analyzer::pia {
class PIA_TCP;
}
namespace zeek::analyzer::tcp
{
}
namespace zeek::analyzer::tcp {
class TCP_Reassembler;
}
}
namespace zeek::packet_analysis::TCP
{
namespace zeek::packet_analysis::TCP {
constexpr bool DEBUG_tcp_data_sent = false;
constexpr bool DEBUG_tcp_connection_close = false;
class TCPAnalyzer;
class TCPSessionAdapter final : public packet_analysis::IP::SessionAdapter
{
class TCPSessionAdapter final : public packet_analysis::IP::SessionAdapter {
public:
explicit TCPSessionAdapter(Connection* conn);
~TCPSessionAdapter() override;
explicit TCPSessionAdapter(Connection* conn);
~TCPSessionAdapter() override;
void Process(bool is_orig, const struct tcphdr* tp, int len, const std::shared_ptr<IP_Hdr>& ip,
const u_char* data, int remaining);
void Process(bool is_orig, const struct tcphdr* tp, int len, const std::shared_ptr<IP_Hdr>& ip, const u_char* data,
int remaining);
void EnableReassembly();
void EnableReassembly();
// Add a child analyzer that will always get the packets,
// independently of whether we do any reassembly.
void AddChildPacketAnalyzer(analyzer::Analyzer* a);
// Add a child analyzer that will always get the packets,
// independently of whether we do any reassembly.
void AddChildPacketAnalyzer(analyzer::Analyzer* a);
Analyzer* FindChild(analyzer::ID id) override;
Analyzer* FindChild(zeek::Tag tag) override;
bool RemoveChildAnalyzer(analyzer::ID id) override;
Analyzer* FindChild(analyzer::ID id) override;
Analyzer* FindChild(zeek::Tag tag) override;
bool RemoveChildAnalyzer(analyzer::ID id) override;
// True if the connection has closed in some sense, false otherwise.
bool IsClosed() const { return orig->did_close || resp->did_close; }
bool BothClosed() const { return orig->did_close && resp->did_close; }
// True if the connection has closed in some sense, false otherwise.
bool IsClosed() const { return orig->did_close || resp->did_close; }
bool BothClosed() const { return orig->did_close && resp->did_close; }
bool IsPartial() const { return is_partial; }
bool IsPartial() const { return is_partial; }
bool HadGap(bool orig) const;
bool HadGap(bool orig) const;
analyzer::tcp::TCP_Endpoint* Orig() const { return orig; }
analyzer::tcp::TCP_Endpoint* Resp() const { return resp; }
int OrigState() const { return orig->state; }
int RespState() const { return resp->state; }
int OrigPrevState() const { return orig->prev_state; }
int RespPrevState() const { return resp->prev_state; }
uint32_t OrigSeq() const { return orig->LastSeq(); }
uint32_t RespSeq() const { return resp->LastSeq(); }
analyzer::tcp::TCP_Endpoint* Orig() const { return orig; }
analyzer::tcp::TCP_Endpoint* Resp() const { return resp; }
int OrigState() const { return orig->state; }
int RespState() const { return resp->state; }
int OrigPrevState() const { return orig->prev_state; }
int RespPrevState() const { return resp->prev_state; }
uint32_t OrigSeq() const { return orig->LastSeq(); }
uint32_t RespSeq() const { return resp->LastSeq(); }
// True if either endpoint still has pending data. closing_endp
// is an endpoint that has indicated it is closing (i.e., for
// which we have seen a FIN) - for it, data is pending unless
// everything's been delivered up to the FIN. For its peer,
// the test is whether it has any outstanding, un-acked data.
bool DataPending(analyzer::tcp::TCP_Endpoint* closing_endp);
// True if either endpoint still has pending data. closing_endp
// is an endpoint that has indicated it is closing (i.e., for
// which we have seen a FIN) - for it, data is pending unless
// everything's been delivered up to the FIN. For its peer,
// the test is whether it has any outstanding, un-acked data.
bool DataPending(analyzer::tcp::TCP_Endpoint* closing_endp);
void SetContentsFile(unsigned int direction, FilePtr f) override;
FilePtr GetContentsFile(unsigned int direction) const override;
void SetContentsFile(unsigned int direction, FilePtr f) override;
FilePtr GetContentsFile(unsigned int direction) const override;
// From Analyzer.h
void UpdateConnVal(RecordVal* conn_val) override;
// From Analyzer.h
void UpdateConnVal(RecordVal* conn_val) override;
void AddExtraAnalyzers(Connection* conn) override;
void AddExtraAnalyzers(Connection* conn) override;
static int get_segment_len(int payload_len, analyzer::tcp::TCP_Flags flags);
static uint64_t get_relative_seq(const analyzer::tcp::TCP_Endpoint* endpoint, uint32_t cur_base,
uint32_t last, uint32_t wraps, bool* underflow);
static int get_segment_len(int payload_len, analyzer::tcp::TCP_Flags flags);
static uint64_t get_relative_seq(const analyzer::tcp::TCP_Endpoint* endpoint, uint32_t cur_base, uint32_t last,
uint32_t wraps, bool* underflow);
protected:
friend class analyzer::tcp::TCP_ApplicationAnalyzer;
friend class analyzer::tcp::TCP_Endpoint;
friend class analyzer::tcp::TCP_Reassembler;
friend class analyzer::pia::PIA_TCP;
friend class packet_analysis::TCP::TCPAnalyzer;
friend class analyzer::tcp::TCP_ApplicationAnalyzer;
friend class analyzer::tcp::TCP_Endpoint;
friend class analyzer::tcp::TCP_Reassembler;
friend class analyzer::pia::PIA_TCP;
friend class packet_analysis::TCP::TCPAnalyzer;
// Analyzer interface.
void Init() override;
void Done() override;
void DeliverPacket(int len, const u_char* data, bool orig, uint64_t seq, const IP_Hdr* ip,
int caplen) override;
void DeliverStream(int len, const u_char* data, bool orig) override;
void Undelivered(uint64_t seq, int len, bool orig) override;
void FlipRoles() override;
bool IsReuse(double t, const u_char* pkt) override;
// Analyzer interface.
void Init() override;
void Done() override;
void DeliverPacket(int len, const u_char* data, bool orig, uint64_t seq, const IP_Hdr* ip, int caplen) override;
void DeliverStream(int len, const u_char* data, bool orig) override;
void Undelivered(uint64_t seq, int len, bool orig) override;
void FlipRoles() override;
bool IsReuse(double t, const u_char* pkt) override;
void SetPartialStatus(analyzer::tcp::TCP_Flags flags, bool is_orig);
void SetFirstPacketSeen(bool is_orig);
void SetPartialStatus(analyzer::tcp::TCP_Flags flags, bool is_orig);
void SetFirstPacketSeen(bool is_orig);
// Update the state machine of the TCPs based on the activity. This
// includes our pseudo-states such as TCP_ENDPOINT_PARTIAL.
//
// On return, do_close is true if we should consider the connection
// as closed, and gen_event if we should generate an event about
// this fact.
void UpdateStateMachine(double t, analyzer::tcp::TCP_Endpoint* endpoint,
analyzer::tcp::TCP_Endpoint* peer, uint32_t base_seq, uint32_t ack_seq,
int len, int32_t delta_last, bool is_orig,
analyzer::tcp::TCP_Flags flags, bool& do_close, bool& gen_event);
// Update the state machine of the TCPs based on the activity. This
// includes our pseudo-states such as TCP_ENDPOINT_PARTIAL.
//
// On return, do_close is true if we should consider the connection
// as closed, and gen_event if we should generate an event about
// this fact.
void UpdateStateMachine(double t, analyzer::tcp::TCP_Endpoint* endpoint, analyzer::tcp::TCP_Endpoint* peer,
uint32_t base_seq, uint32_t ack_seq, int len, int32_t delta_last, bool is_orig,
analyzer::tcp::TCP_Flags flags, bool& do_close, bool& gen_event);
void UpdateInactiveState(double t, analyzer::tcp::TCP_Endpoint* endpoint,
analyzer::tcp::TCP_Endpoint* peer, uint32_t base_seq, uint32_t ack_seq,
int len, bool is_orig, analyzer::tcp::TCP_Flags flags, bool& do_close,
bool& gen_event);
void UpdateInactiveState(double t, analyzer::tcp::TCP_Endpoint* endpoint, analyzer::tcp::TCP_Endpoint* peer,
uint32_t base_seq, uint32_t ack_seq, int len, bool is_orig, analyzer::tcp::TCP_Flags flags,
bool& do_close, bool& gen_event);
void UpdateSYN_SentState(analyzer::tcp::TCP_Endpoint* endpoint,
analyzer::tcp::TCP_Endpoint* peer, int len, bool is_orig,
analyzer::tcp::TCP_Flags flags, bool& do_close, bool& gen_event);
void UpdateSYN_SentState(analyzer::tcp::TCP_Endpoint* endpoint, analyzer::tcp::TCP_Endpoint* peer, int len,
bool is_orig, analyzer::tcp::TCP_Flags flags, bool& do_close, bool& gen_event);
void UpdateEstablishedState(analyzer::tcp::TCP_Endpoint* endpoint,
analyzer::tcp::TCP_Endpoint* peer, analyzer::tcp::TCP_Flags flags,
bool& do_close, bool& gen_event);
void UpdateEstablishedState(analyzer::tcp::TCP_Endpoint* endpoint, analyzer::tcp::TCP_Endpoint* peer,
analyzer::tcp::TCP_Flags flags, bool& do_close, bool& gen_event);
void UpdateClosedState(double t, analyzer::tcp::TCP_Endpoint* endpoint, int32_t delta_last,
analyzer::tcp::TCP_Flags flags, bool& do_close);
void UpdateClosedState(double t, analyzer::tcp::TCP_Endpoint* endpoint, int32_t delta_last,
analyzer::tcp::TCP_Flags flags, bool& do_close);
void UpdateResetState(int len, analyzer::tcp::TCP_Flags flags);
void UpdateResetState(int len, analyzer::tcp::TCP_Flags flags);
void GeneratePacketEvent(uint64_t rel_seq, uint64_t rel_ack, const u_char* data, int len,
int caplen, bool is_orig, analyzer::tcp::TCP_Flags flags);
void GeneratePacketEvent(uint64_t rel_seq, uint64_t rel_ack, const u_char* data, int len, int caplen, bool is_orig,
analyzer::tcp::TCP_Flags flags);
bool DeliverData(double t, const u_char* data, int len, int caplen, const IP_Hdr* ip,
const struct tcphdr* tp, analyzer::tcp::TCP_Endpoint* endpoint,
uint64_t rel_data_seq, bool is_orig, analyzer::tcp::TCP_Flags flags);
bool DeliverData(double t, const u_char* data, int len, int caplen, const IP_Hdr* ip, const struct tcphdr* tp,
analyzer::tcp::TCP_Endpoint* endpoint, uint64_t rel_data_seq, bool is_orig,
analyzer::tcp::TCP_Flags flags);
void CheckPIA_FirstPacket(bool is_orig, const IP_Hdr* ip);
void CheckPIA_FirstPacket(bool is_orig, const IP_Hdr* ip);
friend class session::detail::Timer;
void AttemptTimer(double t);
void PartialCloseTimer(double t);
void ExpireTimer(double t);
void ResetTimer(double t);
void DeleteTimer(double t);
void ConnDeleteTimer(double t);
friend class session::detail::Timer;
void AttemptTimer(double t);
void PartialCloseTimer(double t);
void ExpireTimer(double t);
void ResetTimer(double t);
void DeleteTimer(double t);
void ConnDeleteTimer(double t);
void EndpointEOF(analyzer::tcp::TCP_Reassembler* endp);
void ConnectionClosed(analyzer::tcp::TCP_Endpoint* endpoint, analyzer::tcp::TCP_Endpoint* peer,
bool gen_event);
void ConnectionFinished(bool half_finished);
void ConnectionReset();
void PacketWithRST();
void EndpointEOF(analyzer::tcp::TCP_Reassembler* endp);
void ConnectionClosed(analyzer::tcp::TCP_Endpoint* endpoint, analyzer::tcp::TCP_Endpoint* peer, bool gen_event);
void ConnectionFinished(bool half_finished);
void ConnectionReset();
void PacketWithRST();
void SetReassembler(analyzer::tcp::TCP_Reassembler* rorig,
analyzer::tcp::TCP_Reassembler* rresp);
void SetReassembler(analyzer::tcp::TCP_Reassembler* rorig, analyzer::tcp::TCP_Reassembler* rresp);
uint64_t LastRelDataSeq() const { return rel_data_seq; }
uint64_t LastRelDataSeq() const { return rel_data_seq; }
private:
void SynWeirds(analyzer::tcp::TCP_Flags flags, analyzer::tcp::TCP_Endpoint* endpoint,
int data_len) const;
void SynWeirds(analyzer::tcp::TCP_Flags flags, analyzer::tcp::TCP_Endpoint* endpoint, int data_len) const;
int ParseTCPOptions(const struct tcphdr* tcp, bool is_orig);
int ParseTCPOptions(const struct tcphdr* tcp, bool is_orig);
void CheckRecording(bool need_contents, analyzer::tcp::TCP_Flags flags);
void CheckRecording(bool need_contents, analyzer::tcp::TCP_Flags flags);
analyzer::tcp::TCP_Endpoint* orig;
analyzer::tcp::TCP_Endpoint* resp;
analyzer::tcp::TCP_Endpoint* orig;
analyzer::tcp::TCP_Endpoint* resp;
analyzer::analyzer_list packet_children;
uint64_t rel_data_seq = 0;
analyzer::analyzer_list packet_children;
uint64_t rel_data_seq = 0;
unsigned int first_packet_seen : 2;
unsigned int reassembling : 1;
unsigned int is_partial : 1;
unsigned int is_active : 1;
unsigned int finished : 1;
unsigned int first_packet_seen : 2;
unsigned int reassembling : 1;
unsigned int is_partial : 1;
unsigned int is_active : 1;
unsigned int finished : 1;
// Whether we're waiting on final data delivery before closing
// this connection.
unsigned int close_deferred : 1;
// Whether we're waiting on final data delivery before closing
// this connection.
unsigned int close_deferred : 1;
// Whether to generate an event when we finally do close it.
unsigned int deferred_gen_event : 1;
// Whether to generate an event when we finally do close it.
unsigned int deferred_gen_event : 1;
// Whether we have seen the first ACK from the originator.
unsigned int seen_first_ACK : 1;
};
// Whether we have seen the first ACK from the originator.
unsigned int seen_first_ACK : 1;
};
} // namespace zeek::packet_analysis::tcp
} // namespace zeek::packet_analysis::TCP

View file

@ -5,22 +5,19 @@
#include "zeek/packet_analysis/Component.h"
#include "zeek/packet_analysis/protocol/teredo/Teredo.h"
namespace zeek::plugin::detail::Zeek_Teredo
{
namespace zeek::plugin::detail::Zeek_Teredo {
class Plugin final : public zeek::plugin::Plugin
{
class Plugin final : public zeek::plugin::Plugin {
public:
zeek::plugin::Configuration Configure() override
{
AddComponent(new zeek::packet_analysis::Component(
"Teredo", zeek::packet_analysis::teredo::TeredoAnalyzer::Instantiate));
zeek::plugin::Configuration Configure() override {
AddComponent(
new zeek::packet_analysis::Component("Teredo", zeek::packet_analysis::teredo::TeredoAnalyzer::Instantiate));
zeek::plugin::Configuration config;
config.name = "Zeek::Teredo";
config.description = "Teredo packet analyzer";
return config;
}
} plugin;
zeek::plugin::Configuration config;
config.name = "Zeek::Teredo";
config.description = "Teredo packet analyzer";
return config;
}
} plugin;
} // namespace zeek::plugin::detail::Zeek_Teredo
} // namespace zeek::plugin::detail::Zeek_Teredo

Some files were not shown because too many files have changed in this diff Show more