Merge remote-tracking branch 'origin/topic/timw/1114-analyzers'

* origin/topic/timw/1114-analyzers:
  Add type field to session::Key to help avoid collisions in map
  Move bad UDP checksum handling into adapter object
  Rename IPBasedTransportAnalyzer to SessionAdapter
  Move building session analyzer tree out of analyzer::Manager
  Rework the packet flow through the IP-based analyzers
  Add new UDP packet analyzer, remove old one
  Add new ICMP packet analyzer, remove old one
  Add base class for IP-based packet analyzers
  Move SessionManager::ParseIPPacket to IP analyzer's namespace
  Added skeletons for TCP/UDP/ICMP packet analysis plugins.
This commit is contained in:
Tim Wojtulewicz 2021-05-24 12:38:44 -07:00
commit aa09e02117
78 changed files with 1939 additions and 1403 deletions

28
CHANGES
View file

@ -1,4 +1,32 @@
4.1.0-dev.660 | 2021-05-24 12:38:44 -0700
* Add type field to session::Key to help avoid collisions in map (Tim Wojtulewicz, Corelight)
* Move bad UDP checksum handling into adapter object (Tim Wojtulewicz, Corelight)
* Rename IPBasedTransportAnalyzer to SessionAdapter (Tim Wojtulewicz, Corelight)
This also also combines the old TransportLayerAnalyzer class into
SessionAdapter, and removes the old class. This requires naming changes
in a few places but no functionality changes.
* Move building session analyzer tree out of analyzer::Manager (Tim Wojtulewicz, Corelight)
* Rework the packet flow through the IP-based analyzers (Tim Wojtulewicz, Corelight)
* Add new UDP packet analyzer, remove old one (Tim Wojtulewicz, Corelight)
* Add new ICMP packet analyzer, remove old one (Tim Wojtulewicz, Corelight)
* Add base class for IP-based packet analyzers (Tim Wojtulewicz, Corelight)
* Move SessionManager::ParseIPPacket to IP analyzer's namespace (Tim Wojtulewicz, Corelight)
* Added skeletons for TCP/UDP/ICMP packet analysis plugins. (Tim Wojtulewicz, Corelight)
This includes integration into the IP plugin and calling of the sessions code from each plugin.
4.1.0-dev.646 | 2021-05-18 11:47:25 -0700 4.1.0-dev.646 | 2021-05-18 11:47:25 -0700
* Omit unneeded decimal points in modp_dtoa2() scientific notation output (Jon Siwek, Corelight) * Omit unneeded decimal points in modp_dtoa2() scientific notation output (Jon Siwek, Corelight)

View file

@ -1 +1 @@
4.1.0-dev.646 4.1.0-dev.660

View file

@ -15,3 +15,6 @@
@load base/packet-protocols/gre @load base/packet-protocols/gre
@load base/packet-protocols/iptunnel @load base/packet-protocols/iptunnel
@load base/packet-protocols/vntag @load base/packet-protocols/vntag
@load base/packet-protocols/udp
@load base/packet-protocols/tcp
@load base/packet-protocols/icmp

View file

@ -0,0 +1 @@
@load ./main

View file

@ -0,0 +1,5 @@
module PacketAnalyzer::ICMP;
#event zeek_init() &priority=20
# {
# }

View file

@ -1,8 +1,22 @@
module PacketAnalyzer::IP; module PacketAnalyzer::IP;
const IPPROTO_TCP : count = 6;
const IPPROTO_UDP : count = 17;
const IPPROTO_ICMP : count = 1;
const IPPROTO_ICMP6 : count = 58;
const IPPROTO_IPIP : count = 4;
const IPPROTO_IPV6 : count = 41;
const IPPROTO_GRE : count = 47;
event zeek_init() &priority=20 event zeek_init() &priority=20
{ {
PacketAnalyzer::register_packet_analyzer(PacketAnalyzer::ANALYZER_IP, 4, PacketAnalyzer::ANALYZER_IPTUNNEL); PacketAnalyzer::register_packet_analyzer(PacketAnalyzer::ANALYZER_IP, IPPROTO_IPIP, PacketAnalyzer::ANALYZER_IPTUNNEL);
PacketAnalyzer::register_packet_analyzer(PacketAnalyzer::ANALYZER_IP, 41, PacketAnalyzer::ANALYZER_IPTUNNEL); PacketAnalyzer::register_packet_analyzer(PacketAnalyzer::ANALYZER_IP, IPPROTO_IPV6, PacketAnalyzer::ANALYZER_IPTUNNEL);
PacketAnalyzer::register_packet_analyzer(PacketAnalyzer::ANALYZER_IP, 47, PacketAnalyzer::ANALYZER_GRE); PacketAnalyzer::register_packet_analyzer(PacketAnalyzer::ANALYZER_IP, IPPROTO_GRE, PacketAnalyzer::ANALYZER_GRE);
PacketAnalyzer::register_packet_analyzer(PacketAnalyzer::ANALYZER_IP, IPPROTO_TCP, PacketAnalyzer::ANALYZER_TCP);
PacketAnalyzer::register_packet_analyzer(PacketAnalyzer::ANALYZER_IP, IPPROTO_UDP, PacketAnalyzer::ANALYZER_UDP);
PacketAnalyzer::register_packet_analyzer(PacketAnalyzer::ANALYZER_IP, IPPROTO_ICMP, PacketAnalyzer::ANALYZER_ICMP);
PacketAnalyzer::register_packet_analyzer(PacketAnalyzer::ANALYZER_IP, IPPROTO_ICMP6, PacketAnalyzer::ANALYZER_ICMP);
} }

View file

@ -0,0 +1 @@
@load ./main

View file

@ -0,0 +1,5 @@
module PacketAnalyzer::TCP;
#event zeek_init() &priority=20
# {
# }

View file

@ -0,0 +1 @@
@load ./main

View file

@ -0,0 +1,5 @@
module PacketAnalyzer::UDP;
#event zeek_init() &priority=20
# {
# }

View file

@ -19,6 +19,7 @@
#include "zeek/analyzer/Analyzer.h" #include "zeek/analyzer/Analyzer.h"
#include "zeek/analyzer/Manager.h" #include "zeek/analyzer/Manager.h"
#include "zeek/iosource/IOSource.h" #include "zeek/iosource/IOSource.h"
#include "zeek/packet_analysis/protocol/ip/SessionAdapter.h"
namespace zeek { namespace zeek {
@ -64,7 +65,7 @@ Connection::Connection(const detail::ConnKey& k, double t,
hist_seen = 0; hist_seen = 0;
history = ""; history = "";
root_analyzer = nullptr; adapter = nullptr;
primary_PIA = nullptr; primary_PIA = nullptr;
++current_connections; ++current_connections;
@ -83,7 +84,7 @@ Connection::~Connection()
if ( conn_val ) if ( conn_val )
conn_val->SetOrigin(nullptr); conn_val->SetOrigin(nullptr);
delete root_analyzer; delete adapter;
--current_connections; --current_connections;
} }
@ -129,7 +130,7 @@ void Connection::Done()
// somewhere, but it's session-related, so maybe not? // somewhere, but it's session-related, so maybe not?
if ( ConnTransport() == TRANSPORT_TCP ) if ( ConnTransport() == TRANSPORT_TCP )
{ {
auto ta = static_cast<analyzer::tcp::TCP_Analyzer*>(GetRootAnalyzer()); auto ta = static_cast<analyzer::tcp::TCP_Analyzer*>(adapter);
assert(ta->IsAnalyzer("TCP")); assert(ta->IsAnalyzer("TCP"));
analyzer::tcp::TCP_Endpoint* to = ta->Orig(); analyzer::tcp::TCP_Endpoint* to = ta->Orig();
analyzer::tcp::TCP_Endpoint* tr = ta->Resp(); analyzer::tcp::TCP_Endpoint* tr = ta->Resp();
@ -139,8 +140,8 @@ void Connection::Done()
finished = 1; finished = 1;
if ( root_analyzer && ! root_analyzer->IsFinished() ) if ( adapter && ! adapter->IsFinished() )
root_analyzer->Done(); adapter->Done();
} }
void Connection::NextPacket(double t, bool is_orig, void Connection::NextPacket(double t, bool is_orig,
@ -156,11 +157,11 @@ void Connection::NextPacket(double t, bool is_orig,
if ( Skipping() ) if ( Skipping() )
return; return;
if ( root_analyzer ) if ( adapter )
{ {
record_current_packet = record_packet; record_current_packet = record_packet;
record_current_content = record_content; record_current_content = record_content;
root_analyzer->NextPacket(len, data, is_orig, -1, ip, caplen); adapter->NextPacket(len, data, is_orig, -1, ip, caplen);
record_packet = record_current_packet; record_packet = record_current_packet;
record_content = record_current_content; record_content = record_current_content;
} }
@ -173,7 +174,7 @@ void Connection::NextPacket(double t, bool is_orig,
bool Connection::IsReuse(double t, const u_char* pkt) bool Connection::IsReuse(double t, const u_char* pkt)
{ {
return root_analyzer && root_analyzer->IsReuse(t, pkt); return adapter && adapter->IsReuse(t, pkt);
} }
bool Connection::ScaledHistoryEntry(char code, uint32_t& counter, bool Connection::ScaledHistoryEntry(char code, uint32_t& counter,
@ -275,8 +276,8 @@ const RecordValPtr& Connection::GetVal()
} }
if ( root_analyzer ) if ( adapter )
root_analyzer->UpdateConnVal(conn_val.get()); adapter->UpdateConnVal(conn_val.get());
conn_val->AssignTime(3, start_time); // ### conn_val->AssignTime(3, start_time); // ###
conn_val->AssignInterval(4, last_time - start_time); conn_val->AssignInterval(4, last_time - start_time);
@ -289,17 +290,17 @@ const RecordValPtr& Connection::GetVal()
analyzer::Analyzer* Connection::FindAnalyzer(analyzer::ID id) analyzer::Analyzer* Connection::FindAnalyzer(analyzer::ID id)
{ {
return root_analyzer ? root_analyzer->FindChild(id) : nullptr; return adapter ? adapter->FindChild(id) : nullptr;
} }
analyzer::Analyzer* Connection::FindAnalyzer(const analyzer::Tag& tag) analyzer::Analyzer* Connection::FindAnalyzer(const analyzer::Tag& tag)
{ {
return root_analyzer ? root_analyzer->FindChild(tag) : nullptr; return adapter ? adapter->FindChild(tag) : nullptr;
} }
analyzer::Analyzer* Connection::FindAnalyzer(const char* name) analyzer::Analyzer* Connection::FindAnalyzer(const char* name)
{ {
return root_analyzer->FindChild(name); return adapter->FindChild(name);
} }
void Connection::AppendAddl(const char* str) void Connection::AppendAddl(const char* str)
@ -370,8 +371,8 @@ void Connection::FlipRoles()
conn_val = nullptr; conn_val = nullptr;
if ( root_analyzer ) if ( adapter )
root_analyzer->FlipRoles(); adapter->FlipRoles();
analyzer_mgr->ApplyScheduledAnalyzers(this); analyzer_mgr->ApplyScheduledAnalyzers(this);
@ -383,7 +384,7 @@ unsigned int Connection::MemoryAllocation() const
return session::Session::MemoryAllocation() + padded_sizeof(*this) return session::Session::MemoryAllocation() + padded_sizeof(*this)
+ (timers.MemoryAllocation() - padded_sizeof(timers)) + (timers.MemoryAllocation() - padded_sizeof(timers))
+ (conn_val ? conn_val->MemoryAllocation() : 0) + (conn_val ? conn_val->MemoryAllocation() : 0)
+ (root_analyzer ? root_analyzer->MemoryAllocation(): 0) + (adapter ? adapter->MemoryAllocation(): 0)
// primary_PIA is already contained in the analyzer tree. // primary_PIA is already contained in the analyzer tree.
; ;
} }
@ -448,10 +449,10 @@ void Connection::IDString(ODesc* d) const
d->Add(ntohs(resp_port)); d->Add(ntohs(resp_port));
} }
void Connection::SetRootAnalyzer(analyzer::TransportLayerAnalyzer* analyzer, void Connection::SetSessionAdapter(packet_analysis::IP::SessionAdapter* aa,
analyzer::pia::PIA* pia) analyzer::pia::PIA* pia)
{ {
root_analyzer = analyzer; adapter = aa;
primary_PIA = pia; primary_PIA = pia;
} }

View file

@ -41,12 +41,8 @@ class RuleHdrTest;
} // namespace detail } // namespace detail
namespace analyzer { namespace analyzer { class Analyzer; }
namespace packet_analysis::IP { class SessionAdapter; }
class TransportLayerAnalyzer;
class Analyzer;
} // namespace analyzer
enum ConnEventToFlag { enum ConnEventToFlag {
NUL_IN_LINE, NUL_IN_LINE,
@ -117,7 +113,10 @@ public:
// should be marked invalid. // should be marked invalid.
const detail::ConnKey& Key() const { return key; } const detail::ConnKey& Key() const { return key; }
session::detail::Key SessionKey(bool copy) const override session::detail::Key SessionKey(bool copy) const override
{ return session::detail::Key{&key, sizeof(key), copy}; } {
return session::detail::Key{
&key, sizeof(key), session::detail::Key::CONNECTION_KEY_TYPE, copy};
}
const IPAddr& OrigAddr() const { return orig_addr; } const IPAddr& OrigAddr() const { return orig_addr; }
const IPAddr& RespAddr() const { return resp_addr; } const IPAddr& RespAddr() const { return resp_addr; }
@ -231,8 +230,8 @@ public:
void AddHistory(char code) { history += code; } void AddHistory(char code) { history += code; }
// Sets the root of the analyzer tree as well as the primary PIA. // Sets the root of the analyzer tree as well as the primary PIA.
void SetRootAnalyzer(analyzer::TransportLayerAnalyzer* analyzer, analyzer::pia::PIA* pia); void SetSessionAdapter(packet_analysis::IP::SessionAdapter* aa, analyzer::pia::PIA* pia);
analyzer::TransportLayerAnalyzer* GetRootAnalyzer() { return root_analyzer; } packet_analysis::IP::SessionAdapter* GetSessionAdapter() { return adapter; }
analyzer::pia::PIA* GetPrimaryPIA() { return primary_PIA; } analyzer::pia::PIA* GetPrimaryPIA() { return primary_PIA; }
// Sets the transport protocol in use. // Sets the transport protocol in use.
@ -279,7 +278,7 @@ private:
uint32_t hist_seen; uint32_t hist_seen;
std::string history; std::string history;
analyzer::TransportLayerAnalyzer* root_analyzer; packet_analysis::IP::SessionAdapter* adapter;
analyzer::pia::PIA* primary_PIA; analyzer::pia::PIA* primary_PIA;
UID uid; // Globally unique connection ID. UID uid; // Globally unique connection ID.

View file

@ -177,6 +177,7 @@ public:
bool operator!=( const DictIterator& that ) const { return !(*this == that); } bool operator!=( const DictIterator& that ) const { return !(*this == that); }
private: private:
friend class Dictionary; friend class Dictionary;
DictIterator(const Dictionary* d, detail::DictEntry* begin, detail::DictEntry* end); DictIterator(const Dictionary* d, detail::DictEntry* begin, detail::DictEntry* end);

View file

@ -25,12 +25,12 @@ namespace zeek::detail {
bool RuleConditionTCPState::DoMatch(Rule* rule, RuleEndpointState* state, bool RuleConditionTCPState::DoMatch(Rule* rule, RuleEndpointState* state,
const u_char* data, int len) const u_char* data, int len)
{ {
analyzer::Analyzer* root = state->GetAnalyzer()->Conn()->GetRootAnalyzer(); auto* adapter = state->GetAnalyzer()->Conn()->GetSessionAdapter();
if ( ! root || ! root->IsAnalyzer("TCP") ) if ( ! adapter || ! adapter->IsAnalyzer("TCP") )
return false; return false;
auto* ta = static_cast<analyzer::tcp::TCP_Analyzer*>(root); auto* ta = static_cast<analyzer::tcp::TCP_Analyzer*>(adapter);
if ( tcpstates & RULE_STATE_STATELESS ) if ( tcpstates & RULE_STATE_STATELESS )
return true; return true;
@ -57,9 +57,9 @@ void RuleConditionTCPState::PrintDebug()
bool RuleConditionUDPState::DoMatch(Rule* rule, RuleEndpointState* state, bool RuleConditionUDPState::DoMatch(Rule* rule, RuleEndpointState* state,
const u_char* data, int len) const u_char* data, int len)
{ {
analyzer::Analyzer* root = state->GetAnalyzer()->Conn()->GetRootAnalyzer(); auto* adapter = state->GetAnalyzer()->Conn()->GetSessionAdapter();
if ( ! root || ! root->IsAnalyzer("UDP") ) if ( ! adapter || ! adapter->IsAnalyzer("UDP") )
return false; return false;
if ( states & RULE_STATE_STATELESS ) if ( states & RULE_STATE_STATELESS )

View file

@ -880,31 +880,4 @@ void SupportAnalyzer::ForwardUndelivered(uint64_t seq, int len, bool is_orig)
} }
void TransportLayerAnalyzer::Done()
{
Analyzer::Done();
}
void TransportLayerAnalyzer::SetContentsFile(unsigned int /* direction */,
FilePtr /* f */)
{
reporter->Error("analyzer type does not support writing to a contents file");
}
FilePtr TransportLayerAnalyzer::GetContentsFile(unsigned int /* direction */) const
{
reporter->Error("analyzer type does not support writing to a contents file");
return nullptr;
}
void TransportLayerAnalyzer::PacketContents(const u_char* data, int len)
{
if ( packet_contents && len > 0 )
{
String* cbs = new String(data, len, true);
auto contents = make_intrusive<StringVal>(cbs);
EnqueueConnEvent(packet_contents, ConnVal(), std::move(contents));
}
}
} // namespace zeek::analyzer } // namespace zeek::analyzer

View file

@ -25,6 +25,7 @@ using FilePtr = zeek::IntrusivePtr<File>;
using RecordValPtr = zeek::IntrusivePtr<RecordVal>; using RecordValPtr = zeek::IntrusivePtr<RecordVal>;
namespace detail { class Rule; } namespace detail { class Rule; }
namespace packet_analysis::IP { class IPBasedAnalyzer; }
} // namespace zeek } // namespace zeek
@ -601,6 +602,7 @@ protected:
friend class Manager; friend class Manager;
friend class zeek::Connection; friend class zeek::Connection;
friend class zeek::analyzer::tcp::TCP_ApplicationAnalyzer; friend class zeek::analyzer::tcp::TCP_ApplicationAnalyzer;
friend class zeek::packet_analysis::IP::IPBasedAnalyzer;
/** /**
* Return a string represantation of an analyzer, containing its name * Return a string represantation of an analyzer, containing its name
@ -844,83 +846,4 @@ private:
#define CONTENTS_RESP 2 #define CONTENTS_RESP 2
#define CONTENTS_BOTH 3 #define CONTENTS_BOTH 3
/**
* Base class for analyzers parsing transport-layer protocols.
*/
class TransportLayerAnalyzer : public Analyzer {
public:
/**
* Constructor.
*
* @param name A name for the protocol the analyzer is parsing. The
* name must match the one the corresponding Component registers.
*
* @param conn The connection the analyzer is associated with.
*/
TransportLayerAnalyzer(const char* name, Connection* conn)
: Analyzer(name, conn) { pia = nullptr; }
/**
* Overridden from parent class.
*/
void Done() 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) = 0;
/**
* Associates a file with the analyzer in which to record all
* analyzed input. This must only be called with derived classes that
* overide 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 overide 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; }
/**
* 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 dass to pass to the event.
*
* @param len The length of \a data.
*/
void PacketContents(const u_char* data, int len);
private:
analyzer::pia::PIA* pia;
};
} // namespace zeek::analyzer } // namespace zeek::analyzer

View file

@ -8,11 +8,11 @@
#include "zeek/RunState.h" #include "zeek/RunState.h"
#include "zeek/analyzer/protocol/conn-size/ConnSize.h" #include "zeek/analyzer/protocol/conn-size/ConnSize.h"
#include "zeek/analyzer/protocol/icmp/ICMP.h"
#include "zeek/analyzer/protocol/pia/PIA.h" #include "zeek/analyzer/protocol/pia/PIA.h"
#include "zeek/analyzer/protocol/stepping-stone/SteppingStone.h" #include "zeek/analyzer/protocol/stepping-stone/SteppingStone.h"
#include "zeek/analyzer/protocol/tcp/TCP.h" #include "zeek/analyzer/protocol/tcp/TCP.h"
#include "zeek/analyzer/protocol/udp/UDP.h" #include "zeek/packet_analysis/protocol/ip/IPBasedAnalyzer.h"
#include "zeek/packet_analysis/protocol/ip/SessionAdapter.h"
#include "zeek/plugin/Manager.h" #include "zeek/plugin/Manager.h"
@ -354,15 +354,10 @@ Manager::tag_set* Manager::LookupPort(TransportProto proto, uint32_t port, bool
return l; return l;
} }
Manager::tag_set* Manager::LookupPort(PortVal* val, bool add_if_not_found)
{
return LookupPort(val->PortType(), val->Port(), add_if_not_found);
}
bool Manager::BuildInitialAnalyzerTree(Connection* conn) bool Manager::BuildInitialAnalyzerTree(Connection* conn)
{ {
analyzer::tcp::TCP_Analyzer* tcp = nullptr; analyzer::tcp::TCP_Analyzer* tcp = nullptr;
TransportLayerAnalyzer* root = nullptr; packet_analysis::IP::SessionAdapter* root = nullptr;
analyzer::pia::PIA* pia = nullptr; analyzer::pia::PIA* pia = nullptr;
bool check_port = false; bool check_port = false;
@ -375,19 +370,6 @@ bool Manager::BuildInitialAnalyzerTree(Connection* conn)
DBG_ANALYZER(conn, "activated TCP analyzer"); DBG_ANALYZER(conn, "activated TCP analyzer");
break; break;
case TRANSPORT_UDP:
root = new analyzer::udp::UDP_Analyzer(conn);
pia = new analyzer::pia::PIA_UDP(conn);
check_port = true;
DBG_ANALYZER(conn, "activated UDP analyzer");
break;
case TRANSPORT_ICMP: {
root = new analyzer::icmp::ICMP_Analyzer(conn);
DBG_ANALYZER(conn, "activated ICMP analyzer");
break;
}
default: default:
reporter->InternalWarning("unknown protocol can't build analyzer tree"); reporter->InternalWarning("unknown protocol can't build analyzer tree");
return false; return false;
@ -489,7 +471,7 @@ bool Manager::BuildInitialAnalyzerTree(Connection* conn)
if ( pia ) if ( pia )
root->AddChildAnalyzer(pia->AsAnalyzer()); root->AddChildAnalyzer(pia->AsAnalyzer());
conn->SetRootAnalyzer(root, pia); conn->SetSessionAdapter(root, pia);
root->Init(); root->Init();
root->InitChildren(); root->InitChildren();
@ -607,10 +589,11 @@ Manager::tag_set Manager::GetScheduled(const Connection* conn)
return result; return result;
} }
bool Manager::ApplyScheduledAnalyzers(Connection* conn, bool init, TransportLayerAnalyzer* parent) bool Manager::ApplyScheduledAnalyzers(Connection* conn, bool init,
packet_analysis::IP::SessionAdapter* parent)
{ {
if ( ! parent ) if ( ! parent )
parent = conn->GetRootAnalyzer(); parent = conn->GetSessionAdapter();
if ( ! parent ) if ( ! parent )
return false; return false;

View file

@ -35,6 +35,14 @@
#include "zeek/analyzer/analyzer.bif.h" #include "zeek/analyzer/analyzer.bif.h"
namespace zeek { namespace zeek {
namespace packet_analysis::IP {
class IPBasedAnalyzer;
class SessionAdapter;
} // namespace packet_analysis::IP
namespace analyzer { namespace analyzer {
/** /**
@ -244,8 +252,8 @@ public:
* *
* @param conn The connection to add the initial set of analyzers to. * @param conn The connection to add the initial set of analyzers to.
* *
* @return False if the tree cannot be build; that's usually an * @return False if the tree cannot be built; that's usually an
* internally error. * internal error.
*/ */
bool BuildInitialAnalyzerTree(Connection* conn); bool BuildInitialAnalyzerTree(Connection* conn);
@ -313,7 +321,7 @@ public:
* @return True if at least one scheduled analyzer was found. * @return True if at least one scheduled analyzer was found.
*/ */
bool ApplyScheduledAnalyzers(Connection* conn, bool init_and_event = true, bool ApplyScheduledAnalyzers(Connection* conn, bool init_and_event = true,
TransportLayerAnalyzer* parent = nullptr); packet_analysis::IP::SessionAdapter* parent = nullptr);
/** /**
* Schedules a particular analyzer for an upcoming connection. Once * Schedules a particular analyzer for an upcoming connection. Once
@ -345,10 +353,11 @@ public:
private: private:
friend class packet_analysis::IP::IPBasedAnalyzer;
using tag_set = std::set<Tag>; using tag_set = std::set<Tag>;
using analyzer_map_by_port = std::map<uint32_t, tag_set*>; using analyzer_map_by_port = std::map<uint32_t, tag_set*>;
tag_set* LookupPort(PortVal* val, bool add_if_not_found);
tag_set* LookupPort(TransportProto proto, uint32_t port, bool add_if_not_found); tag_set* LookupPort(TransportProto proto, uint32_t port, bool add_if_not_found);
tag_set GetScheduled(const Connection* conn); tag_set GetScheduled(const Connection* conn);

View file

@ -14,7 +14,6 @@ add_subdirectory(gnutella)
add_subdirectory(gssapi) add_subdirectory(gssapi)
add_subdirectory(gtpv1) add_subdirectory(gtpv1)
add_subdirectory(http) add_subdirectory(http)
add_subdirectory(icmp)
add_subdirectory(ident) add_subdirectory(ident)
add_subdirectory(imap) add_subdirectory(imap)
add_subdirectory(irc) add_subdirectory(irc)
@ -45,7 +44,6 @@ add_subdirectory(stepping-stone)
add_subdirectory(syslog) add_subdirectory(syslog)
add_subdirectory(tcp) add_subdirectory(tcp)
add_subdirectory(teredo) add_subdirectory(teredo)
add_subdirectory(udp)
add_subdirectory(vxlan) add_subdirectory(vxlan)
add_subdirectory(xmpp) add_subdirectory(xmpp)
add_subdirectory(zip) add_subdirectory(zip)

View file

@ -2,9 +2,9 @@
#include "zeek/analyzer/protocol/ayiya/AYIYA.h" #include "zeek/analyzer/protocol/ayiya/AYIYA.h"
#include "zeek/session/Manager.h"
#include "zeek/Func.h" #include "zeek/Func.h"
#include "zeek/packet_analysis/protocol/iptunnel/IPTunnel.h" #include "zeek/packet_analysis/protocol/iptunnel/IPTunnel.h"
#include "zeek/packet_analysis/protocol/ip/IP.h"
namespace zeek::analyzer::ayiya { namespace zeek::analyzer::ayiya {
@ -46,8 +46,8 @@ void AYIYA_Analyzer::DeliverPacket(int len, const u_char* data, bool orig, uint6
caplen -= inner_packet_offset; caplen -= inner_packet_offset;
inner_packet_offset = -1; inner_packet_offset = -1;
IP_Hdr* inner = nullptr; std::unique_ptr<IP_Hdr> inner;
int result = session_mgr->ParseIPPacket(len, data, next_header, inner); int result = packet_analysis::IP::ParsePacket(len, data, next_header, inner);
if ( result == 0 ) if ( result == 0 )
{ {
@ -66,9 +66,6 @@ void AYIYA_Analyzer::DeliverPacket(int len, const u_char* data, bool orig, uint6
else else
ProtocolViolation("AYIYA payload length", ProtocolViolation("AYIYA payload length",
reinterpret_cast<const char*>(data), len); reinterpret_cast<const char*>(data), len);
if ( result != 0 )
delete inner;
} }
} // namespace zeek::analyzer::ayiya } // namespace zeek::analyzer::ayiya

View file

@ -1,7 +1,5 @@
#pragma once #pragma once
#include "zeek/analyzer/protocol/udp/UDP.h"
#include "analyzer/protocol/dhcp/dhcp_pac.h" #include "analyzer/protocol/dhcp/dhcp_pac.h"
namespace zeek::analyzer::dhcp { namespace zeek::analyzer::dhcp {

View file

@ -1,7 +1,6 @@
#pragma once #pragma once
#include "zeek/analyzer/protocol/tcp/TCP.h" #include "zeek/analyzer/protocol/tcp/TCP.h"
#include "zeek/analyzer/protocol/udp/UDP.h"
#include "analyzer/protocol/dnp3/dnp3_pac.h" #include "analyzer/protocol/dnp3/dnp3_pac.h"

View file

@ -129,7 +129,7 @@ bool Gnutella_Analyzer::IsHTTP(std::string header)
if ( Parent()->IsAnalyzer("TCP") ) if ( Parent()->IsAnalyzer("TCP") )
{ {
// Replay buffered data. // Replay buffered data.
analyzer::pia::PIA* pia = static_cast<analyzer::TransportLayerAnalyzer *>(Parent())->GetPIA(); analyzer::pia::PIA* pia = static_cast<packet_analysis::IP::SessionAdapter*>(Parent())->GetPIA();
if ( pia ) if ( pia )
static_cast<analyzer::pia::PIA_TCP *>(pia)->ReplayStreamBuffer(a); static_cast<analyzer::pia::PIA_TCP *>(pia)->ReplayStreamBuffer(a);
} }

View file

@ -2,8 +2,8 @@
#include "zeek/analyzer/protocol/gtpv1/GTPv1.h" #include "zeek/analyzer/protocol/gtpv1/GTPv1.h"
#include "zeek/packet_analysis/protocol/iptunnel/IPTunnel.h" #include "zeek/packet_analysis/protocol/iptunnel/IPTunnel.h"
#include "zeek/packet_analysis/protocol/ip/IP.h"
#include "zeek/session/Manager.h"
#include "zeek/analyzer/protocol/gtpv1/events.bif.h" #include "zeek/analyzer/protocol/gtpv1/events.bif.h"
namespace zeek::analyzer::gtpv1 { namespace zeek::analyzer::gtpv1 {
@ -47,8 +47,8 @@ void GTPv1_Analyzer::DeliverPacket(int len, const u_char* data, bool orig, uint6
caplen -= inner_packet_offset; caplen -= inner_packet_offset;
inner_packet_offset = -1; inner_packet_offset = -1;
IP_Hdr* inner = nullptr; std::unique_ptr<IP_Hdr> inner = nullptr;
int result = session_mgr->ParseIPPacket(len, data, next_header, inner); int result = packet_analysis::IP::ParsePacket(len, data, next_header, inner);
if ( result == 0 ) if ( result == 0 )
{ {
@ -77,9 +77,6 @@ void GTPv1_Analyzer::DeliverPacket(int len, const u_char* data, bool orig, uint6
else else
ProtocolViolation("GTPv1 payload length", ProtocolViolation("GTPv1 payload length",
reinterpret_cast<const char*>(odata), olen); reinterpret_cast<const char*>(odata), olen);
if ( result != 0 )
delete inner;
} }
} // namespace zeek::analyzer::gtpv1 } // namespace zeek::analyzer::gtpv1

View file

@ -1,99 +0,0 @@
// See the file "COPYING" in the main distribution directory for copyright.
#pragma once
#include "zeek/RuleMatcher.h"
#include "zeek/analyzer/Analyzer.h"
#include "zeek/net_util.h"
namespace zeek {
class VectorVal;
using VectorValPtr = IntrusivePtr<VectorVal>;
namespace analyzer::icmp {
enum ICMP_EndpointState {
ICMP_INACTIVE, // no packet seen
ICMP_ACTIVE, // packets seen
};
// We do not have an PIA for ICMP (yet) and therefore derive from
// RuleMatcherState to perform our own matching.
class ICMP_Analyzer final : public analyzer::TransportLayerAnalyzer {
public:
explicit ICMP_Analyzer(Connection* conn);
void UpdateConnVal(RecordVal *conn_val) override;
static analyzer::Analyzer* Instantiate(Connection* conn)
{ return new ICMP_Analyzer(conn); }
protected:
void Done() override;
void DeliverPacket(int len, const u_char* data, bool orig,
uint64_t seq, const IP_Hdr* ip, int caplen) override;
bool IsReuse(double t, const u_char* pkt) override;
unsigned int MemoryAllocation() const override;
void ICMP_Sent(const struct icmp* icmpp, int len, int caplen, int icmpv6,
const u_char* data, const IP_Hdr* ip_hdr);
void Echo(double t, const struct icmp* icmpp, int len,
int caplen, const u_char*& data, const IP_Hdr* ip_hdr);
void Redirect(double t, const struct icmp* icmpp, int len,
int caplen, const u_char*& data, const IP_Hdr* ip_hdr);
void RouterAdvert(double t, const struct icmp* icmpp, int len,
int caplen, const u_char*& data, const IP_Hdr* ip_hdr);
void NeighborAdvert(double t, const struct icmp* icmpp, int len,
int caplen, const u_char*& data, const IP_Hdr* ip_hdr);
void NeighborSolicit(double t, const struct icmp* icmpp, int len,
int caplen, const u_char*& data, const IP_Hdr* ip_hdr);
void RouterSolicit(double t, const struct icmp* icmpp, int len,
int caplen, const u_char*& data, const IP_Hdr* ip_hdr);
void Describe(ODesc* d) const;
RecordValPtr BuildInfo(const struct icmp* icmpp, int len,
bool icmpv6, const IP_Hdr* ip_hdr);
void NextICMP4(double t, const struct icmp* icmpp, int len, int caplen,
const u_char*& data, const IP_Hdr* ip_hdr );
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);
TransportProto GetContextProtocol(const IP_Hdr* ip_hdr, uint32_t* src_port,
uint32_t* dst_port);
void NextICMP6(double t, const struct icmp* icmpp, int len, int caplen,
const u_char*& data, const IP_Hdr* ip_hdr );
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);
// RFC 4861 Neighbor Discover message options
VectorValPtr BuildNDOptionsVal(int caplen, const u_char* data);
RecordValPtr icmp_conn_val;
int type;
int code;
int request_len, reply_len;
detail::RuleMatcherState matcher_state;
private:
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 analyzer::icmp
} // namespace zeek

View file

@ -1,22 +0,0 @@
// See the file in the main distribution directory for copyright.
#include "zeek/plugin/Plugin.h"
#include "zeek/analyzer/Component.h"
#include "zeek/analyzer/protocol/icmp/ICMP.h"
namespace zeek::plugin::detail::Zeek_ICMP {
class Plugin : public zeek::plugin::Plugin {
public:
zeek::plugin::Configuration Configure() override
{
AddComponent(new zeek::analyzer::Component("ICMP", zeek::analyzer::icmp::ICMP_Analyzer::Instantiate));
zeek::plugin::Configuration config;
config.name = "Zeek::ICMP";
config.description = "ICMP analyzer";
return config;
}
} plugin;
} // namespace zeek::plugin::detail::Zeek_ICMP

View file

@ -2,7 +2,6 @@
#pragma once #pragma once
#include "zeek/analyzer/protocol/udp/UDP.h"
#include "zeek/analyzer/protocol/tcp/TCP.h" #include "zeek/analyzer/protocol/tcp/TCP.h"
namespace zeek::analyzer::netbios_ssn { namespace zeek::analyzer::netbios_ssn {

View file

@ -1,7 +1,5 @@
#pragma once #pragma once
#include "zeek/analyzer/protocol/udp/UDP.h"
#include "zeek/analyzer/protocol/ntp/events.bif.h" #include "zeek/analyzer/protocol/ntp/events.bif.h"
#include "zeek/analyzer/protocol/ntp/types.bif.h" #include "zeek/analyzer/protocol/ntp/types.bif.h"
#include "zeek/analyzer/protocol/ntp/ntp_pac.h" #include "zeek/analyzer/protocol/ntp/ntp_pac.h"

View file

@ -1,7 +1,5 @@
#pragma once #pragma once
#include "zeek/analyzer/protocol/udp/UDP.h"
#include "zeek/analyzer/protocol/radius/events.bif.h" #include "zeek/analyzer/protocol/radius/events.bif.h"
#include "zeek/analyzer/protocol/radius/radius_pac.h" #include "zeek/analyzer/protocol/radius/radius_pac.h"

View file

@ -1,7 +1,5 @@
#pragma once #pragma once
#include "zeek/analyzer/protocol/udp/UDP.h"
#include "zeek/analyzer/protocol/rdp/events.bif.h" #include "zeek/analyzer/protocol/rdp/events.bif.h"
#include "zeek/analyzer/protocol/rdp/rdpeudp_pac.h" #include "zeek/analyzer/protocol/rdp/rdpeudp_pac.h"

View file

@ -1,7 +1,5 @@
#pragma once #pragma once
#include "zeek/analyzer/protocol/udp/UDP.h"
#include "zeek/analyzer/protocol/sip/events.bif.h" #include "zeek/analyzer/protocol/sip/events.bif.h"
#include "zeek/analyzer/protocol/sip/sip_pac.h" #include "zeek/analyzer/protocol/sip/sip_pac.h"

View file

@ -1,7 +1,5 @@
#pragma once #pragma once
#include "zeek/analyzer/protocol/udp/UDP.h"
#include "zeek/analyzer/protocol/ssl/events.bif.h" #include "zeek/analyzer/protocol/ssl/events.bif.h"
namespace binpac { namespace DTLS { class SSL_Conn; } } namespace binpac { namespace DTLS { class SSL_Conn; } }

View file

@ -1,6 +1,5 @@
#pragma once #pragma once
#include "zeek/analyzer/protocol/udp/UDP.h"
#include "zeek/analyzer/protocol/tcp/TCP.h" #include "zeek/analyzer/protocol/tcp/TCP.h"
#include "analyzer/protocol/syslog/syslog_pac.h" #include "analyzer/protocol/syslog/syslog_pac.h"

View file

@ -123,7 +123,7 @@ static RecordVal* build_syn_packet_val(bool is_orig, const IP_Hdr* ip,
TCP_Analyzer::TCP_Analyzer(Connection* conn) TCP_Analyzer::TCP_Analyzer(Connection* conn)
: TransportLayerAnalyzer("TCP", conn) : packet_analysis::IP::SessionAdapter("TCP", conn)
{ {
// Set a timer to eventually time out this connection. // Set a timer to eventually time out this connection.
ADD_ANALYZER_TIMER(&TCP_Analyzer::ExpireTimer, ADD_ANALYZER_TIMER(&TCP_Analyzer::ExpireTimer,
@ -180,7 +180,7 @@ void TCP_Analyzer::Done()
analyzer::Analyzer* TCP_Analyzer::FindChild(analyzer::ID arg_id) analyzer::Analyzer* TCP_Analyzer::FindChild(analyzer::ID arg_id)
{ {
analyzer::Analyzer* child = analyzer::TransportLayerAnalyzer::FindChild(arg_id); analyzer::Analyzer* child = packet_analysis::IP::SessionAdapter::FindChild(arg_id);
if ( child ) if ( child )
return child; return child;
@ -197,7 +197,7 @@ analyzer::Analyzer* TCP_Analyzer::FindChild(analyzer::ID arg_id)
analyzer::Analyzer* TCP_Analyzer::FindChild(analyzer::Tag arg_tag) analyzer::Analyzer* TCP_Analyzer::FindChild(analyzer::Tag arg_tag)
{ {
analyzer::Analyzer* child = analyzer::TransportLayerAnalyzer::FindChild(arg_tag); analyzer::Analyzer* child = packet_analysis::IP::SessionAdapter::FindChild(arg_tag);
if ( child ) if ( child )
return child; return child;
@ -214,7 +214,7 @@ analyzer::Analyzer* TCP_Analyzer::FindChild(analyzer::Tag arg_tag)
bool TCP_Analyzer::RemoveChildAnalyzer(analyzer::ID id) bool TCP_Analyzer::RemoveChildAnalyzer(analyzer::ID id)
{ {
auto rval = analyzer::TransportLayerAnalyzer::RemoveChildAnalyzer(id); auto rval = packet_analysis::IP::SessionAdapter::RemoveChildAnalyzer(id);
if ( rval ) if ( rval )
return rval; return rval;
@ -1048,7 +1048,7 @@ static int32_t update_last_seq(TCP_Endpoint* endpoint, uint32_t last_seq,
void TCP_Analyzer::DeliverPacket(int len, const u_char* data, bool is_orig, void TCP_Analyzer::DeliverPacket(int len, const u_char* data, bool is_orig,
uint64_t seq, const IP_Hdr* ip, int caplen) uint64_t seq, const IP_Hdr* ip, int caplen)
{ {
TransportLayerAnalyzer::DeliverPacket(len, data, orig, seq, ip, caplen); packet_analysis::IP::SessionAdapter::DeliverPacket(len, data, orig, seq, ip, caplen);
const struct tcphdr* tp = ExtractTCP_Header(data, len, caplen); const struct tcphdr* tp = ExtractTCP_Header(data, len, caplen);
if ( ! tp ) if ( ! tp )

View file

@ -6,6 +6,7 @@
#include "zeek/IPAddr.h" #include "zeek/IPAddr.h"
#include "zeek/analyzer/protocol/tcp/TCP_Endpoint.h" #include "zeek/analyzer/protocol/tcp/TCP_Endpoint.h"
#include "zeek/analyzer/protocol/tcp/TCP_Flags.h" #include "zeek/analyzer/protocol/tcp/TCP_Flags.h"
#include "zeek/packet_analysis/protocol/ip/SessionAdapter.h"
#include "zeek/Conn.h" #include "zeek/Conn.h"
// We define two classes here: // We define two classes here:
@ -22,7 +23,7 @@ class TCP_Endpoint;
class TCP_Reassembler; class TCP_Reassembler;
class TCP_ApplicationAnalyzer; class TCP_ApplicationAnalyzer;
class TCP_Analyzer final : public analyzer::TransportLayerAnalyzer { class TCP_Analyzer final : public packet_analysis::IP::SessionAdapter {
public: public:
explicit TCP_Analyzer(Connection* conn); explicit TCP_Analyzer(Connection* conn);
~TCP_Analyzer() override; ~TCP_Analyzer() override;
@ -72,6 +73,8 @@ public:
static analyzer::Analyzer* Instantiate(Connection* conn) static analyzer::Analyzer* Instantiate(Connection* conn)
{ return new TCP_Analyzer(conn); } { return new TCP_Analyzer(conn); }
void AddExtraAnalyzers(Connection* conn) override {}
protected: protected:
friend class TCP_ApplicationAnalyzer; friend class TCP_ApplicationAnalyzer;
friend class TCP_Reassembler; friend class TCP_Reassembler;

View file

@ -101,7 +101,7 @@ function set_contents_file%(cid: conn_id, direction: count, f: file%): bool
if ( ! c ) if ( ! c )
return zeek::val_mgr->False(); return zeek::val_mgr->False();
c->GetRootAnalyzer()->SetContentsFile(direction, {zeek::NewRef{}, f}); c->GetSessionAdapter()->SetContentsFile(direction, {zeek::NewRef{}, f});
return zeek::val_mgr->True(); return zeek::val_mgr->True();
%} %}
@ -124,7 +124,7 @@ function get_contents_file%(cid: conn_id, direction: count%): file
if ( c ) if ( c )
{ {
auto cf = c->GetRootAnalyzer()->GetContentsFile(direction); auto cf = c->GetSessionAdapter()->GetContentsFile(direction);
if ( cf ) if ( cf )
return zeek::make_intrusive<zeek::FileVal>(std::move(cf)); return zeek::make_intrusive<zeek::FileVal>(std::move(cf));

View file

@ -4,10 +4,10 @@
#include "zeek/Conn.h" #include "zeek/Conn.h"
#include "zeek/IP.h" #include "zeek/IP.h"
#include "zeek/Reporter.h" #include "zeek/Reporter.h"
#include "zeek/session/Manager.h"
#include "zeek/ZeekString.h" #include "zeek/ZeekString.h"
#include "zeek/RunState.h" #include "zeek/RunState.h"
#include "zeek/packet_analysis/protocol/iptunnel/IPTunnel.h" #include "zeek/packet_analysis/protocol/iptunnel/IPTunnel.h"
#include "zeek/packet_analysis/protocol/ip/IP.h"
#include "zeek/analyzer/protocol/teredo/events.bif.h" #include "zeek/analyzer/protocol/teredo/events.bif.h"
@ -94,7 +94,7 @@ bool TeredoEncapsulation::DoParse(const u_char* data, int& len,
return false; return false;
} }
RecordValPtr TeredoEncapsulation::BuildVal(const IP_Hdr* inner) const RecordValPtr TeredoEncapsulation::BuildVal(const std::unique_ptr<IP_Hdr>& inner) const
{ {
static auto teredo_hdr_type = id::find_type<RecordType>("teredo_hdr"); static auto teredo_hdr_type = id::find_type<RecordType>("teredo_hdr");
static auto teredo_auth_type = id::find_type<RecordType>("teredo_auth"); static auto teredo_auth_type = id::find_type<RecordType>("teredo_auth");
@ -164,8 +164,8 @@ void Teredo_Analyzer::DeliverPacket(int len, const u_char* data, bool orig,
return; return;
} }
IP_Hdr* inner = nullptr; std::unique_ptr<IP_Hdr> inner = nullptr;
int rslt = session_mgr->ParseIPPacket(len, te.InnerIP(), IPPROTO_IPV6, inner); int rslt = packet_analysis::IP::ParsePacket(len, te.InnerIP(), IPPROTO_IPV6, inner);
if ( rslt > 0 ) if ( rslt > 0 )
{ {
@ -175,7 +175,6 @@ void Teredo_Analyzer::DeliverPacket(int len, const u_char* data, bool orig,
Weird("Teredo_bubble_with_payload", true); Weird("Teredo_bubble_with_payload", true);
else else
{ {
delete inner;
ProtocolViolation("Teredo payload length", (const char*) data, len); ProtocolViolation("Teredo payload length", (const char*) data, len);
return; return;
} }
@ -193,7 +192,6 @@ void Teredo_Analyzer::DeliverPacket(int len, const u_char* data, bool orig,
else else
{ {
delete inner;
ProtocolViolation("Truncated Teredo or invalid inner IP version", (const char*) data, len); ProtocolViolation("Truncated Teredo or invalid inner IP version", (const char*) data, len);
return; return;
} }

View file

@ -74,7 +74,7 @@ public:
const u_char* Authentication() const const u_char* Authentication() const
{ return auth; } { return auth; }
RecordValPtr BuildVal(const IP_Hdr* inner) const; RecordValPtr BuildVal(const std::unique_ptr<IP_Hdr>& inner) const;
protected: protected:
bool DoParse(const u_char* data, int& len, bool found_orig, bool found_au); bool DoParse(const u_char* data, int& len, bool found_orig, bool found_au);

View file

@ -1,22 +0,0 @@
// See the file in the main distribution directory for copyright.
#include "zeek/plugin/Plugin.h"
#include "zeek/analyzer/Component.h"
#include "zeek/analyzer/protocol/udp/UDP.h"
namespace zeek::plugin::detail::Zeek_UDP {
class Plugin : public zeek::plugin::Plugin {
public:
zeek::plugin::Configuration Configure() override
{
AddComponent(new zeek::analyzer::Component("UDP", zeek::analyzer::udp::UDP_Analyzer::Instantiate));
zeek::plugin::Configuration config;
config.name = "Zeek::UDP";
config.description = "UDP Analyzer";
return config;
}
} plugin;
} // namespace zeek::plugin::detail::Zeek_UDP

View file

@ -1,275 +0,0 @@
// See the file "COPYING" in the main distribution directory for copyright.
#include "zeek/zeek-config.h"
#include "zeek/analyzer/protocol/udp/UDP.h"
#include <algorithm>
#include "zeek/RunState.h"
#include "zeek/NetVar.h"
#include "zeek/analyzer/Manager.h"
#include "zeek/Reporter.h"
#include "zeek/Conn.h"
#include "zeek/analyzer/protocol/udp/events.bif.h"
namespace zeek::analyzer::udp {
UDP_Analyzer::UDP_Analyzer(Connection* conn)
: analyzer::TransportLayerAnalyzer("UDP", conn)
{
conn->EnableStatusUpdateTimer();
conn->SetInactivityTimeout(zeek::detail::udp_inactivity_timeout);
request_len = reply_len = -1; // -1 means "haven't seen any activity"
req_chk_cnt = rep_chk_cnt = 0;
req_chk_thresh = rep_chk_thresh = 1;
}
UDP_Analyzer::~UDP_Analyzer()
{
// XXX: need to implement this!
// delete src_pkt_writer;
}
void UDP_Analyzer::Init()
{
}
void UDP_Analyzer::Done()
{
Analyzer::Done();
}
void UDP_Analyzer::DeliverPacket(int len, const u_char* data, bool is_orig,
uint64_t seq, const IP_Hdr* ip, int caplen)
{
assert(ip);
Analyzer::DeliverPacket(len, data, is_orig, seq, ip, caplen);
const struct udphdr* up = (const struct udphdr*) data;
// Increment data before checksum check so that data will
// point to UDP payload even if checksum fails. Particularly,
// it allows event packet_contents to get to the data.
data += sizeof(struct udphdr);
// We need the min() here because Ethernet frame padding can lead to
// caplen > len.
if ( packet_contents )
PacketContents(data, std::min(len, caplen) - sizeof(struct udphdr));
int chksum = up->uh_sum;
auto validate_checksum =
! run_state::current_pkt->l3_checksummed &&
! zeek::detail::ignore_checksums &&
! zeek::id::find_val<TableVal>("ignore_checksums_nets")->Contains(ip->IPHeaderSrcAddr()) &&
caplen >=len;
constexpr auto vxlan_len = 8;
constexpr auto eth_len = 14;
if ( validate_checksum &&
len > ((int)sizeof(struct udphdr) + vxlan_len + eth_len) &&
(data[0] & 0x08) == 0x08 )
{
auto& vxlan_ports = analyzer_mgr->GetVxlanPorts();
if ( std::find(vxlan_ports.begin(), vxlan_ports.end(),
ntohs(up->uh_dport)) != vxlan_ports.end() )
{
// Looks like VXLAN on a well-known port, so the checksum should be
// transmitted as zero, and we should accept that. If not
// transmitted as zero, then validating the checksum is optional.
if ( chksum == 0 )
validate_checksum = false;
else
validate_checksum = BifConst::Tunnel::validate_vxlan_checksums;
}
}
if ( validate_checksum )
{
bool bad = false;
if ( ip->IP4_Hdr() )
{
if ( chksum && ! ValidateChecksum(ip, up, len) )
bad = true;
}
/* checksum is not optional for IPv6 */
else if ( ! ValidateChecksum(ip, up, len) )
bad = true;
if ( bad )
{
Weird("bad_UDP_checksum");
if ( is_orig )
{
uint32_t t = req_chk_thresh;
if ( Conn()->ScaledHistoryEntry('C', req_chk_cnt,
req_chk_thresh) )
ChecksumEvent(is_orig, t);
}
else
{
uint32_t t = rep_chk_thresh;
if ( Conn()->ScaledHistoryEntry('c', rep_chk_cnt,
rep_chk_thresh) )
ChecksumEvent(is_orig, t);
}
return;
}
}
int ulen = ntohs(up->uh_ulen);
if ( ulen != len )
Weird("UDP_datagram_length_mismatch", util::fmt("%d != %d", ulen, len));
len -= sizeof(struct udphdr);
ulen -= sizeof(struct udphdr);
caplen -= sizeof(struct udphdr);
Conn()->SetLastTime(run_state::current_timestamp);
if ( udp_contents )
{
static auto udp_content_ports = id::find_val<TableVal>("udp_content_ports");
static auto udp_content_delivery_ports_orig = id::find_val<TableVal>("udp_content_delivery_ports_orig");
static auto udp_content_delivery_ports_resp = id::find_val<TableVal>("udp_content_delivery_ports_resp");
bool do_udp_contents = false;
const auto& sport_val = val_mgr->Port(ntohs(up->uh_sport), TRANSPORT_UDP);
const auto& dport_val = val_mgr->Port(ntohs(up->uh_dport), TRANSPORT_UDP);
if ( udp_content_ports->FindOrDefault(dport_val) ||
udp_content_ports->FindOrDefault(sport_val) )
do_udp_contents = true;
else
{
uint16_t p = zeek::detail::udp_content_delivery_ports_use_resp ? Conn()->RespPort()
: up->uh_dport;
const auto& port_val = zeek::val_mgr->Port(ntohs(p), TRANSPORT_UDP);
if ( is_orig )
{
auto result = udp_content_delivery_ports_orig->FindOrDefault(port_val);
if ( zeek::detail::udp_content_deliver_all_orig || (result && result->AsBool()) )
do_udp_contents = true;
}
else
{
auto result = udp_content_delivery_ports_resp->FindOrDefault(port_val);
if ( zeek::detail::udp_content_deliver_all_resp || (result && result->AsBool()) )
do_udp_contents = true;
}
}
if ( do_udp_contents )
EnqueueConnEvent(udp_contents,
ConnVal(),
val_mgr->Bool(is_orig),
make_intrusive<StringVal>(len, (const char*) data));
}
if ( is_orig )
{
Conn()->CheckHistory(HIST_ORIG_DATA_PKT, 'D');
if ( request_len < 0 )
request_len = ulen;
else
{
request_len += ulen;
#ifdef DEBUG
if ( request_len < 0 )
reporter->Warning("wrapping around for UDP request length");
#endif
}
Event(udp_request);
}
else
{
Conn()->CheckHistory(HIST_RESP_DATA_PKT, 'd');
if ( reply_len < 0 )
reply_len = ulen;
else
{
reply_len += ulen;
#ifdef DEBUG
if ( reply_len < 0 )
reporter->Warning("wrapping around for UDP reply length");
#endif
}
Event(udp_reply);
}
if ( caplen >= len )
ForwardPacket(len, data, is_orig, seq, ip, caplen);
}
void UDP_Analyzer::UpdateConnVal(RecordVal* conn_val)
{
auto orig_endp = conn_val->GetFieldAs<RecordVal>("orig");
auto resp_endp = conn_val->GetFieldAs<RecordVal>("resp");
UpdateEndpointVal(orig_endp, true);
UpdateEndpointVal(resp_endp, false);
// Call children's UpdateConnVal
Analyzer::UpdateConnVal(conn_val);
}
void UDP_Analyzer::UpdateEndpointVal(RecordVal* endp, bool is_orig)
{
bro_int_t size = is_orig ? request_len : reply_len;
if ( size < 0 )
{
endp->Assign(0, 0);
endp->Assign(1, UDP_INACTIVE);
}
else
{
endp->Assign(0, static_cast<uint64_t>(size));
endp->Assign(1, UDP_ACTIVE);
}
}
bool UDP_Analyzer::IsReuse(double /* t */, const u_char* /* pkt */)
{
return false;
}
unsigned int UDP_Analyzer::MemoryAllocation() const
{
// A rather low lower bound....
return Analyzer::MemoryAllocation() + padded_sizeof(*this) - 24;
}
void UDP_Analyzer::ChecksumEvent(bool is_orig, uint32_t threshold)
{
Conn()->HistoryThresholdEvent(udp_multiple_checksum_errors,
is_orig, threshold);
}
bool UDP_Analyzer::ValidateChecksum(const IP_Hdr* ip, const udphdr* up, int len)
{
auto sum = detail::ip_in_cksum(ip->IP4_Hdr(), ip->SrcAddr(), ip->DstAddr(),
IPPROTO_UDP,
reinterpret_cast<const uint8_t*>(up), len);
return sum == 0xffff;
}
} // namespace zeek::analyzer::udp

View file

@ -1,57 +0,0 @@
// See the file "COPYING" in the main distribution directory for copyright.
#pragma once
// This will include netinet/udp.h for us, plus set up some defines that make it work on all
// of the CI platforms.
#include "zeek/net_util.h"
#include "zeek/analyzer/Analyzer.h"
namespace zeek::analyzer::udp {
enum UDP_EndpointState {
UDP_INACTIVE, // no packet seen
UDP_ACTIVE, // packets seen
};
class UDP_Analyzer final : public analyzer::TransportLayerAnalyzer {
public:
explicit UDP_Analyzer(Connection* conn);
~UDP_Analyzer() override;
void Init() override;
void UpdateConnVal(RecordVal *conn_val) override;
static analyzer::Analyzer* Instantiate(Connection* conn)
{ return new UDP_Analyzer(conn); }
protected:
void Done() override;
void DeliverPacket(int len, const u_char* data, bool orig,
uint64_t seq, const IP_Hdr* ip, int caplen) override;
bool IsReuse(double t, const u_char* pkt) override;
unsigned int MemoryAllocation() const override;
void ChecksumEvent(bool is_orig, uint32_t threshold);
// Returns true if the checksum is valid, false if not
static bool ValidateChecksum(const IP_Hdr* ip, const struct udphdr* up,
int len);
bro_int_t request_len, reply_len;
private:
void UpdateEndpointVal(RecordVal* endp, bool is_orig);
#define HIST_ORIG_DATA_PKT 0x1
#define HIST_RESP_DATA_PKT 0x2
#define HIST_ORIG_CORRUPT_PKT 0x4
#define HIST_RESP_CORRUPT_PKT 0x8
// For tracking checksum history.
uint32_t req_chk_cnt, req_chk_thresh;
uint32_t rep_chk_cnt, rep_chk_thresh;
};
} // namespace zeek::analyzer::udp

View file

@ -41,7 +41,7 @@ static zeek::analyzer::Analyzer* add_analyzer(zeek::Connection* conn)
auto a = zeek::analyzer_mgr->InstantiateAnalyzer(ZEEK_FUZZ_ANALYZER, conn); auto a = zeek::analyzer_mgr->InstantiateAnalyzer(ZEEK_FUZZ_ANALYZER, conn);
tcp->AddChildAnalyzer(a); tcp->AddChildAnalyzer(a);
tcp->AddChildAnalyzer(pia->AsAnalyzer()); tcp->AddChildAnalyzer(pia->AsAnalyzer());
conn->SetRootAnalyzer(tcp, pia); conn->SetSessionAdapter(tcp, pia);
return a; return a;
} }

View file

@ -189,6 +189,13 @@ public:
*/ */
mutable bool dump_packet; mutable bool dump_packet;
/**
* Indicates the amount of data to be dumped. If only a header is needed,
* set this to the size of the header. Setting it to zero will dump the
* entire packet.
*/
mutable int dump_size = 0;
// These are fields passed between various packet analyzers. They're best // These are fields passed between various packet analyzers. They're best
// stored with the packet so they stay available as the packet is passed // stored with the packet so they stay available as the packet is passed
// around. // around.

View file

@ -10,7 +10,8 @@
namespace zeek::packet_analysis { namespace zeek::packet_analysis {
Analyzer::Analyzer(std::string name) Analyzer::Analyzer(std::string name, bool report_unknown_protocols) :
report_unknown_protocols(report_unknown_protocols)
{ {
Tag t = packet_mgr->GetComponentTag(name); Tag t = packet_mgr->GetComponentTag(name);
@ -79,12 +80,17 @@ bool Analyzer::ForwardPacket(size_t len, const uint8_t* data, Packet* packet,
inner_analyzer = default_analyzer; inner_analyzer = default_analyzer;
if ( inner_analyzer == nullptr ) if ( inner_analyzer == nullptr )
{
if ( report_unknown_protocols )
{ {
DBG_LOG(DBG_PACKET_ANALYSIS, "Analysis in %s failed, could not find analyzer for identifier %#x.", DBG_LOG(DBG_PACKET_ANALYSIS, "Analysis in %s failed, could not find analyzer for identifier %#x.",
GetAnalyzerName(), identifier); GetAnalyzerName(), identifier);
packet_mgr->ReportUnknownProtocol(GetAnalyzerName(), identifier, data, len); packet_mgr->ReportUnknownProtocol(GetAnalyzerName(), identifier, data, len);
return false; return false;
} }
else
return true;
}
DBG_LOG(DBG_PACKET_ANALYSIS, "Analysis in %s succeeded, next layer identifier is %#x.", DBG_LOG(DBG_PACKET_ANALYSIS, "Analysis in %s succeeded, next layer identifier is %#x.",
GetAnalyzerName(), identifier); GetAnalyzerName(), identifier);
@ -99,7 +105,9 @@ bool Analyzer::ForwardPacket(size_t len, const uint8_t* data, Packet* packet) co
DBG_LOG(DBG_PACKET_ANALYSIS, "Analysis in %s stopped, no default analyzer available.", DBG_LOG(DBG_PACKET_ANALYSIS, "Analysis in %s stopped, no default analyzer available.",
GetAnalyzerName()); GetAnalyzerName());
if ( report_unknown_protocols )
Weird("no_suitable_analyzer_found", packet); Weird("no_suitable_analyzer_found", packet);
return true; return true;
} }

View file

@ -17,8 +17,11 @@ public:
* *
* @param name The name for the type of analyzer. The name must match * @param name The name for the type of analyzer. The name must match
* the one the corresponding Component registers. * 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); explicit Analyzer(std::string name, bool report_unknown_protocols=true);
/** /**
* Constructor. * Constructor.
@ -165,6 +168,11 @@ private:
Dispatcher dispatcher; Dispatcher dispatcher;
AnalyzerPtr default_analyzer = nullptr; AnalyzerPtr default_analyzer = nullptr;
/**
* Flag for whether to report unknown protocols in ForwardPacket.
*/
bool report_unknown_protocols = true;
void Init(const Tag& tag); void Init(const Tag& tag);
}; };

View file

@ -101,7 +101,7 @@ void Manager::ProcessPacket(Packet* packet)
bool dumped_packet = false; bool dumped_packet = false;
if ( packet->dump_packet || zeek::detail::record_all_packets ) if ( packet->dump_packet || zeek::detail::record_all_packets )
{ {
DumpPacket(packet); DumpPacket(packet, packet->dump_size);
dumped_packet = true; dumped_packet = true;
} }
@ -114,7 +114,7 @@ void Manager::ProcessPacket(Packet* packet)
// Check whether packet should be recorded based on session analysis // Check whether packet should be recorded based on session analysis
if ( packet->dump_packet && ! dumped_packet ) if ( packet->dump_packet && ! dumped_packet )
DumpPacket(packet); DumpPacket(packet, packet->dump_size);
} }
bool Manager::ProcessInnerPacket(Packet* packet) bool Manager::ProcessInnerPacket(Packet* packet)

View file

@ -15,6 +15,9 @@ add_subdirectory(linux_sll)
add_subdirectory(arp) add_subdirectory(arp)
add_subdirectory(ip) add_subdirectory(ip)
add_subdirectory(udp)
add_subdirectory(tcp)
add_subdirectory(icmp)
add_subdirectory(gre) add_subdirectory(gre)
add_subdirectory(iptunnel) add_subdirectory(iptunnel)
add_subdirectory(vntag) add_subdirectory(vntag)

View file

@ -1,55 +1,89 @@
// See the file "COPYING" in the main distribution directory for copyright. // See the file "COPYING" in the main distribution directory for copyright.
#include "zeek/zeek-config.h" #include "zeek/packet_analysis/protocol/icmp/ICMP.h"
#include "zeek/analyzer/protocol/icmp/ICMP.h"
#include <netinet/icmp6.h> #include <netinet/icmp6.h>
#include <algorithm>
#include "zeek/IP.h"
#include "zeek/RunState.h" #include "zeek/RunState.h"
#include "zeek/NetVar.h"
#include "zeek/Event.h"
#include "zeek/Conn.h" #include "zeek/Conn.h"
#include "zeek/Desc.h"
#include "zeek/Reporter.h" #include "zeek/Reporter.h"
#include "zeek/Desc.h"
#include "zeek/Val.h"
#include "zeek/analyzer/Manager.h"
#include "zeek/session/Manager.h"
#include "zeek/analyzer/protocol/conn-size/ConnSize.h"
#include "zeek/analyzer/protocol/icmp/events.bif.h" #include "zeek/ZeekString.h"
namespace zeek::analyzer::icmp { #include "zeek/packet_analysis/protocol/icmp/events.bif.h"
ICMP_Analyzer::ICMP_Analyzer(Connection* c) enum ICMP_EndpointState {
: TransportLayerAnalyzer("ICMP", c), ICMP_INACTIVE, // no packet seen
icmp_conn_val(), type(), code(), request_len(-1), reply_len(-1) ICMP_ACTIVE, // packets seen
};
using namespace zeek::packet_analysis::ICMP;
using namespace zeek::packet_analysis::IP;
ICMPAnalyzer::ICMPAnalyzer() : IPBasedAnalyzer("ICMP", TRANSPORT_ICMP, ICMP_PORT_MASK, false)
{ {
c->SetInactivityTimeout(zeek::detail::icmp_inactivity_timeout); // TODO: remove once the other plugins are done
new_plugin = true;
} }
void ICMP_Analyzer::Done() ICMPAnalyzer::~ICMPAnalyzer()
{ {
TransportLayerAnalyzer::Done();
icmp_conn_val = nullptr;
matcher_state.FinishEndpointMatcher();
} }
void ICMP_Analyzer::DeliverPacket(int len, const u_char* data, SessionAdapter* ICMPAnalyzer::MakeSessionAdapter(Connection* conn)
bool is_orig, uint64_t seq, const IP_Hdr* ip, int caplen)
{ {
assert(ip); auto* root = new ICMPSessionAdapter(conn);
root->SetParent(this);
conn->SetInactivityTimeout(zeek::detail::icmp_inactivity_timeout);
TransportLayerAnalyzer::DeliverPacket(len, data, is_orig, seq, ip, caplen); return root;
}
// We need the min() here because Ethernet frame padding can lead to bool ICMPAnalyzer::BuildConnTuple(size_t len, const uint8_t* data, Packet* packet,
// caplen > len. ConnTuple& tuple)
if ( packet_contents ) {
// Subtract off the common part of ICMP header. if ( ! CheckHeaderTrunc(ICMP_MINLEN, len, packet) )
PacketContents(data + 8, std::min(len, caplen) - 8); return false;
tuple.src_addr = packet->ip_hdr->SrcAddr();
tuple.dst_addr = packet->ip_hdr->DstAddr();
tuple.proto = TRANSPORT_ICMP;
const struct icmp* icmpp = (const struct icmp *) data; const struct icmp* icmpp = (const struct icmp *) data;
tuple.src_port = htons(icmpp->icmp_type);
if ( packet->proto == IPPROTO_ICMP )
tuple.dst_port = htons(ICMP4_counterpart(icmpp->icmp_type, icmpp->icmp_code, tuple.is_one_way));
else if ( packet->proto == IPPROTO_ICMPV6 )
tuple.dst_port = htons(ICMP6_counterpart(icmpp->icmp_type, icmpp->icmp_code, tuple.is_one_way));
else
reporter->InternalError("Reached ICMP packet analyzer with unknown packet protocol %x",
packet->proto);
return true;
}
void ICMPAnalyzer::DeliverPacket(Connection* c, double t, bool is_orig, int remaining, Packet* pkt)
{
auto* adapter = static_cast<ICMPSessionAdapter*>(c->GetSessionAdapter());
const u_char* data = pkt->ip_hdr->Payload();
int len = pkt->ip_hdr->PayloadLen();
if ( packet_contents && len > 0 )
adapter->PacketContents(data + 8, std::min(len, remaining) - 8);
const struct icmp* icmpp = (const struct icmp*) data;
const std::unique_ptr<IP_Hdr>& ip = pkt->ip_hdr;
if ( ! zeek::detail::ignore_checksums && if ( ! zeek::detail::ignore_checksums &&
! zeek::id::find_val<TableVal>("ignore_checksums_nets")->Contains(ip->IPHeaderSrcAddr()) && ! zeek::id::find_val<TableVal>("ignore_checksums_nets")->Contains(ip->IPHeaderSrcAddr()) &&
caplen >= len ) remaining >= len )
{ {
int chksum = 0; int chksum = 0;
@ -60,94 +94,81 @@ void ICMP_Analyzer::DeliverPacket(int len, const u_char* data,
break; break;
case IPPROTO_ICMPV6: case IPPROTO_ICMPV6:
chksum = icmp6_checksum(icmpp, ip, len); chksum = icmp6_checksum(icmpp, ip.get(), len);
break; break;
default: default:
reporter->AnalyzerError( reporter->Error("unexpected IP proto in ICMP analyzer: %d", ip->NextProto());
this, "unexpected IP proto in ICMP analyzer: %d", ip->NextProto());
return; return;
} }
if ( chksum != 0xffff ) if ( chksum != 0xffff )
{ {
Weird("bad_ICMP_checksum"); adapter->Weird("bad_ICMP_checksum");
return; return;
} }
} }
Conn()->SetLastTime(run_state::current_timestamp); c->SetLastTime(run_state::current_timestamp);
adapter->InitEndpointMatcher(ip.get(), len, is_orig);
if ( zeek::detail::rule_matcher )
{
if ( ! matcher_state.MatcherInitialized(is_orig) )
matcher_state.InitEndpointMatcher(this, ip, len, is_orig, nullptr);
}
type = icmpp->icmp_type;
code = icmpp->icmp_code;
// Move past common portion of ICMP header. // Move past common portion of ICMP header.
data += 8; data += 8;
caplen -= 8; remaining -= 8;
len -= 8; len -= 8;
int& len_stat = is_orig ? request_len : reply_len; adapter->UpdateLength(is_orig, len);
if ( len_stat < 0 )
len_stat = len;
else
len_stat += len;
if ( ip->NextProto() == IPPROTO_ICMP ) if ( ip->NextProto() == IPPROTO_ICMP )
NextICMP4(run_state::current_timestamp, icmpp, len, caplen, data, ip); NextICMP4(run_state::current_timestamp, icmpp, len, remaining, data, ip.get(), adapter);
else if ( ip->NextProto() == IPPROTO_ICMPV6 ) else if ( ip->NextProto() == IPPROTO_ICMPV6 )
NextICMP6(run_state::current_timestamp, icmpp, len, caplen, data, ip); NextICMP6(run_state::current_timestamp, icmpp, len, remaining, data, ip.get(), adapter);
else else
{ {
reporter->AnalyzerError( reporter->Error("expected ICMP as IP packet's protocol, got %d", ip->NextProto());
this, "expected ICMP as IP packet's protocol, got %d", ip->NextProto());
return; return;
} }
ForwardPacket(len, data, pkt);
if ( caplen >= len ) if ( remaining >= len )
ForwardPacket(len, data, is_orig, seq, ip, caplen); adapter->ForwardPacket(len, data, is_orig, -1, ip.get(), remaining);
if ( zeek::detail::rule_matcher ) adapter->MatchEndpoint(data, len, is_orig);
matcher_state.Match(zeek::detail::Rule::PAYLOAD, data, len, is_orig,
false, false, true);
} }
void ICMP_Analyzer::NextICMP4(double t, const struct icmp* icmpp, int len, int caplen, void ICMPAnalyzer::NextICMP4(double t, const struct icmp* icmpp, int len, int caplen,
const u_char*& data, const IP_Hdr* ip_hdr ) const u_char*& data, const IP_Hdr* ip_hdr,
ICMPSessionAdapter* adapter)
{ {
switch ( icmpp->icmp_type ) switch ( icmpp->icmp_type )
{ {
case ICMP_ECHO: case ICMP_ECHO:
case ICMP_ECHOREPLY: case ICMP_ECHOREPLY:
Echo(t, icmpp, len, caplen, data, ip_hdr); Echo(t, icmpp, len, caplen, data, ip_hdr, adapter);
break; break;
case ICMP_UNREACH: case ICMP_UNREACH:
case ICMP_TIMXCEED: case ICMP_TIMXCEED:
Context4(t, icmpp, len, caplen, data, ip_hdr); Context4(t, icmpp, len, caplen, data, ip_hdr, adapter);
break; break;
default: default:
ICMP_Sent(icmpp, len, caplen, 0, data, ip_hdr); ICMP_Sent(icmpp, len, caplen, 0, data, ip_hdr, adapter);
break; break;
} }
} }
void ICMP_Analyzer::NextICMP6(double t, const struct icmp* icmpp, int len, int caplen, void ICMPAnalyzer::NextICMP6(double t, const struct icmp* icmpp, int len, int caplen,
const u_char*& data, const IP_Hdr* ip_hdr ) const u_char*& data, const IP_Hdr* ip_hdr,
ICMPSessionAdapter* adapter)
{ {
switch ( icmpp->icmp_type ) switch ( icmpp->icmp_type )
{ {
// Echo types. // Echo types.
case ICMP6_ECHO_REQUEST: case ICMP6_ECHO_REQUEST:
case ICMP6_ECHO_REPLY: case ICMP6_ECHO_REPLY:
Echo(t, icmpp, len, caplen, data, ip_hdr); Echo(t, icmpp, len, caplen, data, ip_hdr, adapter);
break; break;
// Error messages all have the same structure for their context, // Error messages all have the same structure for their context,
@ -156,27 +177,27 @@ void ICMP_Analyzer::NextICMP6(double t, const struct icmp* icmpp, int len, int c
case ICMP6_TIME_EXCEEDED: case ICMP6_TIME_EXCEEDED:
case ICMP6_PACKET_TOO_BIG: case ICMP6_PACKET_TOO_BIG:
case ICMP6_DST_UNREACH: case ICMP6_DST_UNREACH:
Context6(t, icmpp, len, caplen, data, ip_hdr); Context6(t, icmpp, len, caplen, data, ip_hdr, adapter);
break; break;
// Router related messages. // Router related messages.
case ND_REDIRECT: case ND_REDIRECT:
Redirect(t, icmpp, len, caplen, data, ip_hdr); Redirect(t, icmpp, len, caplen, data, ip_hdr, adapter);
break; break;
case ND_ROUTER_ADVERT: case ND_ROUTER_ADVERT:
RouterAdvert(t, icmpp, len, caplen, data, ip_hdr); RouterAdvert(t, icmpp, len, caplen, data, ip_hdr, adapter);
break; break;
case ND_NEIGHBOR_ADVERT: case ND_NEIGHBOR_ADVERT:
NeighborAdvert(t, icmpp, len, caplen, data, ip_hdr); NeighborAdvert(t, icmpp, len, caplen, data, ip_hdr, adapter);
break; break;
case ND_NEIGHBOR_SOLICIT: case ND_NEIGHBOR_SOLICIT:
NeighborSolicit(t, icmpp, len, caplen, data, ip_hdr); NeighborSolicit(t, icmpp, len, caplen, data, ip_hdr, adapter);
break; break;
case ND_ROUTER_SOLICIT: case ND_ROUTER_SOLICIT:
RouterSolicit(t, icmpp, len, caplen, data, ip_hdr); RouterSolicit(t, icmpp, len, caplen, data, ip_hdr, adapter);
break; break;
case ICMP6_ROUTER_RENUMBERING: case ICMP6_ROUTER_RENUMBERING:
ICMP_Sent(icmpp, len, caplen, 1, data, ip_hdr); ICMP_Sent(icmpp, len, caplen, 1, data, ip_hdr, adapter);
break; break;
#if 0 #if 0
@ -190,49 +211,45 @@ void ICMP_Analyzer::NextICMP6(double t, const struct icmp* icmpp, int len, int c
// the same structure for their context, and are // the same structure for their context, and are
// handled by the same function. // handled by the same function.
if ( icmpp->icmp_type < 128 ) if ( icmpp->icmp_type < 128 )
Context6(t, icmpp, len, caplen, data, ip_hdr); Context6(t, icmpp, len, caplen, data, ip_hdr, adapter);
else else
ICMP_Sent(icmpp, len, caplen, 1, data, ip_hdr); ICMP_Sent(icmpp, len, caplen, 1, data, ip_hdr, adapter);
break; break;
} }
} }
void ICMP_Analyzer::ICMP_Sent(const struct icmp* icmpp, int len, int caplen, void ICMPAnalyzer::ICMP_Sent(const struct icmp* icmpp, int len, int caplen,
int icmpv6, const u_char* data, int icmpv6, const u_char* data, const IP_Hdr* ip_hdr,
const IP_Hdr* ip_hdr) ICMPSessionAdapter* adapter)
{ {
if ( icmp_sent ) if ( icmp_sent )
EnqueueConnEvent(icmp_sent, adapter->EnqueueConnEvent(icmp_sent, adapter->ConnVal(),
ConnVal(), BuildInfo(icmpp, len, icmpv6, ip_hdr));
BuildInfo(icmpp, len, icmpv6, ip_hdr)
);
if ( icmp_sent_payload ) if ( icmp_sent_payload )
{ {
String* payload = new String(data, std::min(len, caplen), false); String* payload = new String(data, std::min(len, caplen), false);
EnqueueConnEvent(icmp_sent_payload, adapter->EnqueueConnEvent(icmp_sent_payload, adapter->ConnVal(),
ConnVal(),
BuildInfo(icmpp, len, icmpv6, ip_hdr), BuildInfo(icmpp, len, icmpv6, ip_hdr),
make_intrusive<StringVal>(payload) make_intrusive<StringVal>(payload));
);
} }
} }
RecordValPtr ICMP_Analyzer::BuildInfo(const struct icmp* icmpp, int len, zeek::RecordValPtr ICMPAnalyzer::BuildInfo(const struct icmp* icmpp, int len,
bool icmpv6, const IP_Hdr* ip_hdr) bool icmpv6, const IP_Hdr* ip_hdr)
{ {
static auto icmp_info = id::find_type<RecordType>("icmp_info"); static auto icmp_info = id::find_type<RecordType>("icmp_info");
auto rval = make_intrusive<RecordVal>(icmp_info); auto rval = make_intrusive<zeek::RecordVal>(icmp_info);
rval->Assign(0, static_cast<bool>(icmpv6)); rval->Assign(0, val_mgr->Bool(icmpv6));
rval->Assign(1, icmpp->icmp_type); rval->Assign(1, val_mgr->Count(icmpp->icmp_type));
rval->Assign(2, icmpp->icmp_code); rval->Assign(2, val_mgr->Count(icmpp->icmp_code));
rval->Assign(3, len); rval->Assign(3, val_mgr->Count(len));
rval->Assign(4, ip_hdr->TTL()); rval->Assign(4, val_mgr->Count(ip_hdr->TTL()));
return rval; return rval;
} }
TransportProto ICMP_Analyzer::GetContextProtocol(const IP_Hdr* ip_hdr, uint32_t* src_port, uint32_t* dst_port) TransportProto ICMPAnalyzer::GetContextProtocol(const IP_Hdr* ip_hdr, uint32_t* src_port, uint32_t* dst_port)
{ {
const u_char* transport_hdr; const u_char* transport_hdr;
uint32_t ip_hdr_len = ip_hdr->HdrLen(); uint32_t ip_hdr_len = ip_hdr->HdrLen();
@ -297,7 +314,7 @@ TransportProto ICMP_Analyzer::GetContextProtocol(const IP_Hdr* ip_hdr, uint32_t*
return proto; return proto;
} }
RecordValPtr ICMP_Analyzer::ExtractICMP4Context(int len, const u_char*& data) zeek::RecordValPtr ICMPAnalyzer::ExtractICMP4Context(int len, const u_char*& data)
{ {
const IP_Hdr ip_hdr_data((const struct ip*) data, false); const IP_Hdr ip_hdr_data((const struct ip*) data, false);
const IP_Hdr* ip_hdr = &ip_hdr_data; const IP_Hdr* ip_hdr = &ip_hdr_data;
@ -346,8 +363,8 @@ RecordValPtr ICMP_Analyzer::ExtractICMP4Context(int len, const u_char*& data)
} }
static auto icmp_context = id::find_type<RecordType>("icmp_context"); static auto icmp_context = id::find_type<RecordType>("icmp_context");
auto iprec = make_intrusive<RecordVal>(icmp_context); auto iprec = make_intrusive<zeek::RecordVal>(icmp_context);
auto id_val = make_intrusive<RecordVal>(id::conn_id); auto id_val = make_intrusive<zeek::RecordVal>(id::conn_id);
id_val->Assign(0, make_intrusive<AddrVal>(src_addr)); id_val->Assign(0, make_intrusive<AddrVal>(src_addr));
id_val->Assign(1, val_mgr->Port(src_port, proto)); id_val->Assign(1, val_mgr->Port(src_port, proto));
@ -355,18 +372,18 @@ RecordValPtr ICMP_Analyzer::ExtractICMP4Context(int len, const u_char*& data)
id_val->Assign(3, val_mgr->Port(dst_port, proto)); id_val->Assign(3, val_mgr->Port(dst_port, proto));
iprec->Assign(0, std::move(id_val)); iprec->Assign(0, std::move(id_val));
iprec->Assign(1, ip_len); iprec->Assign(1, val_mgr->Count(ip_len));
iprec->Assign(2, proto); iprec->Assign(2, val_mgr->Count(proto));
iprec->Assign(3, frag_offset); iprec->Assign(3, val_mgr->Count(frag_offset));
iprec->Assign(4, static_cast<bool>(bad_hdr_len)); iprec->Assign(4, val_mgr->Bool(bad_hdr_len));
iprec->Assign(5, static_cast<bool>(bad_checksum)); iprec->Assign(5, val_mgr->Bool(bad_checksum));
iprec->Assign(6, static_cast<bool>(MF)); iprec->Assign(6, val_mgr->Bool(MF));
iprec->Assign(7, static_cast<bool>(DF)); iprec->Assign(7, val_mgr->Bool(DF));
return iprec; return iprec;
} }
RecordValPtr ICMP_Analyzer::ExtractICMP6Context(int len, const u_char*& data) zeek::RecordValPtr ICMPAnalyzer::ExtractICMP6Context(int len, const u_char*& data)
{ {
int DF = 0, MF = 0, bad_hdr_len = 0; int DF = 0, MF = 0, bad_hdr_len = 0;
TransportProto proto = TRANSPORT_UNKNOWN; TransportProto proto = TRANSPORT_UNKNOWN;
@ -406,8 +423,8 @@ RecordValPtr ICMP_Analyzer::ExtractICMP6Context(int len, const u_char*& data)
} }
static auto icmp_context = id::find_type<RecordType>("icmp_context"); static auto icmp_context = id::find_type<RecordType>("icmp_context");
auto iprec = make_intrusive<RecordVal>(icmp_context); auto iprec = make_intrusive<zeek::RecordVal>(icmp_context);
auto id_val = make_intrusive<RecordVal>(id::conn_id); auto id_val = make_intrusive<zeek::RecordVal>(id::conn_id);
id_val->Assign(0, make_intrusive<AddrVal>(src_addr)); id_val->Assign(0, make_intrusive<AddrVal>(src_addr));
id_val->Assign(1, val_mgr->Port(src_port, proto)); id_val->Assign(1, val_mgr->Port(src_port, proto));
@ -415,84 +432,21 @@ RecordValPtr ICMP_Analyzer::ExtractICMP6Context(int len, const u_char*& data)
id_val->Assign(3, val_mgr->Port(dst_port, proto)); id_val->Assign(3, val_mgr->Port(dst_port, proto));
iprec->Assign(0, std::move(id_val)); iprec->Assign(0, std::move(id_val));
iprec->Assign(1, ip_len); iprec->Assign(1, val_mgr->Count(ip_len));
iprec->Assign(2, proto); iprec->Assign(2, val_mgr->Count(proto));
iprec->Assign(3, frag_offset); iprec->Assign(3, val_mgr->Count(frag_offset));
iprec->Assign(4, static_cast<bool>(bad_hdr_len)); iprec->Assign(4, val_mgr->Bool(bad_hdr_len));
// bad_checksum is always false since IPv6 layer doesn't have a checksum. // bad_checksum is always false since IPv6 layer doesn't have a checksum.
iprec->Assign(5, false); iprec->Assign(5, val_mgr->False());
iprec->Assign(6, static_cast<bool>(MF)); iprec->Assign(6, val_mgr->Bool(MF));
iprec->Assign(7, static_cast<bool>(DF)); iprec->Assign(7, val_mgr->Bool(DF));
return iprec; return iprec;
} }
bool ICMP_Analyzer::IsReuse(double /* t */, const u_char* /* pkt */) void ICMPAnalyzer::Echo(double t, const struct icmp* icmpp, int len,
{ int caplen, const u_char*& data, const IP_Hdr* ip_hdr,
return false; ICMPSessionAdapter* adapter)
}
void ICMP_Analyzer::Describe(ODesc* d) const
{
d->Add(Conn()->StartTime());
d->Add("(");
d->Add(Conn()->LastTime());
d->AddSP(")");
d->Add(Conn()->OrigAddr());
d->Add(".");
d->Add(type);
d->Add(".");
d->Add(code);
d->SP();
d->AddSP("->");
d->Add(Conn()->RespAddr());
}
void ICMP_Analyzer::UpdateConnVal(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);
// Call children's UpdateConnVal
Analyzer::UpdateConnVal(conn_val);
}
void ICMP_Analyzer::UpdateEndpointVal(const ValPtr& endp_arg, bool is_orig)
{
Conn()->EnableStatusUpdateTimer();
int size = is_orig ? request_len : reply_len;
auto endp = endp_arg->AsRecordVal();
if ( size < 0 )
{
endp->Assign(0, 0);
endp->Assign(1, ICMP_INACTIVE);
}
else
{
endp->Assign(0, size);
endp->Assign(1, ICMP_ACTIVE);
}
}
unsigned int ICMP_Analyzer::MemoryAllocation() const
{
return Analyzer::MemoryAllocation()
+ padded_sizeof(*this) - padded_sizeof(Connection)
+ (icmp_conn_val ? icmp_conn_val->MemoryAllocation() : 0);
}
void ICMP_Analyzer::Echo(double t, const struct icmp* icmpp, int len,
int caplen, const u_char*& data, const IP_Hdr* ip_hdr)
{ {
// For handling all Echo related ICMP messages // For handling all Echo related ICMP messages
EventHandlerPtr f = nullptr; EventHandlerPtr f = nullptr;
@ -512,8 +466,8 @@ void ICMP_Analyzer::Echo(double t, const struct icmp* icmpp, int len,
String* payload = new String(data, caplen, false); String* payload = new String(data, caplen, false);
EnqueueConnEvent(f, adapter->EnqueueConnEvent(f,
ConnVal(), adapter->ConnVal(),
BuildInfo(icmpp, len, ip_hdr->NextProto() != IPPROTO_ICMP, ip_hdr), BuildInfo(icmpp, len, ip_hdr->NextProto() != IPPROTO_ICMP, ip_hdr),
val_mgr->Count(iid), val_mgr->Count(iid),
val_mgr->Count(iseq), val_mgr->Count(iseq),
@ -522,8 +476,9 @@ void ICMP_Analyzer::Echo(double t, const struct icmp* icmpp, int len,
} }
void ICMP_Analyzer::RouterAdvert(double t, const struct icmp* icmpp, int len, void ICMPAnalyzer::RouterAdvert(double t, const struct icmp* icmpp, int len,
int caplen, const u_char*& data, const IP_Hdr* ip_hdr) int caplen, const u_char*& data, const IP_Hdr* ip_hdr,
ICMPSessionAdapter* adapter)
{ {
EventHandlerPtr f = icmp_router_advertisement; EventHandlerPtr f = icmp_router_advertisement;
@ -540,8 +495,8 @@ void ICMP_Analyzer::RouterAdvert(double t, const struct icmp* icmpp, int len,
int opt_offset = sizeof(reachable) + sizeof(retrans); int opt_offset = sizeof(reachable) + sizeof(retrans);
EnqueueConnEvent(f, adapter->EnqueueConnEvent(f,
ConnVal(), adapter->ConnVal(),
BuildInfo(icmpp, len, 1, ip_hdr), BuildInfo(icmpp, len, 1, ip_hdr),
val_mgr->Count(icmpp->icmp_num_addrs), // Cur Hop Limit val_mgr->Count(icmpp->icmp_num_addrs), // Cur Hop Limit
val_mgr->Bool(icmpp->icmp_wpa & 0x80), // Managed val_mgr->Bool(icmpp->icmp_wpa & 0x80), // Managed
@ -553,13 +508,14 @@ void ICMP_Analyzer::RouterAdvert(double t, const struct icmp* icmpp, int len,
make_intrusive<IntervalVal>((double)ntohs(icmpp->icmp_lifetime), Seconds), make_intrusive<IntervalVal>((double)ntohs(icmpp->icmp_lifetime), Seconds),
make_intrusive<IntervalVal>((double)ntohl(reachable), Milliseconds), make_intrusive<IntervalVal>((double)ntohl(reachable), Milliseconds),
make_intrusive<IntervalVal>((double)ntohl(retrans), Milliseconds), make_intrusive<IntervalVal>((double)ntohl(retrans), Milliseconds),
BuildNDOptionsVal(caplen - opt_offset, data + opt_offset) BuildNDOptionsVal(caplen - opt_offset, data + opt_offset, adapter)
); );
} }
void ICMP_Analyzer::NeighborAdvert(double t, const struct icmp* icmpp, int len, void ICMPAnalyzer::NeighborAdvert(double t, const struct icmp* icmpp, int len,
int caplen, const u_char*& data, const IP_Hdr* ip_hdr) int caplen, const u_char*& data, const IP_Hdr* ip_hdr,
ICMPSessionAdapter* adapter)
{ {
EventHandlerPtr f = icmp_neighbor_advertisement; EventHandlerPtr f = icmp_neighbor_advertisement;
@ -573,20 +529,21 @@ void ICMP_Analyzer::NeighborAdvert(double t, const struct icmp* icmpp, int len,
int opt_offset = sizeof(in6_addr); int opt_offset = sizeof(in6_addr);
EnqueueConnEvent(f, adapter->EnqueueConnEvent(f,
ConnVal(), adapter->ConnVal(),
BuildInfo(icmpp, len, 1, ip_hdr), BuildInfo(icmpp, len, 1, ip_hdr),
val_mgr->Bool(icmpp->icmp_num_addrs & 0x80), // Router val_mgr->Bool(icmpp->icmp_num_addrs & 0x80), // Router
val_mgr->Bool(icmpp->icmp_num_addrs & 0x40), // Solicited val_mgr->Bool(icmpp->icmp_num_addrs & 0x40), // Solicited
val_mgr->Bool(icmpp->icmp_num_addrs & 0x20), // Override val_mgr->Bool(icmpp->icmp_num_addrs & 0x20), // Override
make_intrusive<AddrVal>(tgtaddr), make_intrusive<AddrVal>(tgtaddr),
BuildNDOptionsVal(caplen - opt_offset, data + opt_offset) BuildNDOptionsVal(caplen - opt_offset, data + opt_offset, adapter)
); );
} }
void ICMP_Analyzer::NeighborSolicit(double t, const struct icmp* icmpp, int len, void ICMPAnalyzer::NeighborSolicit(double t, const struct icmp* icmpp, int len,
int caplen, const u_char*& data, const IP_Hdr* ip_hdr) int caplen, const u_char*& data, const IP_Hdr* ip_hdr,
ICMPSessionAdapter* adapter)
{ {
EventHandlerPtr f = icmp_neighbor_solicitation; EventHandlerPtr f = icmp_neighbor_solicitation;
@ -600,17 +557,18 @@ void ICMP_Analyzer::NeighborSolicit(double t, const struct icmp* icmpp, int len,
int opt_offset = sizeof(in6_addr); int opt_offset = sizeof(in6_addr);
EnqueueConnEvent(f, adapter->EnqueueConnEvent(f,
ConnVal(), adapter->ConnVal(),
BuildInfo(icmpp, len, 1, ip_hdr), BuildInfo(icmpp, len, 1, ip_hdr),
make_intrusive<AddrVal>(tgtaddr), make_intrusive<AddrVal>(tgtaddr),
BuildNDOptionsVal(caplen - opt_offset, data + opt_offset) BuildNDOptionsVal(caplen - opt_offset, data + opt_offset, adapter)
); );
} }
void ICMP_Analyzer::Redirect(double t, const struct icmp* icmpp, int len, void ICMPAnalyzer::Redirect(double t, const struct icmp* icmpp, int len,
int caplen, const u_char*& data, const IP_Hdr* ip_hdr) int caplen, const u_char*& data, const IP_Hdr* ip_hdr,
ICMPSessionAdapter* adapter)
{ {
EventHandlerPtr f = icmp_redirect; EventHandlerPtr f = icmp_redirect;
@ -627,34 +585,36 @@ void ICMP_Analyzer::Redirect(double t, const struct icmp* icmpp, int len,
int opt_offset = 2 * sizeof(in6_addr); int opt_offset = 2 * sizeof(in6_addr);
EnqueueConnEvent(f, adapter->EnqueueConnEvent(f,
ConnVal(), adapter->ConnVal(),
BuildInfo(icmpp, len, 1, ip_hdr), BuildInfo(icmpp, len, 1, ip_hdr),
make_intrusive<AddrVal>(tgtaddr), make_intrusive<AddrVal>(tgtaddr),
make_intrusive<AddrVal>(dstaddr), make_intrusive<AddrVal>(dstaddr),
BuildNDOptionsVal(caplen - opt_offset, data + opt_offset) BuildNDOptionsVal(caplen - opt_offset, data + opt_offset, adapter)
); );
} }
void ICMP_Analyzer::RouterSolicit(double t, const struct icmp* icmpp, int len, void ICMPAnalyzer::RouterSolicit(double t, const struct icmp* icmpp, int len,
int caplen, const u_char*& data, const IP_Hdr* ip_hdr) int caplen, const u_char*& data, const IP_Hdr* ip_hdr,
ICMPSessionAdapter* adapter)
{ {
EventHandlerPtr f = icmp_router_solicitation; EventHandlerPtr f = icmp_router_solicitation;
if ( ! f ) if ( ! f )
return; return;
EnqueueConnEvent(f, adapter->EnqueueConnEvent(f,
ConnVal(), adapter->ConnVal(),
BuildInfo(icmpp, len, 1, ip_hdr), BuildInfo(icmpp, len, 1, ip_hdr),
BuildNDOptionsVal(caplen, data) BuildNDOptionsVal(caplen, data, adapter)
); );
} }
void ICMP_Analyzer::Context4(double t, const struct icmp* icmpp, void ICMPAnalyzer::Context4(double t, const struct icmp* icmpp, int len,
int len, int caplen, const u_char*& data, const IP_Hdr* ip_hdr) int caplen, const u_char*& data, const IP_Hdr* ip_hdr,
ICMPSessionAdapter* adapter)
{ {
EventHandlerPtr f = nullptr; EventHandlerPtr f = nullptr;
@ -670,8 +630,8 @@ void ICMP_Analyzer::Context4(double t, const struct icmp* icmpp,
} }
if ( f ) if ( f )
EnqueueConnEvent(f, adapter->EnqueueConnEvent(f,
ConnVal(), adapter->ConnVal(),
BuildInfo(icmpp, len, 0, ip_hdr), BuildInfo(icmpp, len, 0, ip_hdr),
val_mgr->Count(icmpp->icmp_code), val_mgr->Count(icmpp->icmp_code),
ExtractICMP4Context(caplen, data) ExtractICMP4Context(caplen, data)
@ -679,8 +639,9 @@ void ICMP_Analyzer::Context4(double t, const struct icmp* icmpp,
} }
void ICMP_Analyzer::Context6(double t, const struct icmp* icmpp, void ICMPAnalyzer::Context6(double t, const struct icmp* icmpp, int len,
int len, int caplen, const u_char*& data, const IP_Hdr* ip_hdr) int caplen, const u_char*& data, const IP_Hdr* ip_hdr,
ICMPSessionAdapter* adapter)
{ {
EventHandlerPtr f = nullptr; EventHandlerPtr f = nullptr;
@ -708,20 +669,21 @@ void ICMP_Analyzer::Context6(double t, const struct icmp* icmpp,
} }
if ( f ) if ( f )
EnqueueConnEvent(f, adapter->EnqueueConnEvent(f,
ConnVal(), adapter->ConnVal(),
BuildInfo(icmpp, len, 1, ip_hdr), BuildInfo(icmpp, len, 1, ip_hdr),
val_mgr->Count(icmpp->icmp_code), val_mgr->Count(icmpp->icmp_code),
ExtractICMP6Context(caplen, data) ExtractICMP6Context(caplen, data)
); );
} }
VectorValPtr ICMP_Analyzer::BuildNDOptionsVal(int caplen, const u_char* data) zeek::VectorValPtr ICMPAnalyzer::BuildNDOptionsVal(int caplen, const u_char* data,
ICMPSessionAdapter* adapter)
{ {
static auto icmp6_nd_option_type = id::find_type<RecordType>("icmp6_nd_option"); static auto icmp6_nd_option_type = id::find_type<RecordType>("icmp6_nd_option");
static auto icmp6_nd_prefix_info_type = id::find_type<RecordType>("icmp6_nd_prefix_info"); static auto icmp6_nd_prefix_info_type = id::find_type<RecordType>("icmp6_nd_prefix_info");
auto vv = make_intrusive<VectorVal>( auto vv = make_intrusive<zeek::VectorVal>(
id::find_type<VectorType>("icmp6_nd_options")); id::find_type<VectorType>("icmp6_nd_options"));
while ( caplen > 0 ) while ( caplen > 0 )
@ -729,7 +691,7 @@ VectorValPtr ICMP_Analyzer::BuildNDOptionsVal(int caplen, const u_char* data)
// Must have at least type & length to continue parsing options. // Must have at least type & length to continue parsing options.
if ( caplen < 2 ) if ( caplen < 2 )
{ {
Weird("truncated_ICMPv6_ND_options"); adapter->Weird("truncated_ICMPv6_ND_options");
break; break;
} }
@ -738,13 +700,13 @@ VectorValPtr ICMP_Analyzer::BuildNDOptionsVal(int caplen, const u_char* data)
if ( length == 0 ) if ( length == 0 )
{ {
Weird("zero_length_ICMPv6_ND_option"); adapter->Weird("zero_length_ICMPv6_ND_option");
break; break;
} }
auto rv = make_intrusive<RecordVal>(icmp6_nd_option_type); auto rv = make_intrusive<zeek::RecordVal>(icmp6_nd_option_type);
rv->Assign(0, type); rv->Assign(0, val_mgr->Count(type));
rv->Assign(1, length); rv->Assign(1, val_mgr->Count(length));
// Adjust length to be in units of bytes, exclude type/length fields. // Adjust length to be in units of bytes, exclude type/length fields.
length = length * 8 - 2; length = length * 8 - 2;
@ -763,7 +725,7 @@ VectorValPtr ICMP_Analyzer::BuildNDOptionsVal(int caplen, const u_char* data)
if ( caplen >= length ) if ( caplen >= length )
{ {
String* link_addr = new String(data, length, false); String* link_addr = new String(data, length, false);
rv->Assign(2, link_addr); rv->Assign(2, make_intrusive<StringVal>(link_addr));
} }
else else
set_payload_field = true; set_payload_field = true;
@ -776,18 +738,18 @@ VectorValPtr ICMP_Analyzer::BuildNDOptionsVal(int caplen, const u_char* data)
{ {
if ( caplen >= 30 ) if ( caplen >= 30 )
{ {
auto info = make_intrusive<RecordVal>(icmp6_nd_prefix_info_type); auto info = make_intrusive<zeek::RecordVal>(icmp6_nd_prefix_info_type);
uint8_t prefix_len = *((const uint8_t*)(data)); uint8_t prefix_len = *((const uint8_t*)(data));
bool L_flag = (*((const uint8_t*)(data + 1)) & 0x80) != 0; bool L_flag = (*((const uint8_t*)(data + 1)) & 0x80) != 0;
bool A_flag = (*((const uint8_t*)(data + 1)) & 0x40) != 0; bool A_flag = (*((const uint8_t*)(data + 1)) & 0x40) != 0;
uint32_t valid_life = *((const uint32_t*)(data + 2)); uint32_t valid_life = *((const uint32_t*)(data + 2));
uint32_t prefer_life = *((const uint32_t*)(data + 6)); uint32_t prefer_life = *((const uint32_t*)(data + 6));
in6_addr prefix = *((const in6_addr*)(data + 14)); in6_addr prefix = *((const in6_addr*)(data + 14));
info->Assign(0, prefix_len); info->Assign(0, val_mgr->Count(prefix_len));
info->Assign(1, L_flag); info->Assign(1, val_mgr->Bool(L_flag));
info->Assign(2, A_flag); info->Assign(2, val_mgr->Bool(A_flag));
info->AssignInterval(3, double(ntohl(valid_life))); info->Assign(3, make_intrusive<IntervalVal>((double)ntohl(valid_life), Seconds));
info->AssignInterval(4, double(ntohl(prefer_life))); info->Assign(4, make_intrusive<IntervalVal>((double)ntohl(prefer_life), Seconds));
info->Assign(5, make_intrusive<AddrVal>(IPAddr(prefix))); info->Assign(5, make_intrusive<AddrVal>(IPAddr(prefix)));
rv->Assign(3, std::move(info)); rv->Assign(3, std::move(info));
} }
@ -816,7 +778,7 @@ VectorValPtr ICMP_Analyzer::BuildNDOptionsVal(int caplen, const u_char* data)
// MTU option // MTU option
{ {
if ( caplen >= 6 ) if ( caplen >= 6 )
rv->Assign(5, ntohl(*((const uint32_t*)(data + 2)))); rv->Assign(5, val_mgr->Count(ntohl(*((const uint32_t*)(data + 2)))));
else else
set_payload_field = true; set_payload_field = true;
@ -833,7 +795,7 @@ VectorValPtr ICMP_Analyzer::BuildNDOptionsVal(int caplen, const u_char* data)
if ( set_payload_field ) if ( set_payload_field )
{ {
String* payload = new String(data, std::min((int)length, caplen), false); String* payload = new String(data, std::min((int)length, caplen), false);
rv->Assign(6, payload); rv->Assign(6, make_intrusive<StringVal>(payload));
} }
data += length; data += length;
@ -845,7 +807,7 @@ VectorValPtr ICMP_Analyzer::BuildNDOptionsVal(int caplen, const u_char* data)
return vv; return vv;
} }
int ICMP4_counterpart(int icmp_type, int icmp_code, bool& is_one_way) int ICMPAnalyzer::ICMP4_counterpart(int icmp_type, int icmp_code, bool& is_one_way)
{ {
is_one_way = false; is_one_way = false;
@ -873,7 +835,7 @@ int ICMP4_counterpart(int icmp_type, int icmp_code, bool& is_one_way)
} }
} }
int ICMP6_counterpart(int icmp_type, int icmp_code, bool& is_one_way) int ICMPAnalyzer::ICMP6_counterpart(int icmp_type, int icmp_code, bool& is_one_way)
{ {
is_one_way = false; is_one_way = false;
@ -905,4 +867,72 @@ int ICMP6_counterpart(int icmp_type, int icmp_code, bool& is_one_way)
} }
} }
} // namespace zeek::analyzer::icmp void ICMPSessionAdapter::AddExtraAnalyzers(Connection* conn)
{
static analyzer::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));
}
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);
analyzer::Analyzer::UpdateConnVal(conn_val);
}
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();
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::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::Done()
{
SessionAdapter::Done();
matcher_state.FinishEndpointMatcher();
}

View file

@ -0,0 +1,138 @@
// See the file "COPYING" in the main distribution directory for copyright.
#pragma once
#include "zeek/packet_analysis/Analyzer.h"
#include "zeek/packet_analysis/Component.h"
#include "zeek/packet_analysis/protocol/ip/IPBasedAnalyzer.h"
#include "zeek/analyzer/Analyzer.h"
#include "zeek/RuleMatcher.h"
namespace zeek {
class VectorVal;
using VectorValPtr = IntrusivePtr<VectorVal>;
class RecordVal;
using RecordValPtr = IntrusivePtr<RecordVal>;
namespace packet_analysis::ICMP {
class ICMPSessionAdapter;
class ICMPAnalyzer final : public IP::IPBasedAnalyzer {
public:
ICMPAnalyzer();
~ICMPAnalyzer() override;
static zeek::packet_analysis::AnalyzerPtr Instantiate()
{
return std::make_shared<ICMPAnalyzer>();
}
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;
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 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 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 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);
TransportProto GetContextProtocol(const IP_Hdr* ip_hdr, uint32_t* src_port,
uint32_t* dst_port);
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);
// RFC 4861 Neighbor Discover message options
VectorValPtr BuildNDOptionsVal(int caplen, const u_char* data,
ICMPSessionAdapter* adapter);
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).
int ICMP4_counterpart(int icmp_type, int icmp_code, bool& is_one_way);
int ICMP6_counterpart(int icmp_type, int icmp_code, bool& is_one_way);
};
class ICMPSessionAdapter final : public IP::SessionAdapter {
public:
ICMPSessionAdapter(Connection* conn) :
IP::SessionAdapter("ICMP", conn) { }
static zeek::analyzer::Analyzer* Instantiate(Connection* conn)
{
return new ICMPSessionAdapter(conn);
}
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 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;
};
} // namespace packet_analysis::ICMP
} // namespace zeek

View file

@ -0,0 +1,26 @@
// See the file "COPYING" in the main distribution directory for copyright.
#include "zeek/plugin/Plugin.h"
#include "zeek/packet_analysis/Component.h"
#include "zeek/packet_analysis/protocol/icmp/ICMP.h"
namespace zeek::plugin::Zeek_ICMP {
class Plugin : public zeek::plugin::Plugin {
public:
zeek::plugin::Configuration Configure()
{
AddComponent(new zeek::packet_analysis::Component("ICMP",
zeek::packet_analysis::ICMP::ICMPAnalyzer::Instantiate));
AddComponent(new zeek::analyzer::Component("ICMP",
zeek::packet_analysis::ICMP::ICMPSessionAdapter::Instantiate));
zeek::plugin::Configuration config;
config.name = "Zeek::ICMP";
config.description = "Packet analyzer for ICMP";
return config;
}
} plugin;
}

View file

@ -4,5 +4,5 @@ include(ZeekPlugin)
include_directories(BEFORE ${CMAKE_CURRENT_SOURCE_DIR} ${CMAKE_CURRENT_BINARY_DIR}) include_directories(BEFORE ${CMAKE_CURRENT_SOURCE_DIR} ${CMAKE_CURRENT_BINARY_DIR})
zeek_plugin_begin(PacketAnalyzer IP) zeek_plugin_begin(PacketAnalyzer IP)
zeek_plugin_cc(IP.cc Plugin.cc) zeek_plugin_cc(IP.cc IPBasedAnalyzer.cc SessionAdapter.cc Plugin.cc)
zeek_plugin_end() zeek_plugin_end()

View file

@ -10,6 +10,7 @@
#include "zeek/Frag.h" #include "zeek/Frag.h"
#include "zeek/Event.h" #include "zeek/Event.h"
#include "zeek/TunnelEncapsulation.h" #include "zeek/TunnelEncapsulation.h"
#include "zeek/IPAddr.h"
using namespace zeek::packet_analysis::IP; using namespace zeek::packet_analysis::IP;
@ -235,14 +236,6 @@ bool IPAnalyzer::AnalyzePacket(size_t len, const uint8_t* data, Packet* packet)
packet->proto = proto; packet->proto = proto;
switch ( proto ) { switch ( proto ) {
case IPPROTO_TCP:
case IPPROTO_UDP:
case IPPROTO_ICMP:
case IPPROTO_ICMPV6:
DBG_LOG(DBG_PACKET_ANALYSIS, "Analysis in %s succeeded, next layer identifier is %#x.",
GetAnalyzerName(), proto);
session_mgr->ProcessTransportLayer(run_state::processing_start_time, packet, len);
break;
case IPPROTO_NONE: case IPPROTO_NONE:
// If the packet is encapsulated in Teredo, then it was a bubble and // 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 // the Teredo analyzer may have raised an event for that, else we're
@ -268,3 +261,40 @@ bool IPAnalyzer::AnalyzePacket(size_t len, const uint8_t* data, Packet* packet)
return return_val; return return_val;
} }
int zeek::packet_analysis::IP::ParsePacket(int caplen, const u_char* const pkt, int proto,
std::unique_ptr<zeek::IP_Hdr>& inner)
{
if ( proto == IPPROTO_IPV6 )
{
if ( caplen < (int)sizeof(struct ip6_hdr) )
return -1;
const struct ip6_hdr* ip6 = (const struct ip6_hdr*) pkt;
inner = std::make_unique<zeek::IP_Hdr>(ip6, false, caplen);
if ( ( ip6->ip6_ctlun.ip6_un2_vfc & 0xF0 ) != 0x60 )
return -2;
}
else if ( proto == IPPROTO_IPV4 )
{
if ( caplen < (int)sizeof(struct ip) )
return -1;
const struct ip* ip4 = (const struct ip*) pkt;
inner = std::make_unique<zeek::IP_Hdr>(ip4, false);
if ( ip4->ip_v != 4 )
return -2;
}
else
{
zeek::reporter->InternalWarning("Bad IP protocol version in IP::ParsePacket");
return -1;
}
if ( (uint32_t)caplen != inner->TotalLen() )
return (uint32_t)caplen < inner->TotalLen() ? -1 : 1;
return 0;
}

View file

@ -32,4 +32,28 @@ private:
zeek::detail::Discarder* discarder = nullptr; zeek::detail::Discarder* discarder = nullptr;
}; };
/**
* Returns a wrapper IP_Hdr object if \a pkt appears to be a valid IPv4
* or IPv6 header based on whether it's long enough to contain such a header,
* if version given in the header matches the proto argument, and also checks
* that the payload length field of that header matches the actual
* length of \a pkt given by \a caplen.
*
* @param caplen The length of \a pkt in bytes.
* @param pkt The inner IP packet data.
* @param proto Either IPPROTO_IPV6 or IPPROTO_IPV4 to indicate which IP
* protocol \a pkt corresponds to.
* @param inner The inner IP packet wrapper pointer to be allocated/assigned
* if \a pkt looks like a valid IP packet or at least long enough
* to hold an IP header.
* @return 0 If the inner IP packet appeared valid, else -1 if \a caplen
* is greater than the supposed IP packet's payload length field, -2
* if the version of the inner header does not match proto or
* 1 if \a caplen is less than the supposed packet's payload length.
* In the -1 case, \a inner may still be non-null if \a caplen was
* long enough to be an IP header, and \a inner is always non-null
* for other return values.
*/
int ParsePacket(int caplen, const u_char* const pkt, int proto,
std::unique_ptr<IP_Hdr>& inner);
} }

View file

@ -0,0 +1,273 @@
// See the file "COPYING" in the main distribution directory for copyright.
#include "zeek/packet_analysis/protocol/ip/IPBasedAnalyzer.h"
#include "zeek/RunState.h"
#include "zeek/Conn.h"
#include "zeek/Val.h"
#include "zeek/session/Manager.h"
#include "zeek/analyzer/Manager.h"
#include "zeek/analyzer/protocol/pia/PIA.h"
#include "zeek/plugin/Manager.h"
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()
{
}
bool IPBasedAnalyzer::AnalyzePacket(size_t len, const uint8_t* data, Packet* pkt)
{
ConnTuple tuple;
if ( ! BuildConnTuple(len, data, pkt, tuple) )
return false;
const std::unique_ptr<IP_Hdr>& ip_hdr = pkt->ip_hdr;
detail::ConnKey key(tuple);
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);
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;
bool is_orig = (tuple.src_addr == conn->OrigAddr()) &&
(tuple.src_port == conn->OrigPort());
conn->CheckFlowLabel(is_orig, ip_hdr->FlowLabel());
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 ( new_packet )
conn->EnqueueEvent(new_packet, nullptr, conn->GetVal(),
pkt_hdr_val ? std::move(pkt_hdr_val) : ip_hdr->ToPktHdrVal());
if ( new_plugin )
{
conn->SetRecordPackets(true);
conn->SetRecordContents(true);
const u_char* data = pkt->ip_hdr->Payload();
run_state::current_timestamp = run_state::processing_start_time;
run_state::current_pkt = pkt;
// TODO: Does this actually mean anything?
if ( conn->Skipping() )
return true;
DeliverPacket(conn, run_state::processing_start_time, is_orig, len, pkt);
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 we don't want the content, set the dump size to include just
// the header.
if ( ! conn->RecordContents() )
pkt->dump_size = data - pkt->data;
}
}
else
{
int record_packet = 1; // whether to record the packet at all
int record_content = 1; // whether to record its data
const u_char* data = pkt->ip_hdr->Payload();
conn->NextPacket(run_state::processing_start_time, is_orig, ip_hdr.get(), ip_hdr->PayloadLen(),
len, data, record_packet, record_content, pkt);
// If the packet is reassembled, disable packet dumping because the
// pointer math to dump the data wouldn't work.
if ( ip_hdr->reassembled )
pkt->dump_packet = false;
else if ( record_packet )
{
pkt->dump_packet = true;
// If we don't want the content, set the dump size to include just
// the header.
if ( ! record_content )
pkt->dump_size = data - pkt->data;
}
}
return true;
}
bool IPBasedAnalyzer::CheckHeaderTrunc(size_t min_hdr_len, size_t remaining, Packet* packet)
{
if ( 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;
}
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<bro_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;
}
// We exploit our knowledge of PortVal's internal storage mechanism here.
port |= server_port_mask;
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;
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);
if ( flip )
conn->FlipRoles();
if ( ! new_plugin )
{
if ( ! analyzer_mgr->BuildInitialAnalyzerTree(conn) )
{
conn->Done();
Unref(conn);
return nullptr;
}
}
else if ( ! BuildSessionAnalyzerTree(conn) )
{
conn->Done();
Unref(conn);
return nullptr;
}
if ( new_connection )
conn->Event(new_connection, nullptr);
return conn;
}
bool IPBasedAnalyzer::BuildSessionAnalyzerTree(Connection* conn)
{
SessionAdapter* root = MakeSessionAdapter(conn);
analyzer::pia::PIA* pia = MakePIA(conn);
// TODO: temporary, can be replaced when the port lookup stuff is moved from analyzer_mgr
bool check_port = conn->ConnTransport() != TRANSPORT_ICMP;
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 ( check_port && ! zeek::detail::dpd_ignore_ports )
{
// TODO: ideally this lookup would be local to the packet analyzer instead of
// calling out to the analyzer manager. This code can move once the TCP work
// is in progress so that it doesn't have to be done piecemeal.
//
int resp_port = ntohs(conn->RespPort());
std::set<analyzer::Tag>* ports = analyzer_mgr->LookupPort(conn->ConnTransport(), resp_port, false);
if ( ports )
{
for ( const auto& port : *ports )
{
analyzer::Analyzer* analyzer = analyzer_mgr->InstantiateAnalyzer(port, conn);
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->AddExtraAnalyzers(conn);
if ( pia )
root->AddChildAnalyzer(pia->AsAnalyzer());
conn->SetSessionAdapter(root, pia);
root->Init();
root->InitChildren();
PLUGIN_HOOK_VOID(HOOK_SETUP_ANALYZER_TREE, HookSetupAnalyzerTree(conn));
// TODO: temporary
return true;
}

View file

@ -0,0 +1,149 @@
// See the file "COPYING" in the main distribution directory for copyright.
#pragma once
#include "zeek/packet_analysis/Analyzer.h"
#include "zeek/packet_analysis/Component.h"
#include "zeek/packet_analysis/protocol/ip/SessionAdapter.h"
#include "zeek/analyzer/Analyzer.h"
#include "zeek/analyzer/Manager.h"
namespace zeek::analyzer::pia { class PIA; }
namespace zeek::packet_analysis::IP {
/**
* A base class for reuse by packet analyzers based on IP. This is used by default
* 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 {
public:
~IPBasedAnalyzer() 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; }
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);
/**
* 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) {}
/**
* 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 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);
/**
* 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;
// TODO: temporary, until all of the plugins are implemented
bool new_plugin = false;
private:
/**
* 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);
bool BuildSessionAnalyzerTree(Connection* conn);
TransportProto transport;
uint32_t server_port_mask;
};
}

View file

@ -0,0 +1,39 @@
#include "zeek/packet_analysis/protocol/ip/SessionAdapter.h"
#include "zeek/File.h"
#include "zeek/ZeekString.h"
#include "zeek/packet_analysis/protocol/ip/IPBasedAnalyzer.h"
using namespace zeek::packet_analysis::IP;
void SessionAdapter::Done()
{
Analyzer::Done();
}
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");
}
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));
}
}

View file

@ -0,0 +1,102 @@
#pragma once
#include "zeek/analyzer/Analyzer.h"
namespace zeek::analyzer::pia { class PIA; }
namespace zeek::packet_analysis::IP {
class IPBasedAnalyzer;
/**
* This class represents the interface between the packet analysis framework and
* 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 {
public:
SessionAdapter(const char* name, Connection* conn)
: analyzer::Analyzer(name, conn) { }
/**
* 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; }
/**
* 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 analzyers 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
* overide 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 overide 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; }
/**
* 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 dass to pass to the event.
*
* @param len The length of \a data.
*/
void PacketContents(const u_char* data, int len);
protected:
IPBasedAnalyzer* parent;
analyzer::pia::PIA* pia;
};
} // namespace zeek::packet_analysis::IP

View file

@ -4,10 +4,10 @@
#include <pcap.h> // For DLT_ constants #include <pcap.h> // For DLT_ constants
#include "zeek/session/Manager.h"
#include "zeek/RunState.h" #include "zeek/RunState.h"
#include "zeek/IP.h" #include "zeek/IP.h"
#include "zeek/TunnelEncapsulation.h" #include "zeek/TunnelEncapsulation.h"
#include "zeek/packet_analysis/protocol/ip/IP.h"
namespace zeek::packet_analysis::IPTunnel { namespace zeek::packet_analysis::IPTunnel {
@ -45,12 +45,12 @@ bool IPTunnelAnalyzer::AnalyzePacket(size_t len, const uint8_t* data, Packet* pa
BifEnum::Tunnel::Type tunnel_type = packet->tunnel_type; BifEnum::Tunnel::Type tunnel_type = packet->tunnel_type;
int gre_link_type = packet->gre_link_type; int gre_link_type = packet->gre_link_type;
IP_Hdr* inner = nullptr; std::unique_ptr<IP_Hdr> inner = nullptr;
if ( gre_version != 0 ) if ( gre_version != 0 )
{ {
// Check for a valid inner packet first. // Check for a valid inner packet first.
int result = session_mgr->ParseIPPacket(len, data, proto, inner); int result = packet_analysis::IP::ParsePacket(len, data, proto, inner);
if ( result == -2 ) if ( result == -2 )
Weird("invalid_inner_IP_version", packet); Weird("invalid_inner_IP_version", packet);
else if ( result < 0 ) else if ( result < 0 )
@ -59,11 +59,8 @@ bool IPTunnelAnalyzer::AnalyzePacket(size_t len, const uint8_t* data, Packet* pa
Weird("inner_IP_payload_length_mismatch", packet); Weird("inner_IP_payload_length_mismatch", packet);
if ( result != 0 ) if ( result != 0 )
{
delete inner;
return false; return false;
} }
}
// Look up to see if we've already seen this IP tunnel, identified // 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 // by the pair of IP addresses, so that we can always associate the
@ -100,7 +97,7 @@ bool IPTunnelAnalyzer::AnalyzePacket(size_t len, const uint8_t* data, Packet* pa
* Handles a packet that contains an IP header directly after the tunnel header. * Handles a packet that contains an IP header directly after the tunnel header.
*/ */
bool IPTunnelAnalyzer::ProcessEncapsulatedPacket(double t, const Packet* pkt, bool IPTunnelAnalyzer::ProcessEncapsulatedPacket(double t, const Packet* pkt,
const IP_Hdr* inner, const std::unique_ptr<IP_Hdr>& inner,
std::shared_ptr<EncapsulationStack> prev, std::shared_ptr<EncapsulationStack> prev,
const EncapsulatingConn& ec) const EncapsulatingConn& ec)
{ {
@ -138,8 +135,6 @@ bool IPTunnelAnalyzer::ProcessEncapsulatedPacket(double t, const Packet* pkt,
// Forward the packet back to the IP analyzer. // Forward the packet back to the IP analyzer.
bool return_val = ForwardPacket(len, data, &p); bool return_val = ForwardPacket(len, data, &p);
delete inner;
return return_val; return return_val;
} }

View file

@ -40,7 +40,7 @@ public:
* @param ec The most-recently found depth of encapsulation. * @param ec The most-recently found depth of encapsulation.
*/ */
bool ProcessEncapsulatedPacket(double t, const Packet *pkt, bool ProcessEncapsulatedPacket(double t, const Packet *pkt,
const IP_Hdr* inner, const std::unique_ptr<IP_Hdr>& inner,
std::shared_ptr<EncapsulationStack> prev, std::shared_ptr<EncapsulationStack> prev,
const EncapsulatingConn& ec); const EncapsulatingConn& ec);

View file

@ -0,0 +1,8 @@
include(ZeekPlugin)
include_directories(BEFORE ${CMAKE_CURRENT_SOURCE_DIR} ${CMAKE_CURRENT_BINARY_DIR})
zeek_plugin_begin(PacketAnalyzer TCP_PKT)
zeek_plugin_cc(TCP.cc Plugin.cc)
zeek_plugin_end()

View file

@ -0,0 +1,24 @@
// See the file "COPYING" in the main distribution directory for copyright.
#include "zeek/plugin/Plugin.h"
#include "zeek/packet_analysis/Component.h"
#include "zeek/packet_analysis/protocol/tcp/TCP.h"
namespace zeek::plugin::Zeek_TCP {
class Plugin : public zeek::plugin::Plugin {
public:
zeek::plugin::Configuration Configure()
{
AddComponent(new zeek::packet_analysis::Component("TCP",
zeek::packet_analysis::TCP::TCPAnalyzer::Instantiate));
zeek::plugin::Configuration config;
config.name = "Zeek::TCP_PKT";
config.description = "Packet analyzer for TCP";
return config;
}
} plugin;
}

View file

@ -0,0 +1,76 @@
// See the file "COPYING" in the main distribution directory for copyright.
#include "zeek/packet_analysis/protocol/tcp/TCP.h"
#include "zeek/RunState.h"
using namespace zeek::packet_analysis::TCP;
using namespace zeek::packet_analysis::IP;
TCPAnalyzer::TCPAnalyzer() : IPBasedAnalyzer("TCP", TRANSPORT_TCP, TCP_PORT_MASK, false)
{
}
TCPAnalyzer::~TCPAnalyzer()
{
}
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();
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;
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;
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;
// 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;
}

View file

@ -0,0 +1,54 @@
// See the file "COPYING" in the main distribution directory for copyright.
#pragma once
#include "zeek/packet_analysis/Analyzer.h"
#include "zeek/packet_analysis/Component.h"
#include "zeek/packet_analysis/protocol/ip/IPBasedAnalyzer.h"
namespace zeek::packet_analysis::TCP {
class TCPAnalyzer final : public IP::IPBasedAnalyzer {
public:
TCPAnalyzer();
~TCPAnalyzer() override;
static zeek::packet_analysis::AnalyzerPtr Instantiate()
{
return std::make_shared<TCPAnalyzer>();
}
/**
* Returns an 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.
*
* TODO: this is a stub until the TCP analyzer moves to the packet analysis framework.
*/
IP::SessionAdapter* MakeSessionAdapter(Connection* conn) override { return nullptr; }
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;
/**
* 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;
};
}

View file

@ -0,0 +1,26 @@
// See the file "COPYING" in the main distribution directory for copyright.
#include "zeek/plugin/Plugin.h"
#include "zeek/packet_analysis/Component.h"
#include "zeek/packet_analysis/protocol/udp/UDP.h"
namespace zeek::plugin::Zeek_UDP {
class Plugin : public zeek::plugin::Plugin {
public:
zeek::plugin::Configuration Configure()
{
AddComponent(new zeek::packet_analysis::Component("UDP",
zeek::packet_analysis::UDP::UDPAnalyzer::Instantiate));
AddComponent(new zeek::analyzer::Component("UDP",
zeek::packet_analysis::UDP::UDPSessionAdapter::Instantiate));
zeek::plugin::Configuration config;
config.name = "Zeek::UDP";
config.description = "Packet analyzer for UDP";
return config;
}
} plugin;
}

View file

@ -0,0 +1,338 @@
// See the file "COPYING" in the main distribution directory for copyright.
#include "zeek/packet_analysis/protocol/udp/UDP.h"
#include "zeek/RunState.h"
#include "zeek/Conn.h"
#include "zeek/session/Manager.h"
#include "zeek/analyzer/Manager.h"
#include "zeek/analyzer/protocol/pia/PIA.h"
#include "zeek/analyzer/protocol/conn-size/ConnSize.h"
#include "zeek/packet_analysis/protocol/udp/events.bif.h"
using namespace zeek::packet_analysis::UDP;
using namespace zeek::packet_analysis::IP;
constexpr uint32_t HIST_ORIG_DATA_PKT = 0x1;
constexpr uint32_t HIST_RESP_DATA_PKT = 0x2;
constexpr uint32_t HIST_ORIG_CORRUPT_PKT = 0x4;
constexpr uint32_t HIST_RESP_CORRUPT_PKT = 0x8;
enum UDP_EndpointState {
UDP_INACTIVE, // no packet seen
UDP_ACTIVE, // packets seen
};
UDPAnalyzer::UDPAnalyzer() : IPBasedAnalyzer("UDP", TRANSPORT_UDP, UDP_PORT_MASK, false)
{
// TODO: remove once the other plugins are done
new_plugin = true;
}
UDPAnalyzer::~UDPAnalyzer()
{
}
SessionAdapter* UDPAnalyzer::MakeSessionAdapter(Connection* conn)
{
auto* root = new UDPSessionAdapter(conn);
root->SetParent(this);
conn->EnableStatusUpdateTimer();
conn->SetInactivityTimeout(zeek::detail::udp_inactivity_timeout);
return root;
}
zeek::analyzer::pia::PIA* UDPAnalyzer::MakePIA(Connection* conn)
{
return new analyzer::pia::PIA_UDP(conn);
}
void UDPAnalyzer::Initialize()
{
IPBasedAnalyzer::Initialize();
const auto& id = detail::global_scope()->Find("Tunnel::vxlan_ports");
if ( ! (id && id->GetVal()) )
reporter->FatalError("Tunnel::vxlan_ports not defined");
auto table_val = id->GetVal()->AsTableVal();
auto port_list = table_val->ToPureListVal();
for ( auto i = 0; i < port_list->Length(); ++i )
vxlan_ports.emplace_back(port_list->Idx(i)->AsPortVal()->Port());
}
bool UDPAnalyzer::WantConnection(uint16_t src_port, uint16_t dst_port,
const u_char* data, bool& flip_roles) const
{
flip_roles = IsLikelyServerPort(src_port) && ! IsLikelyServerPort(dst_port);
return true;
}
bool UDPAnalyzer::BuildConnTuple(size_t len, const uint8_t* data, Packet* packet,
ConnTuple& tuple)
{
uint32_t min_hdr_len = sizeof(struct udphdr);
if ( ! CheckHeaderTrunc(min_hdr_len, len, packet) )
return false;
tuple.src_addr = packet->ip_hdr->SrcAddr();
tuple.dst_addr = packet->ip_hdr->DstAddr();
const struct udphdr* up = (const struct udphdr *) packet->ip_hdr->Payload();
tuple.src_port = up->uh_sport;
tuple.dst_port = up->uh_dport;
tuple.is_one_way = false;
tuple.proto = TRANSPORT_UDP;
return true;
}
void UDPAnalyzer::DeliverPacket(Connection* c, double t, bool is_orig, int remaining, Packet* pkt)
{
auto* adapter = static_cast<UDPSessionAdapter*>(c->GetSessionAdapter());
const u_char* data = pkt->ip_hdr->Payload();
int len = pkt->ip_hdr->PayloadLen();
const struct udphdr* up = (const struct udphdr*) data;
const std::unique_ptr<IP_Hdr>& ip = pkt->ip_hdr;
adapter->DeliverPacket(len, data, is_orig, -1, ip.get(), remaining);
// Increment data before checksum check so that data will
// point to UDP payload even if checksum fails. Particularly,
// it allows event packet_contents to get to the data.
data += sizeof(struct udphdr);
// We need the min() here because Ethernet frame padding can lead to
// remaining > len.
if ( packet_contents )
adapter->PacketContents(data, std::min(len, remaining) - sizeof(struct udphdr));
int chksum = up->uh_sum;
auto validate_checksum =
! run_state::current_pkt->l3_checksummed &&
! zeek::detail::ignore_checksums &&
! zeek::id::find_val<TableVal>("ignore_checksums_nets")->Contains(ip->IPHeaderSrcAddr()) &&
remaining >=len;
constexpr auto vxlan_len = 8;
constexpr auto eth_len = 14;
if ( validate_checksum &&
len > ((int)sizeof(struct udphdr) + vxlan_len + eth_len) &&
(data[0] & 0x08) == 0x08 )
{
if ( std::find(vxlan_ports.begin(), vxlan_ports.end(),
ntohs(up->uh_dport)) != vxlan_ports.end() )
{
// Looks like VXLAN on a well-known port, so the checksum should be
// transmitted as zero, and we should accept that. If not
// transmitted as zero, then validating the checksum is optional.
if ( chksum == 0 )
validate_checksum = false;
else
validate_checksum = BifConst::Tunnel::validate_vxlan_checksums;
}
}
if ( validate_checksum )
{
bool bad = false;
if ( ip->IP4_Hdr() )
{
if ( chksum && ! ValidateChecksum(ip.get(), up, len) )
bad = true;
}
/* checksum is not optional for IPv6 */
else if ( ! ValidateChecksum(ip.get(), up, len) )
bad = true;
if ( bad )
{
adapter->HandleBadChecksum(is_orig);
return;
}
}
int ulen = ntohs(up->uh_ulen);
if ( ulen != len )
adapter->Weird("UDP_datagram_length_mismatch", util::fmt("%d != %d", ulen, len));
len -= sizeof(struct udphdr);
ulen -= sizeof(struct udphdr);
remaining -= sizeof(struct udphdr);
c->SetLastTime(run_state::current_timestamp);
if ( udp_contents )
{
static auto udp_content_ports = id::find_val<TableVal>("udp_content_ports");
static auto udp_content_delivery_ports_orig = id::find_val<TableVal>("udp_content_delivery_ports_orig");
static auto udp_content_delivery_ports_resp = id::find_val<TableVal>("udp_content_delivery_ports_resp");
bool do_udp_contents = false;
const auto& sport_val = val_mgr->Port(ntohs(up->uh_sport), TRANSPORT_UDP);
const auto& dport_val = val_mgr->Port(ntohs(up->uh_dport), TRANSPORT_UDP);
if ( udp_content_ports->FindOrDefault(dport_val) ||
udp_content_ports->FindOrDefault(sport_val) )
do_udp_contents = true;
else
{
uint16_t p = zeek::detail::udp_content_delivery_ports_use_resp ? c->RespPort()
: up->uh_dport;
const auto& port_val = zeek::val_mgr->Port(ntohs(p), TRANSPORT_UDP);
if ( is_orig )
{
auto result = udp_content_delivery_ports_orig->FindOrDefault(port_val);
if ( zeek::detail::udp_content_deliver_all_orig || (result && result->AsBool()) )
do_udp_contents = true;
}
else
{
auto result = udp_content_delivery_ports_resp->FindOrDefault(port_val);
if ( zeek::detail::udp_content_deliver_all_resp || (result && result->AsBool()) )
do_udp_contents = true;
}
}
if ( do_udp_contents )
adapter->EnqueueConnEvent(udp_contents,
adapter->ConnVal(),
val_mgr->Bool(is_orig),
make_intrusive<StringVal>(len, (const char*) data));
}
if ( is_orig )
{
c->CheckHistory(HIST_ORIG_DATA_PKT, 'D');
adapter->UpdateLength(is_orig, ulen);
adapter->Event(udp_request);
}
else
{
c->CheckHistory(HIST_RESP_DATA_PKT, 'd');
adapter->UpdateLength(is_orig, ulen);
adapter->Event(udp_reply);
}
// Send the packet back into the packet analysis framework.
ForwardPacket(len, data, pkt);
// Also try sending it into session analysis.
if ( remaining >= len )
adapter->ForwardPacket(len, data, is_orig, -1, ip.get(), remaining);
}
bool UDPAnalyzer::ValidateChecksum(const IP_Hdr* ip, const udphdr* up, int len)
{
auto sum = detail::ip_in_cksum(ip->IP4_Hdr(), ip->SrcAddr(), ip->DstAddr(),
IPPROTO_UDP,
reinterpret_cast<const uint8_t*>(up), len);
return sum == 0xffff;
}
void UDPSessionAdapter::AddExtraAnalyzers(Connection* conn)
{
static analyzer::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));
}
void UDPSessionAdapter::UpdateConnVal(RecordVal* conn_val)
{
auto orig_endp = conn_val->GetField("orig");
auto resp_endp = conn_val->GetField("resp");
UpdateEndpointVal(orig_endp, true);
UpdateEndpointVal(resp_endp, false);
// Call children's UpdateConnVal
Analyzer::UpdateConnVal(conn_val);
}
void UDPSessionAdapter::UpdateEndpointVal(const ValPtr& endp_arg, bool is_orig)
{
bro_int_t 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, UDP_INACTIVE);
}
else
{
endp->Assign(0, static_cast<uint64_t>(size));
endp->Assign(1, UDP_ACTIVE);
}
}
void UDPSessionAdapter::UpdateLength(bool is_orig, int len)
{
if ( is_orig )
{
if ( request_len < 0 )
request_len = len;
else
{
request_len += len;
#ifdef DEBUG
if ( request_len < 0 )
reporter->Warning("wrapping around for UDP request length");
#endif
}
}
else
{
if ( reply_len < 0 )
reply_len = len;
else
{
reply_len += len;
#ifdef DEBUG
if ( reply_len < 0 )
reporter->Warning("wrapping around for UDP reply length");
#endif
}
}
}
void UDPSessionAdapter::HandleBadChecksum(bool is_orig)
{
Weird("bad_UDP_checksum");
if ( is_orig )
{
uint32_t t = req_chk_thresh;
if ( Conn()->ScaledHistoryEntry('C', req_chk_cnt, req_chk_thresh) )
ChecksumEvent(is_orig, t);
}
else
{
uint32_t t = rep_chk_thresh;
if ( Conn()->ScaledHistoryEntry('c', rep_chk_cnt, rep_chk_thresh) )
ChecksumEvent(is_orig, t);
}
}
void UDPSessionAdapter::ChecksumEvent(bool is_orig, uint32_t threshold)
{
Conn()->HistoryThresholdEvent(udp_multiple_checksum_errors, is_orig, threshold);
}

View file

@ -0,0 +1,100 @@
// See the file "COPYING" in the main distribution directory for copyright.
#pragma once
#include "zeek/packet_analysis/Analyzer.h"
#include "zeek/packet_analysis/Component.h"
#include "zeek/packet_analysis/protocol/ip/IPBasedAnalyzer.h"
namespace zeek::packet_analysis::UDP {
class UDPAnalyzer final : public IP::IPBasedAnalyzer {
public:
UDPAnalyzer();
~UDPAnalyzer() override;
static zeek::packet_analysis::AnalyzerPtr Instantiate()
{
return std::make_shared<UDPAnalyzer>();
}
/**
* 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;
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;
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;
packet_analysis::IP::SessionAdapter* MakeSessionAdapter(Connection* conn) override;
analyzer::pia::PIA* MakePIA(Connection* conn) override;
private:
// Returns true if the checksum is valid, false if not
static bool ValidateChecksum(const IP_Hdr* ip, const struct udphdr* up,
int len);
std::vector<uint16_t> vxlan_ports;
};
class UDPSessionAdapter final : public IP::SessionAdapter {
public:
UDPSessionAdapter(Connection* conn) :
IP::SessionAdapter("UDP", conn) { }
static zeek::analyzer::Analyzer* Instantiate(Connection* conn)
{
return new UDPSessionAdapter(conn);
}
void AddExtraAnalyzers(Connection* conn) override;
void UpdateConnVal(RecordVal* conn_val) override;
void UpdateLength(bool is_orig, int len);
void HandleBadChecksum(bool is_orig);
// For tracking checksum history. These are connection-specific so they
// need to be stored in the session adapter created for each connection.
uint32_t req_chk_cnt = 0;
uint32_t req_chk_thresh = 1;
uint32_t rep_chk_cnt = 0;
uint32_t rep_chk_thresh = 1;
private:
void UpdateEndpointVal(const ValPtr& endp_arg, bool is_orig);
void ChecksumEvent(bool is_orig, uint32_t threshold);
bro_int_t request_len = -1;
bro_int_t reply_len = -1;
};
}

View file

@ -4,7 +4,8 @@
namespace zeek::session::detail { namespace zeek::session::detail {
Key::Key(const void* session, size_t size, bool copy) : size(size) Key::Key(const void* session, size_t size, size_t type, bool copy) :
size(size), type(type)
{ {
data = reinterpret_cast<const uint8_t*>(session); data = reinterpret_cast<const uint8_t*>(session);
@ -63,6 +64,8 @@ bool Key::operator<(const Key& rhs) const
{ {
if ( size != rhs.size ) if ( size != rhs.size )
return size < rhs.size; return size < rhs.size;
else if ( type != rhs.type )
return type < rhs.type;
return memcmp(data, rhs.data, size) < 0; return memcmp(data, rhs.data, size) < 0;
} }

View file

@ -20,16 +20,22 @@ namespace zeek::session::detail {
class Key final { class Key final {
public: public:
const static size_t CONNECTION_KEY_TYPE=0;
/** /**
* Create a new session key from a data pointer. * Create a new session key from a data pointer.
* *
* @param session A pointer to the data for the key. * @param session A pointer to the data for the key.
* @param size The size of the key data, in bytes. * @param size The size of the key data, in bytes.
* @param type An identifier for the type of this key. The value used should be
* unique across all types of session keys. CONNECTION_KEY_TYPE (0) is used by
* Connection sessions and is reserved. This value is used to avoid collisions
* when doing comparisons of the memory stored by keys.
* @param copy Flag for whether the data should be copied into the Key * @param copy Flag for whether the data should be copied into the Key
* during construction. This defaults to false because normally the only time * during construction. This defaults to false because normally the only time
* data is copied into the key is when it's inserted into the session map. * data is copied into the key is when it's inserted into the session map.
*/ */
Key(const void* key_data, size_t size, bool copy=false); Key(const void* key_data, size_t size, size_t type, bool copy=false);
~Key(); ~Key();
@ -55,6 +61,7 @@ public:
private: private:
const uint8_t* data = nullptr; const uint8_t* data = nullptr;
size_t size = 0; size_t size = 0;
size_t type = CONNECTION_KEY_TYPE;
bool copied = false; bool copied = false;
}; };

View file

@ -21,9 +21,6 @@
#include "zeek/session/Session.h" #include "zeek/session/Session.h"
#include "zeek/TunnelEncapsulation.h" #include "zeek/TunnelEncapsulation.h"
#include "zeek/telemetry/Manager.h" #include "zeek/telemetry/Manager.h"
#include "zeek/analyzer/protocol/icmp/ICMP.h"
#include "zeek/analyzer/protocol/udp/UDP.h"
#include "zeek/analyzer/Manager.h" #include "zeek/analyzer/Manager.h"
#include "zeek/iosource/IOSource.h" #include "zeek/iosource/IOSource.h"
@ -107,234 +104,6 @@ void Manager::Done()
{ {
} }
void Manager::ProcessTransportLayer(double t, const Packet* pkt, size_t remaining)
{
const std::unique_ptr<IP_Hdr>& ip_hdr = pkt->ip_hdr;
uint32_t len = ip_hdr->TotalLen();
uint16_t ip_hdr_len = ip_hdr->HdrLen();
if ( len < ip_hdr_len )
{
session_mgr->Weird("bogus_IP_header_lengths", pkt);
return;
}
len -= ip_hdr_len; // remove IP header
int proto = ip_hdr->NextProto();
if ( CheckHeaderTrunc(proto, len, remaining, pkt) )
return;
const u_char* data = ip_hdr->Payload();
ConnTuple id;
id.src_addr = ip_hdr->SrcAddr();
id.dst_addr = ip_hdr->DstAddr();
BifEnum::Tunnel::Type tunnel_type = BifEnum::Tunnel::IP;
switch ( proto ) {
case IPPROTO_TCP:
{
const struct tcphdr* tp = (const struct tcphdr *) data;
id.src_port = tp->th_sport;
id.dst_port = tp->th_dport;
id.is_one_way = false;
id.proto = TRANSPORT_TCP;
break;
}
case IPPROTO_UDP:
{
const struct udphdr* up = (const struct udphdr *) data;
id.src_port = up->uh_sport;
id.dst_port = up->uh_dport;
id.is_one_way = false;
id.proto = TRANSPORT_UDP;
break;
}
case IPPROTO_ICMP:
{
const struct icmp* icmpp = (const struct icmp *) data;
id.src_port = icmpp->icmp_type;
id.dst_port = analyzer::icmp::ICMP4_counterpart(icmpp->icmp_type,
icmpp->icmp_code,
id.is_one_way);
id.src_port = htons(id.src_port);
id.dst_port = htons(id.dst_port);
id.proto = TRANSPORT_ICMP;
break;
}
case IPPROTO_ICMPV6:
{
const struct icmp* icmpp = (const struct icmp *) data;
id.src_port = icmpp->icmp_type;
id.dst_port = analyzer::icmp::ICMP6_counterpart(icmpp->icmp_type,
icmpp->icmp_code,
id.is_one_way);
id.src_port = htons(id.src_port);
id.dst_port = htons(id.dst_port);
id.proto = TRANSPORT_ICMP;
break;
}
default:
Weird("unknown_protocol", pkt, util::fmt("%d", proto));
return;
}
zeek::detail::ConnKey conn_key(id);
detail::Key key(&conn_key, sizeof(conn_key), false);
Connection* conn = nullptr;
// FIXME: The following is getting pretty complex. Need to split up
// into separate functions.
auto it = session_map.find(key);
if (it != session_map.end() )
conn = static_cast<Connection*>(it->second);
if ( ! conn )
{
conn = NewConn(conn_key, t, &id, data, proto, ip_hdr->FlowLabel(), pkt);
if ( conn )
InsertSession(std::move(key), conn);
}
else
{
// We already know that connection.
if ( conn->IsReuse(t, data) )
{
conn->Event(connection_reused, nullptr);
Remove(conn);
conn = NewConn(conn_key, t, &id, data, proto, ip_hdr->FlowLabel(), pkt);
if ( conn )
InsertSession(std::move(key), conn);
}
else
{
conn->CheckEncapsulation(pkt->encap);
}
}
if ( ! conn )
return;
int record_packet = 1; // whether to record the packet at all
int record_content = 1; // whether to record its data
bool is_orig = (id.src_addr == conn->OrigAddr()) &&
(id.src_port == conn->OrigPort());
conn->CheckFlowLabel(is_orig, ip_hdr->FlowLabel());
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 ( new_packet )
conn->EnqueueEvent(new_packet, nullptr, conn->GetVal(), pkt_hdr_val ?
std::move(pkt_hdr_val) : ip_hdr->ToPktHdrVal());
conn->NextPacket(t, is_orig, ip_hdr.get(), len, remaining, data,
record_packet, record_content, pkt);
// We skip this block for reassembled packets because the pointer
// math wouldn't work.
if ( ! ip_hdr->reassembled && record_packet )
{
if ( record_content )
pkt->dump_packet = true; // save the whole thing
else
{
int hdr_len = data - pkt->data;
packet_mgr->DumpPacket(pkt, hdr_len); // just save the header
}
}
}
int Manager::ParseIPPacket(int caplen, const u_char* const pkt, int proto,
IP_Hdr*& inner)
{
if ( proto == IPPROTO_IPV6 )
{
if ( caplen < (int)sizeof(struct ip6_hdr) )
return -1;
const struct ip6_hdr* ip6 = (const struct ip6_hdr*) pkt;
inner = new IP_Hdr(ip6, false, caplen);
if ( ( ip6->ip6_ctlun.ip6_un2_vfc & 0xF0 ) != 0x60 )
return -2;
}
else if ( proto == IPPROTO_IPV4 )
{
if ( caplen < (int)sizeof(struct ip) )
return -1;
const struct ip* ip4 = (const struct ip*) pkt;
inner = new IP_Hdr(ip4, false);
if ( ip4->ip_v != 4 )
return -2;
}
else
{
reporter->InternalWarning("Bad IP protocol version in ParseIPPacket");
return -1;
}
if ( (uint32_t)caplen != inner->TotalLen() )
return (uint32_t)caplen < inner->TotalLen() ? -1 : 1;
return 0;
}
bool Manager::CheckHeaderTrunc(int proto, uint32_t len, uint32_t caplen,
const Packet* p)
{
uint32_t min_hdr_len = 0;
switch ( proto ) {
case IPPROTO_TCP:
min_hdr_len = sizeof(struct tcphdr);
break;
case IPPROTO_UDP:
min_hdr_len = sizeof(struct udphdr);
break;
case IPPROTO_ICMP:
case IPPROTO_ICMPV6:
default:
// Use for all other packets.
min_hdr_len = ICMP_MINLEN;
break;
}
if ( len < min_hdr_len )
{
Weird("truncated_header", p);
return true;
}
if ( caplen < min_hdr_len )
{
Weird("internally_truncated_header", p);
return true;
}
return false;
}
Connection* Manager::FindConnection(Val* v) Connection* Manager::FindConnection(Val* v)
{ {
const auto& vt = v->GetType(); const auto& vt = v->GetType();
@ -380,14 +149,19 @@ Connection* Manager::FindConnection(Val* v)
htons((unsigned short) resp_portv->Port()), htons((unsigned short) resp_portv->Port()),
orig_portv->PortType(), false); orig_portv->PortType(), false);
detail::Key key(&conn_key, sizeof(conn_key), false); return FindConnection(conn_key);
}
Connection* Manager::FindConnection(const zeek::detail::ConnKey& conn_key)
{
detail::Key key(&conn_key, sizeof(conn_key),
detail::Key::CONNECTION_KEY_TYPE, false);
Connection* conn = nullptr;
auto it = session_map.find(key); auto it = session_map.find(key);
if ( it != session_map.end() ) if ( it != session_map.end() )
conn = static_cast<Connection*>(it->second); return static_cast<Connection*>(it->second);
return conn; return nullptr;
} }
void Manager::Remove(Session* s) void Manager::Remove(Session* s)
@ -418,16 +192,20 @@ void Manager::Remove(Session* s)
} }
} }
void Manager::Insert(Session* s) void Manager::Insert(Session* s, bool remove_existing)
{ {
Session* old = nullptr; Session* old = nullptr;
detail::Key key = s->SessionKey(true); detail::Key key = s->SessionKey(true);
if ( remove_existing )
{
auto it = session_map.find(key); auto it = session_map.find(key);
if ( it != session_map.end() ) if ( it != session_map.end() )
old = it->second; old = it->second;
session_map.erase(key); session_map.erase(key);
}
InsertSession(std::move(key), s); InsertSession(std::move(key), s);
if ( old && old != s ) if ( old && old != s )
@ -482,140 +260,6 @@ void Manager::GetStats(Stats& s)
s.num_packets = packet_mgr->PacketsProcessed(); s.num_packets = packet_mgr->PacketsProcessed();
} }
Connection* Manager::NewConn(const zeek::detail::ConnKey& k, double t, const ConnTuple* id,
const u_char* data, int proto, uint32_t flow_label,
const Packet* pkt)
{
// FIXME: This should be cleaned up a bit, it's too protocol-specific.
// But I'm not yet sure what the right abstraction for these things is.
int src_h = ntohs(id->src_port);
int dst_h = ntohs(id->dst_port);
int flags = 0;
// Hmm... This is not great.
TransportProto tproto = TRANSPORT_UNKNOWN;
switch ( proto ) {
case IPPROTO_ICMP:
tproto = TRANSPORT_ICMP;
break;
case IPPROTO_TCP:
tproto = TRANSPORT_TCP;
break;
case IPPROTO_UDP:
tproto = TRANSPORT_UDP;
break;
case IPPROTO_ICMPV6:
tproto = TRANSPORT_ICMP;
break;
default:
reporter->InternalWarning("unknown transport protocol");
return nullptr;
};
if ( tproto == TRANSPORT_TCP )
{
const struct tcphdr* tp = (const struct tcphdr*) data;
flags = tp->th_flags;
}
bool flip = false;
if ( ! WantConnection(src_h, dst_h, tproto, flags, flip) )
return nullptr;
Connection* conn = new Connection(k, t, id, flow_label, pkt);
conn->SetTransport(tproto);
if ( flip )
conn->FlipRoles();
if ( ! analyzer_mgr->BuildInitialAnalyzerTree(conn) )
{
conn->Done();
Unref(conn);
return nullptr;
}
if ( new_connection )
conn->Event(new_connection, nullptr);
return conn;
}
bool Manager::IsLikelyServerPort(uint32_t port, TransportProto proto) const
{
// We keep a cached in-core version of the table to speed up the lookup.
static std::set<bro_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;
}
// We exploit our knowledge of PortVal's internal storage mechanism
// here.
if ( proto == TRANSPORT_TCP )
port |= TCP_PORT_MASK;
else if ( proto == TRANSPORT_UDP )
port |= UDP_PORT_MASK;
else if ( proto == TRANSPORT_ICMP )
port |= ICMP_PORT_MASK;
return port_cache.find(port) != port_cache.end();
}
bool Manager::WantConnection(uint16_t src_port, uint16_t dst_port,
TransportProto transport_proto,
uint8_t tcp_flags, bool& flip_roles)
{
flip_roles = false;
if ( transport_proto == TRANSPORT_TCP )
{
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;
// 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, TRANSPORT_TCP) )
{ // connection is a candidate for flipping
if ( IsLikelyServerPort(dst_port, TRANSPORT_TCP) )
// 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;
}
}
}
else if ( transport_proto == TRANSPORT_UDP )
flip_roles =
IsLikelyServerPort(src_port, TRANSPORT_UDP) &&
! IsLikelyServerPort(dst_port, TRANSPORT_UDP);
return true;
}
void Manager::Weird(const char* name, const Packet* pkt, const char* addl, const char* source) void Manager::Weird(const char* name, const Packet* pkt, const char* addl, const char* source)
{ {
const char* weird_name = name; const char* weird_name = name;

View file

@ -60,14 +60,13 @@ public:
/** /**
* Looks up the connection referred to by a given key. * Looks up the connection referred to by a given key.
* *
* @param key The key for the connection to search for. * @param conn_key The key for the connection to search for.
* @param proto The transport protocol for the connection.
* @return The connection, or nullptr if one doesn't exist. * @return The connection, or nullptr if one doesn't exist.
*/ */
Connection* FindConnection(const zeek::detail::ConnKey& key, TransportProto proto); Connection* FindConnection(const zeek::detail::ConnKey& conn_key);
void Remove(Session* s); void Remove(Session* s);
void Insert(Session* c); void Insert(Session* c, bool remove_existing=true);
// Generating connection_pending events for all connections // Generating connection_pending events for all connections
// that are still active. // that are still active.
@ -94,43 +93,6 @@ public:
[[deprecated("Remove in v5.1. Use CurrentSessions().")]] [[deprecated("Remove in v5.1. Use CurrentSessions().")]]
unsigned int CurrentConnections() { return CurrentSessions(); } unsigned int CurrentConnections() { return CurrentSessions(); }
/**
* Main entry point for processing packets destined for session analyzers. This
* method is called by the packet analysis manager when after it has processed
* an IP-based packet, and shouldn't be called directly from other places.
*
* @param t The timestamp for this packet.
* @param pkt The packet being processed.
* @param len The number of bytes that haven't been processed yet by packet
* analysis.
*/
void ProcessTransportLayer(double t, const Packet *pkt, size_t len);
/**
* Returns a wrapper IP_Hdr object if \a pkt appears to be a valid IPv4
* or IPv6 header based on whether it's long enough to contain such a header,
* if version given in the header matches the proto argument, and also checks
* that the payload length field of that header matches the actual
* length of \a pkt given by \a caplen.
*
* @param caplen The length of \a pkt in bytes.
* @param pkt The inner IP packet data.
* @param proto Either IPPROTO_IPV6 or IPPROTO_IPV4 to indicate which IP
* protocol \a pkt corresponds to.
* @param inner The inner IP packet wrapper pointer to be allocated/assigned
* if \a pkt looks like a valid IP packet or at least long enough
* to hold an IP header.
* @return 0 If the inner IP packet appeared valid, else -1 if \a caplen
* is greater than the supposed IP packet's payload length field, -2
* if the version of the inner header does not match proto or
* 1 if \a caplen is less than the supposed packet's payload length.
* In the -1 case, \a inner may still be non-null if \a caplen was
* long enough to be an IP header, and \a inner is always non-null
* for other return values.
*/
int ParseIPPacket(int caplen, const u_char* const pkt, int proto,
IP_Hdr*& inner);
unsigned int SessionMemoryUsage(); unsigned int SessionMemoryUsage();
unsigned int SessionMemoryUsageVals(); unsigned int SessionMemoryUsageVals();
@ -148,32 +110,6 @@ private:
using SessionMap = std::map<detail::Key, Session*>; using SessionMap = std::map<detail::Key, Session*>;
Connection* NewConn(const zeek::detail::ConnKey& k, double t, const ConnTuple* id,
const u_char* data, int proto, uint32_t flow_label,
const Packet* pkt);
// Returns true if the port corresonds to an application
// for which there's a Bro analyzer (even if it might not
// be used by the present policy script), or it's more
// generally a likely server port, false otherwise.
//
// Note, port is in host order.
bool IsLikelyServerPort(uint32_t port, TransportProto transport_proto) const;
// 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 or such).
// Use tcp_flags=0 for non-TCP.
bool WantConnection(uint16_t src_port, uint16_t dest_port,
TransportProto transport_proto,
uint8_t tcp_flags, bool& flip_roles);
// For a given protocol, checks whether the header's length as derived
// from lower-level headers or the length actually captured is less
// than that protocol's minimum header size.
bool CheckHeaderTrunc(int proto, uint32_t len, uint32_t caplen, const Packet *pkt);
// Inserts a new connection into the sessions map. If a connection with // Inserts a new connection into the sessions map. If a connection with
// the same key already exists in the map, it will be overwritten by // the same key already exists in the map, it will be overwritten by
// the new one. Connection count stats get updated either way (so most // the new one. Connection count stats get updated either way (so most

View file

@ -37,8 +37,8 @@ XXXXXXXXXX.XXXXXX - 2001:4f8:4:7:2e0:81ff:fe52:ffff 0 2001:4f8:4:7:2e0:81ff:fe52
#open XXXX-XX-XX-XX-XX-XX #open XXXX-XX-XX-XX-XX-XX
#fields ts uid id.orig_h id.orig_p id.resp_h id.resp_p name addl notice peer source #fields ts uid id.orig_h id.orig_p id.resp_h id.resp_p name addl notice peer source
#types time string addr port addr port string string bool string string #types time string addr port addr port string string bool string string
XXXXXXXXXX.XXXXXX - 10.0.0.1 0 192.0.43.10 0 internally_truncated_header - F zeek - XXXXXXXXXX.XXXXXX - 10.0.0.1 0 192.0.43.10 0 internally_truncated_header - F zeek ICMP
XXXXXXXXXX.XXXXXX - 192.0.43.10 0 10.0.0.1 0 internally_truncated_header - F zeek - XXXXXXXXXX.XXXXXX - 192.0.43.10 0 10.0.0.1 0 internally_truncated_header - F zeek ICMP
#close XXXX-XX-XX-XX-XX-XX #close XXXX-XX-XX-XX-XX-XX
#separator \x09 #separator \x09
#set_separator , #set_separator ,

View file

@ -57,6 +57,12 @@ scripts/base/init-bare.zeek
scripts/base/packet-protocols/iptunnel/main.zeek scripts/base/packet-protocols/iptunnel/main.zeek
scripts/base/packet-protocols/vntag/__load__.zeek scripts/base/packet-protocols/vntag/__load__.zeek
scripts/base/packet-protocols/vntag/main.zeek scripts/base/packet-protocols/vntag/main.zeek
scripts/base/packet-protocols/udp/__load__.zeek
scripts/base/packet-protocols/udp/main.zeek
scripts/base/packet-protocols/tcp/__load__.zeek
scripts/base/packet-protocols/tcp/main.zeek
scripts/base/packet-protocols/icmp/__load__.zeek
scripts/base/packet-protocols/icmp/main.zeek
scripts/base/init-frameworks-and-bifs.zeek scripts/base/init-frameworks-and-bifs.zeek
scripts/base/frameworks/logging/__load__.zeek scripts/base/frameworks/logging/__load__.zeek
scripts/base/frameworks/logging/main.zeek scripts/base/frameworks/logging/main.zeek
@ -125,7 +131,6 @@ scripts/base/init-frameworks-and-bifs.zeek
build/scripts/base/bif/plugins/Zeek_GTPv1.events.bif.zeek build/scripts/base/bif/plugins/Zeek_GTPv1.events.bif.zeek
build/scripts/base/bif/plugins/Zeek_HTTP.events.bif.zeek build/scripts/base/bif/plugins/Zeek_HTTP.events.bif.zeek
build/scripts/base/bif/plugins/Zeek_HTTP.functions.bif.zeek build/scripts/base/bif/plugins/Zeek_HTTP.functions.bif.zeek
build/scripts/base/bif/plugins/Zeek_ICMP.events.bif.zeek
build/scripts/base/bif/plugins/Zeek_Ident.events.bif.zeek build/scripts/base/bif/plugins/Zeek_Ident.events.bif.zeek
build/scripts/base/bif/plugins/Zeek_IMAP.events.bif.zeek build/scripts/base/bif/plugins/Zeek_IMAP.events.bif.zeek
build/scripts/base/bif/plugins/Zeek_IRC.events.bif.zeek build/scripts/base/bif/plugins/Zeek_IRC.events.bif.zeek
@ -201,10 +206,11 @@ scripts/base/init-frameworks-and-bifs.zeek
build/scripts/base/bif/plugins/Zeek_TCP.types.bif.zeek build/scripts/base/bif/plugins/Zeek_TCP.types.bif.zeek
build/scripts/base/bif/plugins/Zeek_TCP.functions.bif.zeek build/scripts/base/bif/plugins/Zeek_TCP.functions.bif.zeek
build/scripts/base/bif/plugins/Zeek_Teredo.events.bif.zeek build/scripts/base/bif/plugins/Zeek_Teredo.events.bif.zeek
build/scripts/base/bif/plugins/Zeek_UDP.events.bif.zeek
build/scripts/base/bif/plugins/Zeek_VXLAN.events.bif.zeek build/scripts/base/bif/plugins/Zeek_VXLAN.events.bif.zeek
build/scripts/base/bif/plugins/Zeek_XMPP.events.bif.zeek build/scripts/base/bif/plugins/Zeek_XMPP.events.bif.zeek
build/scripts/base/bif/plugins/Zeek_ARP.events.bif.zeek build/scripts/base/bif/plugins/Zeek_ARP.events.bif.zeek
build/scripts/base/bif/plugins/Zeek_UDP.events.bif.zeek
build/scripts/base/bif/plugins/Zeek_ICMP.events.bif.zeek
build/scripts/base/bif/plugins/Zeek_FileEntropy.events.bif.zeek build/scripts/base/bif/plugins/Zeek_FileEntropy.events.bif.zeek
build/scripts/base/bif/plugins/Zeek_FileExtract.events.bif.zeek build/scripts/base/bif/plugins/Zeek_FileExtract.events.bif.zeek
build/scripts/base/bif/plugins/Zeek_FileExtract.functions.bif.zeek build/scripts/base/bif/plugins/Zeek_FileExtract.functions.bif.zeek

View file

@ -57,6 +57,12 @@ scripts/base/init-bare.zeek
scripts/base/packet-protocols/iptunnel/main.zeek scripts/base/packet-protocols/iptunnel/main.zeek
scripts/base/packet-protocols/vntag/__load__.zeek scripts/base/packet-protocols/vntag/__load__.zeek
scripts/base/packet-protocols/vntag/main.zeek scripts/base/packet-protocols/vntag/main.zeek
scripts/base/packet-protocols/udp/__load__.zeek
scripts/base/packet-protocols/udp/main.zeek
scripts/base/packet-protocols/tcp/__load__.zeek
scripts/base/packet-protocols/tcp/main.zeek
scripts/base/packet-protocols/icmp/__load__.zeek
scripts/base/packet-protocols/icmp/main.zeek
scripts/base/init-frameworks-and-bifs.zeek scripts/base/init-frameworks-and-bifs.zeek
scripts/base/frameworks/logging/__load__.zeek scripts/base/frameworks/logging/__load__.zeek
scripts/base/frameworks/logging/main.zeek scripts/base/frameworks/logging/main.zeek
@ -125,7 +131,6 @@ scripts/base/init-frameworks-and-bifs.zeek
build/scripts/base/bif/plugins/Zeek_GTPv1.events.bif.zeek build/scripts/base/bif/plugins/Zeek_GTPv1.events.bif.zeek
build/scripts/base/bif/plugins/Zeek_HTTP.events.bif.zeek build/scripts/base/bif/plugins/Zeek_HTTP.events.bif.zeek
build/scripts/base/bif/plugins/Zeek_HTTP.functions.bif.zeek build/scripts/base/bif/plugins/Zeek_HTTP.functions.bif.zeek
build/scripts/base/bif/plugins/Zeek_ICMP.events.bif.zeek
build/scripts/base/bif/plugins/Zeek_Ident.events.bif.zeek build/scripts/base/bif/plugins/Zeek_Ident.events.bif.zeek
build/scripts/base/bif/plugins/Zeek_IMAP.events.bif.zeek build/scripts/base/bif/plugins/Zeek_IMAP.events.bif.zeek
build/scripts/base/bif/plugins/Zeek_IRC.events.bif.zeek build/scripts/base/bif/plugins/Zeek_IRC.events.bif.zeek
@ -201,10 +206,11 @@ scripts/base/init-frameworks-and-bifs.zeek
build/scripts/base/bif/plugins/Zeek_TCP.types.bif.zeek build/scripts/base/bif/plugins/Zeek_TCP.types.bif.zeek
build/scripts/base/bif/plugins/Zeek_TCP.functions.bif.zeek build/scripts/base/bif/plugins/Zeek_TCP.functions.bif.zeek
build/scripts/base/bif/plugins/Zeek_Teredo.events.bif.zeek build/scripts/base/bif/plugins/Zeek_Teredo.events.bif.zeek
build/scripts/base/bif/plugins/Zeek_UDP.events.bif.zeek
build/scripts/base/bif/plugins/Zeek_VXLAN.events.bif.zeek build/scripts/base/bif/plugins/Zeek_VXLAN.events.bif.zeek
build/scripts/base/bif/plugins/Zeek_XMPP.events.bif.zeek build/scripts/base/bif/plugins/Zeek_XMPP.events.bif.zeek
build/scripts/base/bif/plugins/Zeek_ARP.events.bif.zeek build/scripts/base/bif/plugins/Zeek_ARP.events.bif.zeek
build/scripts/base/bif/plugins/Zeek_UDP.events.bif.zeek
build/scripts/base/bif/plugins/Zeek_ICMP.events.bif.zeek
build/scripts/base/bif/plugins/Zeek_FileEntropy.events.bif.zeek build/scripts/base/bif/plugins/Zeek_FileEntropy.events.bif.zeek
build/scripts/base/bif/plugins/Zeek_FileExtract.events.bif.zeek build/scripts/base/bif/plugins/Zeek_FileExtract.events.bif.zeek
build/scripts/base/bif/plugins/Zeek_FileExtract.functions.bif.zeek build/scripts/base/bif/plugins/Zeek_FileExtract.functions.bif.zeek

View file

@ -572,9 +572,13 @@
0.000000 MetaHookPost CallFunction(PacketAnalyzer::register_packet_analyzer, <frame>, (PacketAnalyzer::ANALYZER_IEEE802_11, 32821, PacketAnalyzer::ANALYZER_ARP)) -> <no result> 0.000000 MetaHookPost CallFunction(PacketAnalyzer::register_packet_analyzer, <frame>, (PacketAnalyzer::ANALYZER_IEEE802_11, 32821, PacketAnalyzer::ANALYZER_ARP)) -> <no result>
0.000000 MetaHookPost CallFunction(PacketAnalyzer::register_packet_analyzer, <frame>, (PacketAnalyzer::ANALYZER_IEEE802_11, 34525, PacketAnalyzer::ANALYZER_IP)) -> <no result> 0.000000 MetaHookPost CallFunction(PacketAnalyzer::register_packet_analyzer, <frame>, (PacketAnalyzer::ANALYZER_IEEE802_11, 34525, PacketAnalyzer::ANALYZER_IP)) -> <no result>
0.000000 MetaHookPost CallFunction(PacketAnalyzer::register_packet_analyzer, <frame>, (PacketAnalyzer::ANALYZER_IEEE802_11_RADIO, 105, PacketAnalyzer::ANALYZER_IEEE802_11)) -> <no result> 0.000000 MetaHookPost CallFunction(PacketAnalyzer::register_packet_analyzer, <frame>, (PacketAnalyzer::ANALYZER_IEEE802_11_RADIO, 105, PacketAnalyzer::ANALYZER_IEEE802_11)) -> <no result>
0.000000 MetaHookPost CallFunction(PacketAnalyzer::register_packet_analyzer, <frame>, (PacketAnalyzer::ANALYZER_IP, 1, PacketAnalyzer::ANALYZER_ICMP)) -> <no result>
0.000000 MetaHookPost CallFunction(PacketAnalyzer::register_packet_analyzer, <frame>, (PacketAnalyzer::ANALYZER_IP, 17, PacketAnalyzer::ANALYZER_UDP)) -> <no result>
0.000000 MetaHookPost CallFunction(PacketAnalyzer::register_packet_analyzer, <frame>, (PacketAnalyzer::ANALYZER_IP, 4, PacketAnalyzer::ANALYZER_IPTUNNEL)) -> <no result> 0.000000 MetaHookPost CallFunction(PacketAnalyzer::register_packet_analyzer, <frame>, (PacketAnalyzer::ANALYZER_IP, 4, PacketAnalyzer::ANALYZER_IPTUNNEL)) -> <no result>
0.000000 MetaHookPost CallFunction(PacketAnalyzer::register_packet_analyzer, <frame>, (PacketAnalyzer::ANALYZER_IP, 41, PacketAnalyzer::ANALYZER_IPTUNNEL)) -> <no result> 0.000000 MetaHookPost CallFunction(PacketAnalyzer::register_packet_analyzer, <frame>, (PacketAnalyzer::ANALYZER_IP, 41, PacketAnalyzer::ANALYZER_IPTUNNEL)) -> <no result>
0.000000 MetaHookPost CallFunction(PacketAnalyzer::register_packet_analyzer, <frame>, (PacketAnalyzer::ANALYZER_IP, 47, PacketAnalyzer::ANALYZER_GRE)) -> <no result> 0.000000 MetaHookPost CallFunction(PacketAnalyzer::register_packet_analyzer, <frame>, (PacketAnalyzer::ANALYZER_IP, 47, PacketAnalyzer::ANALYZER_GRE)) -> <no result>
0.000000 MetaHookPost CallFunction(PacketAnalyzer::register_packet_analyzer, <frame>, (PacketAnalyzer::ANALYZER_IP, 58, PacketAnalyzer::ANALYZER_ICMP)) -> <no result>
0.000000 MetaHookPost CallFunction(PacketAnalyzer::register_packet_analyzer, <frame>, (PacketAnalyzer::ANALYZER_IP, 6, PacketAnalyzer::ANALYZER_TCP)) -> <no result>
0.000000 MetaHookPost CallFunction(PacketAnalyzer::register_packet_analyzer, <frame>, (PacketAnalyzer::ANALYZER_LINUXSLL, 2048, PacketAnalyzer::ANALYZER_IP)) -> <no result> 0.000000 MetaHookPost CallFunction(PacketAnalyzer::register_packet_analyzer, <frame>, (PacketAnalyzer::ANALYZER_LINUXSLL, 2048, PacketAnalyzer::ANALYZER_IP)) -> <no result>
0.000000 MetaHookPost CallFunction(PacketAnalyzer::register_packet_analyzer, <frame>, (PacketAnalyzer::ANALYZER_LINUXSLL, 2054, PacketAnalyzer::ANALYZER_ARP)) -> <no result> 0.000000 MetaHookPost CallFunction(PacketAnalyzer::register_packet_analyzer, <frame>, (PacketAnalyzer::ANALYZER_LINUXSLL, 2054, PacketAnalyzer::ANALYZER_ARP)) -> <no result>
0.000000 MetaHookPost CallFunction(PacketAnalyzer::register_packet_analyzer, <frame>, (PacketAnalyzer::ANALYZER_LINUXSLL, 32821, PacketAnalyzer::ANALYZER_ARP)) -> <no result> 0.000000 MetaHookPost CallFunction(PacketAnalyzer::register_packet_analyzer, <frame>, (PacketAnalyzer::ANALYZER_LINUXSLL, 32821, PacketAnalyzer::ANALYZER_ARP)) -> <no result>
@ -915,6 +919,7 @@
0.000000 MetaHookPost LoadFile(0, base<...>/hash, <...>/hash) -> -1 0.000000 MetaHookPost LoadFile(0, base<...>/hash, <...>/hash) -> -1
0.000000 MetaHookPost LoadFile(0, base<...>/hash_hrw, <...>/hash_hrw.zeek) -> -1 0.000000 MetaHookPost LoadFile(0, base<...>/hash_hrw, <...>/hash_hrw.zeek) -> -1
0.000000 MetaHookPost LoadFile(0, base<...>/http, <...>/http) -> -1 0.000000 MetaHookPost LoadFile(0, base<...>/http, <...>/http) -> -1
0.000000 MetaHookPost LoadFile(0, base<...>/icmp, <...>/icmp) -> -1
0.000000 MetaHookPost LoadFile(0, base<...>/ieee802_11, <...>/ieee802_11) -> -1 0.000000 MetaHookPost LoadFile(0, base<...>/ieee802_11, <...>/ieee802_11) -> -1
0.000000 MetaHookPost LoadFile(0, base<...>/ieee802_11_radio, <...>/ieee802_11_radio) -> -1 0.000000 MetaHookPost LoadFile(0, base<...>/ieee802_11_radio, <...>/ieee802_11_radio) -> -1
0.000000 MetaHookPost LoadFile(0, base<...>/imap, <...>/imap) -> -1 0.000000 MetaHookPost LoadFile(0, base<...>/imap, <...>/imap) -> -1
@ -979,10 +984,12 @@
0.000000 MetaHookPost LoadFile(0, base<...>/supervisor, <...>/supervisor) -> -1 0.000000 MetaHookPost LoadFile(0, base<...>/supervisor, <...>/supervisor) -> -1
0.000000 MetaHookPost LoadFile(0, base<...>/supervisor.bif, <...>/supervisor.bif.zeek) -> -1 0.000000 MetaHookPost LoadFile(0, base<...>/supervisor.bif, <...>/supervisor.bif.zeek) -> -1
0.000000 MetaHookPost LoadFile(0, base<...>/syslog, <...>/syslog) -> -1 0.000000 MetaHookPost LoadFile(0, base<...>/syslog, <...>/syslog) -> -1
0.000000 MetaHookPost LoadFile(0, base<...>/tcp, <...>/tcp) -> -1
0.000000 MetaHookPost LoadFile(0, base<...>/thresholds, <...>/thresholds.zeek) -> -1 0.000000 MetaHookPost LoadFile(0, base<...>/thresholds, <...>/thresholds.zeek) -> -1
0.000000 MetaHookPost LoadFile(0, base<...>/time, <...>/time.zeek) -> -1 0.000000 MetaHookPost LoadFile(0, base<...>/time, <...>/time.zeek) -> -1
0.000000 MetaHookPost LoadFile(0, base<...>/tunnels, <...>/tunnels) -> -1 0.000000 MetaHookPost LoadFile(0, base<...>/tunnels, <...>/tunnels) -> -1
0.000000 MetaHookPost LoadFile(0, base<...>/types.bif, <...>/types.bif.zeek) -> -1 0.000000 MetaHookPost LoadFile(0, base<...>/types.bif, <...>/types.bif.zeek) -> -1
0.000000 MetaHookPost LoadFile(0, base<...>/udp, <...>/udp) -> -1
0.000000 MetaHookPost LoadFile(0, base<...>/urls, <...>/urls.zeek) -> -1 0.000000 MetaHookPost LoadFile(0, base<...>/urls, <...>/urls.zeek) -> -1
0.000000 MetaHookPost LoadFile(0, base<...>/utils, <...>/utils.zeek) -> -1 0.000000 MetaHookPost LoadFile(0, base<...>/utils, <...>/utils.zeek) -> -1
0.000000 MetaHookPost LoadFile(0, base<...>/version, <...>/version.zeek) -> -1 0.000000 MetaHookPost LoadFile(0, base<...>/version, <...>/version.zeek) -> -1
@ -1582,9 +1589,13 @@
0.000000 MetaHookPre CallFunction(PacketAnalyzer::register_packet_analyzer, <frame>, (PacketAnalyzer::ANALYZER_IEEE802_11, 32821, PacketAnalyzer::ANALYZER_ARP)) 0.000000 MetaHookPre CallFunction(PacketAnalyzer::register_packet_analyzer, <frame>, (PacketAnalyzer::ANALYZER_IEEE802_11, 32821, PacketAnalyzer::ANALYZER_ARP))
0.000000 MetaHookPre CallFunction(PacketAnalyzer::register_packet_analyzer, <frame>, (PacketAnalyzer::ANALYZER_IEEE802_11, 34525, PacketAnalyzer::ANALYZER_IP)) 0.000000 MetaHookPre CallFunction(PacketAnalyzer::register_packet_analyzer, <frame>, (PacketAnalyzer::ANALYZER_IEEE802_11, 34525, PacketAnalyzer::ANALYZER_IP))
0.000000 MetaHookPre CallFunction(PacketAnalyzer::register_packet_analyzer, <frame>, (PacketAnalyzer::ANALYZER_IEEE802_11_RADIO, 105, PacketAnalyzer::ANALYZER_IEEE802_11)) 0.000000 MetaHookPre CallFunction(PacketAnalyzer::register_packet_analyzer, <frame>, (PacketAnalyzer::ANALYZER_IEEE802_11_RADIO, 105, PacketAnalyzer::ANALYZER_IEEE802_11))
0.000000 MetaHookPre CallFunction(PacketAnalyzer::register_packet_analyzer, <frame>, (PacketAnalyzer::ANALYZER_IP, 1, PacketAnalyzer::ANALYZER_ICMP))
0.000000 MetaHookPre CallFunction(PacketAnalyzer::register_packet_analyzer, <frame>, (PacketAnalyzer::ANALYZER_IP, 17, PacketAnalyzer::ANALYZER_UDP))
0.000000 MetaHookPre CallFunction(PacketAnalyzer::register_packet_analyzer, <frame>, (PacketAnalyzer::ANALYZER_IP, 4, PacketAnalyzer::ANALYZER_IPTUNNEL)) 0.000000 MetaHookPre CallFunction(PacketAnalyzer::register_packet_analyzer, <frame>, (PacketAnalyzer::ANALYZER_IP, 4, PacketAnalyzer::ANALYZER_IPTUNNEL))
0.000000 MetaHookPre CallFunction(PacketAnalyzer::register_packet_analyzer, <frame>, (PacketAnalyzer::ANALYZER_IP, 41, PacketAnalyzer::ANALYZER_IPTUNNEL)) 0.000000 MetaHookPre CallFunction(PacketAnalyzer::register_packet_analyzer, <frame>, (PacketAnalyzer::ANALYZER_IP, 41, PacketAnalyzer::ANALYZER_IPTUNNEL))
0.000000 MetaHookPre CallFunction(PacketAnalyzer::register_packet_analyzer, <frame>, (PacketAnalyzer::ANALYZER_IP, 47, PacketAnalyzer::ANALYZER_GRE)) 0.000000 MetaHookPre CallFunction(PacketAnalyzer::register_packet_analyzer, <frame>, (PacketAnalyzer::ANALYZER_IP, 47, PacketAnalyzer::ANALYZER_GRE))
0.000000 MetaHookPre CallFunction(PacketAnalyzer::register_packet_analyzer, <frame>, (PacketAnalyzer::ANALYZER_IP, 58, PacketAnalyzer::ANALYZER_ICMP))
0.000000 MetaHookPre CallFunction(PacketAnalyzer::register_packet_analyzer, <frame>, (PacketAnalyzer::ANALYZER_IP, 6, PacketAnalyzer::ANALYZER_TCP))
0.000000 MetaHookPre CallFunction(PacketAnalyzer::register_packet_analyzer, <frame>, (PacketAnalyzer::ANALYZER_LINUXSLL, 2048, PacketAnalyzer::ANALYZER_IP)) 0.000000 MetaHookPre CallFunction(PacketAnalyzer::register_packet_analyzer, <frame>, (PacketAnalyzer::ANALYZER_LINUXSLL, 2048, PacketAnalyzer::ANALYZER_IP))
0.000000 MetaHookPre CallFunction(PacketAnalyzer::register_packet_analyzer, <frame>, (PacketAnalyzer::ANALYZER_LINUXSLL, 2054, PacketAnalyzer::ANALYZER_ARP)) 0.000000 MetaHookPre CallFunction(PacketAnalyzer::register_packet_analyzer, <frame>, (PacketAnalyzer::ANALYZER_LINUXSLL, 2054, PacketAnalyzer::ANALYZER_ARP))
0.000000 MetaHookPre CallFunction(PacketAnalyzer::register_packet_analyzer, <frame>, (PacketAnalyzer::ANALYZER_LINUXSLL, 32821, PacketAnalyzer::ANALYZER_ARP)) 0.000000 MetaHookPre CallFunction(PacketAnalyzer::register_packet_analyzer, <frame>, (PacketAnalyzer::ANALYZER_LINUXSLL, 32821, PacketAnalyzer::ANALYZER_ARP))
@ -1925,6 +1936,7 @@
0.000000 MetaHookPre LoadFile(0, base<...>/hash, <...>/hash) 0.000000 MetaHookPre LoadFile(0, base<...>/hash, <...>/hash)
0.000000 MetaHookPre LoadFile(0, base<...>/hash_hrw, <...>/hash_hrw.zeek) 0.000000 MetaHookPre LoadFile(0, base<...>/hash_hrw, <...>/hash_hrw.zeek)
0.000000 MetaHookPre LoadFile(0, base<...>/http, <...>/http) 0.000000 MetaHookPre LoadFile(0, base<...>/http, <...>/http)
0.000000 MetaHookPre LoadFile(0, base<...>/icmp, <...>/icmp)
0.000000 MetaHookPre LoadFile(0, base<...>/ieee802_11, <...>/ieee802_11) 0.000000 MetaHookPre LoadFile(0, base<...>/ieee802_11, <...>/ieee802_11)
0.000000 MetaHookPre LoadFile(0, base<...>/ieee802_11_radio, <...>/ieee802_11_radio) 0.000000 MetaHookPre LoadFile(0, base<...>/ieee802_11_radio, <...>/ieee802_11_radio)
0.000000 MetaHookPre LoadFile(0, base<...>/imap, <...>/imap) 0.000000 MetaHookPre LoadFile(0, base<...>/imap, <...>/imap)
@ -1989,10 +2001,12 @@
0.000000 MetaHookPre LoadFile(0, base<...>/supervisor, <...>/supervisor) 0.000000 MetaHookPre LoadFile(0, base<...>/supervisor, <...>/supervisor)
0.000000 MetaHookPre LoadFile(0, base<...>/supervisor.bif, <...>/supervisor.bif.zeek) 0.000000 MetaHookPre LoadFile(0, base<...>/supervisor.bif, <...>/supervisor.bif.zeek)
0.000000 MetaHookPre LoadFile(0, base<...>/syslog, <...>/syslog) 0.000000 MetaHookPre LoadFile(0, base<...>/syslog, <...>/syslog)
0.000000 MetaHookPre LoadFile(0, base<...>/tcp, <...>/tcp)
0.000000 MetaHookPre LoadFile(0, base<...>/thresholds, <...>/thresholds.zeek) 0.000000 MetaHookPre LoadFile(0, base<...>/thresholds, <...>/thresholds.zeek)
0.000000 MetaHookPre LoadFile(0, base<...>/time, <...>/time.zeek) 0.000000 MetaHookPre LoadFile(0, base<...>/time, <...>/time.zeek)
0.000000 MetaHookPre LoadFile(0, base<...>/tunnels, <...>/tunnels) 0.000000 MetaHookPre LoadFile(0, base<...>/tunnels, <...>/tunnels)
0.000000 MetaHookPre LoadFile(0, base<...>/types.bif, <...>/types.bif.zeek) 0.000000 MetaHookPre LoadFile(0, base<...>/types.bif, <...>/types.bif.zeek)
0.000000 MetaHookPre LoadFile(0, base<...>/udp, <...>/udp)
0.000000 MetaHookPre LoadFile(0, base<...>/urls, <...>/urls.zeek) 0.000000 MetaHookPre LoadFile(0, base<...>/urls, <...>/urls.zeek)
0.000000 MetaHookPre LoadFile(0, base<...>/utils, <...>/utils.zeek) 0.000000 MetaHookPre LoadFile(0, base<...>/utils, <...>/utils.zeek)
0.000000 MetaHookPre LoadFile(0, base<...>/version, <...>/version.zeek) 0.000000 MetaHookPre LoadFile(0, base<...>/version, <...>/version.zeek)
@ -2591,9 +2605,13 @@
0.000000 | HookCallFunction PacketAnalyzer::register_packet_analyzer(PacketAnalyzer::ANALYZER_IEEE802_11, 32821, PacketAnalyzer::ANALYZER_ARP) 0.000000 | HookCallFunction PacketAnalyzer::register_packet_analyzer(PacketAnalyzer::ANALYZER_IEEE802_11, 32821, PacketAnalyzer::ANALYZER_ARP)
0.000000 | HookCallFunction PacketAnalyzer::register_packet_analyzer(PacketAnalyzer::ANALYZER_IEEE802_11, 34525, PacketAnalyzer::ANALYZER_IP) 0.000000 | HookCallFunction PacketAnalyzer::register_packet_analyzer(PacketAnalyzer::ANALYZER_IEEE802_11, 34525, PacketAnalyzer::ANALYZER_IP)
0.000000 | HookCallFunction PacketAnalyzer::register_packet_analyzer(PacketAnalyzer::ANALYZER_IEEE802_11_RADIO, 105, PacketAnalyzer::ANALYZER_IEEE802_11) 0.000000 | HookCallFunction PacketAnalyzer::register_packet_analyzer(PacketAnalyzer::ANALYZER_IEEE802_11_RADIO, 105, PacketAnalyzer::ANALYZER_IEEE802_11)
0.000000 | HookCallFunction PacketAnalyzer::register_packet_analyzer(PacketAnalyzer::ANALYZER_IP, 1, PacketAnalyzer::ANALYZER_ICMP)
0.000000 | HookCallFunction PacketAnalyzer::register_packet_analyzer(PacketAnalyzer::ANALYZER_IP, 17, PacketAnalyzer::ANALYZER_UDP)
0.000000 | HookCallFunction PacketAnalyzer::register_packet_analyzer(PacketAnalyzer::ANALYZER_IP, 4, PacketAnalyzer::ANALYZER_IPTUNNEL) 0.000000 | HookCallFunction PacketAnalyzer::register_packet_analyzer(PacketAnalyzer::ANALYZER_IP, 4, PacketAnalyzer::ANALYZER_IPTUNNEL)
0.000000 | HookCallFunction PacketAnalyzer::register_packet_analyzer(PacketAnalyzer::ANALYZER_IP, 41, PacketAnalyzer::ANALYZER_IPTUNNEL) 0.000000 | HookCallFunction PacketAnalyzer::register_packet_analyzer(PacketAnalyzer::ANALYZER_IP, 41, PacketAnalyzer::ANALYZER_IPTUNNEL)
0.000000 | HookCallFunction PacketAnalyzer::register_packet_analyzer(PacketAnalyzer::ANALYZER_IP, 47, PacketAnalyzer::ANALYZER_GRE) 0.000000 | HookCallFunction PacketAnalyzer::register_packet_analyzer(PacketAnalyzer::ANALYZER_IP, 47, PacketAnalyzer::ANALYZER_GRE)
0.000000 | HookCallFunction PacketAnalyzer::register_packet_analyzer(PacketAnalyzer::ANALYZER_IP, 58, PacketAnalyzer::ANALYZER_ICMP)
0.000000 | HookCallFunction PacketAnalyzer::register_packet_analyzer(PacketAnalyzer::ANALYZER_IP, 6, PacketAnalyzer::ANALYZER_TCP)
0.000000 | HookCallFunction PacketAnalyzer::register_packet_analyzer(PacketAnalyzer::ANALYZER_LINUXSLL, 2048, PacketAnalyzer::ANALYZER_IP) 0.000000 | HookCallFunction PacketAnalyzer::register_packet_analyzer(PacketAnalyzer::ANALYZER_LINUXSLL, 2048, PacketAnalyzer::ANALYZER_IP)
0.000000 | HookCallFunction PacketAnalyzer::register_packet_analyzer(PacketAnalyzer::ANALYZER_LINUXSLL, 2054, PacketAnalyzer::ANALYZER_ARP) 0.000000 | HookCallFunction PacketAnalyzer::register_packet_analyzer(PacketAnalyzer::ANALYZER_LINUXSLL, 2054, PacketAnalyzer::ANALYZER_ARP)
0.000000 | HookCallFunction PacketAnalyzer::register_packet_analyzer(PacketAnalyzer::ANALYZER_LINUXSLL, 32821, PacketAnalyzer::ANALYZER_ARP) 0.000000 | HookCallFunction PacketAnalyzer::register_packet_analyzer(PacketAnalyzer::ANALYZER_LINUXSLL, 32821, PacketAnalyzer::ANALYZER_ARP)
@ -2946,6 +2964,7 @@
0.000000 | HookLoadFile base<...>/hash <...>/hash 0.000000 | HookLoadFile base<...>/hash <...>/hash
0.000000 | HookLoadFile base<...>/hash_hrw <...>/hash_hrw.zeek 0.000000 | HookLoadFile base<...>/hash_hrw <...>/hash_hrw.zeek
0.000000 | HookLoadFile base<...>/http <...>/http 0.000000 | HookLoadFile base<...>/http <...>/http
0.000000 | HookLoadFile base<...>/icmp <...>/icmp
0.000000 | HookLoadFile base<...>/ieee802_11 <...>/ieee802_11 0.000000 | HookLoadFile base<...>/ieee802_11 <...>/ieee802_11
0.000000 | HookLoadFile base<...>/ieee802_11_radio <...>/ieee802_11_radio 0.000000 | HookLoadFile base<...>/ieee802_11_radio <...>/ieee802_11_radio
0.000000 | HookLoadFile base<...>/imap <...>/imap 0.000000 | HookLoadFile base<...>/imap <...>/imap
@ -3010,10 +3029,12 @@
0.000000 | HookLoadFile base<...>/supervisor <...>/supervisor 0.000000 | HookLoadFile base<...>/supervisor <...>/supervisor
0.000000 | HookLoadFile base<...>/supervisor.bif <...>/supervisor.bif.zeek 0.000000 | HookLoadFile base<...>/supervisor.bif <...>/supervisor.bif.zeek
0.000000 | HookLoadFile base<...>/syslog <...>/syslog 0.000000 | HookLoadFile base<...>/syslog <...>/syslog
0.000000 | HookLoadFile base<...>/tcp <...>/tcp
0.000000 | HookLoadFile base<...>/thresholds <...>/thresholds.zeek 0.000000 | HookLoadFile base<...>/thresholds <...>/thresholds.zeek
0.000000 | HookLoadFile base<...>/time <...>/time.zeek 0.000000 | HookLoadFile base<...>/time <...>/time.zeek
0.000000 | HookLoadFile base<...>/tunnels <...>/tunnels 0.000000 | HookLoadFile base<...>/tunnels <...>/tunnels
0.000000 | HookLoadFile base<...>/types.bif <...>/types.bif.zeek 0.000000 | HookLoadFile base<...>/types.bif <...>/types.bif.zeek
0.000000 | HookLoadFile base<...>/udp <...>/udp
0.000000 | HookLoadFile base<...>/urls <...>/urls.zeek 0.000000 | HookLoadFile base<...>/urls <...>/urls.zeek
0.000000 | HookLoadFile base<...>/utils <...>/utils.zeek 0.000000 | HookLoadFile base<...>/utils <...>/utils.zeek
0.000000 | HookLoadFile base<...>/version <...>/version.zeek 0.000000 | HookLoadFile base<...>/version <...>/version.zeek