mirror of
https://github.com/zeek/zeek.git
synced 2025-10-09 10:08:20 +00:00
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:
commit
aa09e02117
78 changed files with 1939 additions and 1403 deletions
28
CHANGES
28
CHANGES
|
@ -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
|
||||
|
||||
* Omit unneeded decimal points in modp_dtoa2() scientific notation output (Jon Siwek, Corelight)
|
||||
|
|
2
VERSION
2
VERSION
|
@ -1 +1 @@
|
|||
4.1.0-dev.646
|
||||
4.1.0-dev.660
|
||||
|
|
|
@ -15,3 +15,6 @@
|
|||
@load base/packet-protocols/gre
|
||||
@load base/packet-protocols/iptunnel
|
||||
@load base/packet-protocols/vntag
|
||||
@load base/packet-protocols/udp
|
||||
@load base/packet-protocols/tcp
|
||||
@load base/packet-protocols/icmp
|
||||
|
|
1
scripts/base/packet-protocols/icmp/__load__.zeek
Normal file
1
scripts/base/packet-protocols/icmp/__load__.zeek
Normal file
|
@ -0,0 +1 @@
|
|||
@load ./main
|
5
scripts/base/packet-protocols/icmp/main.zeek
Normal file
5
scripts/base/packet-protocols/icmp/main.zeek
Normal file
|
@ -0,0 +1,5 @@
|
|||
module PacketAnalyzer::ICMP;
|
||||
|
||||
#event zeek_init() &priority=20
|
||||
# {
|
||||
# }
|
|
@ -1,8 +1,22 @@
|
|||
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
|
||||
{
|
||||
PacketAnalyzer::register_packet_analyzer(PacketAnalyzer::ANALYZER_IP, 4, PacketAnalyzer::ANALYZER_IPTUNNEL);
|
||||
PacketAnalyzer::register_packet_analyzer(PacketAnalyzer::ANALYZER_IP, 41, PacketAnalyzer::ANALYZER_IPTUNNEL);
|
||||
PacketAnalyzer::register_packet_analyzer(PacketAnalyzer::ANALYZER_IP, 47, PacketAnalyzer::ANALYZER_GRE);
|
||||
PacketAnalyzer::register_packet_analyzer(PacketAnalyzer::ANALYZER_IP, IPPROTO_IPIP, PacketAnalyzer::ANALYZER_IPTUNNEL);
|
||||
PacketAnalyzer::register_packet_analyzer(PacketAnalyzer::ANALYZER_IP, IPPROTO_IPV6, PacketAnalyzer::ANALYZER_IPTUNNEL);
|
||||
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);
|
||||
}
|
||||
|
|
1
scripts/base/packet-protocols/tcp/__load__.zeek
Normal file
1
scripts/base/packet-protocols/tcp/__load__.zeek
Normal file
|
@ -0,0 +1 @@
|
|||
@load ./main
|
5
scripts/base/packet-protocols/tcp/main.zeek
Normal file
5
scripts/base/packet-protocols/tcp/main.zeek
Normal file
|
@ -0,0 +1,5 @@
|
|||
module PacketAnalyzer::TCP;
|
||||
|
||||
#event zeek_init() &priority=20
|
||||
# {
|
||||
# }
|
1
scripts/base/packet-protocols/udp/__load__.zeek
Normal file
1
scripts/base/packet-protocols/udp/__load__.zeek
Normal file
|
@ -0,0 +1 @@
|
|||
@load ./main
|
5
scripts/base/packet-protocols/udp/main.zeek
Normal file
5
scripts/base/packet-protocols/udp/main.zeek
Normal file
|
@ -0,0 +1,5 @@
|
|||
module PacketAnalyzer::UDP;
|
||||
|
||||
#event zeek_init() &priority=20
|
||||
# {
|
||||
# }
|
39
src/Conn.cc
39
src/Conn.cc
|
@ -19,6 +19,7 @@
|
|||
#include "zeek/analyzer/Analyzer.h"
|
||||
#include "zeek/analyzer/Manager.h"
|
||||
#include "zeek/iosource/IOSource.h"
|
||||
#include "zeek/packet_analysis/protocol/ip/SessionAdapter.h"
|
||||
|
||||
namespace zeek {
|
||||
|
||||
|
@ -64,7 +65,7 @@ Connection::Connection(const detail::ConnKey& k, double t,
|
|||
hist_seen = 0;
|
||||
history = "";
|
||||
|
||||
root_analyzer = nullptr;
|
||||
adapter = nullptr;
|
||||
primary_PIA = nullptr;
|
||||
|
||||
++current_connections;
|
||||
|
@ -83,7 +84,7 @@ Connection::~Connection()
|
|||
if ( conn_val )
|
||||
conn_val->SetOrigin(nullptr);
|
||||
|
||||
delete root_analyzer;
|
||||
delete adapter;
|
||||
|
||||
--current_connections;
|
||||
}
|
||||
|
@ -129,7 +130,7 @@ void Connection::Done()
|
|||
// somewhere, but it's session-related, so maybe not?
|
||||
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"));
|
||||
analyzer::tcp::TCP_Endpoint* to = ta->Orig();
|
||||
analyzer::tcp::TCP_Endpoint* tr = ta->Resp();
|
||||
|
@ -139,8 +140,8 @@ void Connection::Done()
|
|||
|
||||
finished = 1;
|
||||
|
||||
if ( root_analyzer && ! root_analyzer->IsFinished() )
|
||||
root_analyzer->Done();
|
||||
if ( adapter && ! adapter->IsFinished() )
|
||||
adapter->Done();
|
||||
}
|
||||
|
||||
void Connection::NextPacket(double t, bool is_orig,
|
||||
|
@ -156,11 +157,11 @@ void Connection::NextPacket(double t, bool is_orig,
|
|||
if ( Skipping() )
|
||||
return;
|
||||
|
||||
if ( root_analyzer )
|
||||
if ( adapter )
|
||||
{
|
||||
record_current_packet = record_packet;
|
||||
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_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)
|
||||
{
|
||||
return root_analyzer && root_analyzer->IsReuse(t, pkt);
|
||||
return adapter && adapter->IsReuse(t, pkt);
|
||||
}
|
||||
|
||||
bool Connection::ScaledHistoryEntry(char code, uint32_t& counter,
|
||||
|
@ -275,8 +276,8 @@ const RecordValPtr& Connection::GetVal()
|
|||
|
||||
}
|
||||
|
||||
if ( root_analyzer )
|
||||
root_analyzer->UpdateConnVal(conn_val.get());
|
||||
if ( adapter )
|
||||
adapter->UpdateConnVal(conn_val.get());
|
||||
|
||||
conn_val->AssignTime(3, 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)
|
||||
{
|
||||
return root_analyzer ? root_analyzer->FindChild(id) : nullptr;
|
||||
return adapter ? adapter->FindChild(id) : nullptr;
|
||||
}
|
||||
|
||||
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)
|
||||
{
|
||||
return root_analyzer->FindChild(name);
|
||||
return adapter->FindChild(name);
|
||||
}
|
||||
|
||||
void Connection::AppendAddl(const char* str)
|
||||
|
@ -370,8 +371,8 @@ void Connection::FlipRoles()
|
|||
|
||||
conn_val = nullptr;
|
||||
|
||||
if ( root_analyzer )
|
||||
root_analyzer->FlipRoles();
|
||||
if ( adapter )
|
||||
adapter->FlipRoles();
|
||||
|
||||
analyzer_mgr->ApplyScheduledAnalyzers(this);
|
||||
|
||||
|
@ -383,7 +384,7 @@ unsigned int Connection::MemoryAllocation() const
|
|||
return session::Session::MemoryAllocation() + padded_sizeof(*this)
|
||||
+ (timers.MemoryAllocation() - padded_sizeof(timers))
|
||||
+ (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.
|
||||
;
|
||||
}
|
||||
|
@ -448,10 +449,10 @@ void Connection::IDString(ODesc* d) const
|
|||
d->Add(ntohs(resp_port));
|
||||
}
|
||||
|
||||
void Connection::SetRootAnalyzer(analyzer::TransportLayerAnalyzer* analyzer,
|
||||
analyzer::pia::PIA* pia)
|
||||
void Connection::SetSessionAdapter(packet_analysis::IP::SessionAdapter* aa,
|
||||
analyzer::pia::PIA* pia)
|
||||
{
|
||||
root_analyzer = analyzer;
|
||||
adapter = aa;
|
||||
primary_PIA = pia;
|
||||
}
|
||||
|
||||
|
|
19
src/Conn.h
19
src/Conn.h
|
@ -41,12 +41,8 @@ class RuleHdrTest;
|
|||
|
||||
} // namespace detail
|
||||
|
||||
namespace analyzer {
|
||||
|
||||
class TransportLayerAnalyzer;
|
||||
class Analyzer;
|
||||
|
||||
} // namespace analyzer
|
||||
namespace analyzer { class Analyzer; }
|
||||
namespace packet_analysis::IP { class SessionAdapter; }
|
||||
|
||||
enum ConnEventToFlag {
|
||||
NUL_IN_LINE,
|
||||
|
@ -117,7 +113,10 @@ public:
|
|||
// should be marked invalid.
|
||||
const detail::ConnKey& Key() const { return key; }
|
||||
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& RespAddr() const { return resp_addr; }
|
||||
|
@ -231,8 +230,8 @@ public:
|
|||
void AddHistory(char code) { history += code; }
|
||||
|
||||
// Sets the root of the analyzer tree as well as the primary PIA.
|
||||
void SetRootAnalyzer(analyzer::TransportLayerAnalyzer* analyzer, analyzer::pia::PIA* pia);
|
||||
analyzer::TransportLayerAnalyzer* GetRootAnalyzer() { return root_analyzer; }
|
||||
void SetSessionAdapter(packet_analysis::IP::SessionAdapter* aa, analyzer::pia::PIA* pia);
|
||||
packet_analysis::IP::SessionAdapter* GetSessionAdapter() { return adapter; }
|
||||
analyzer::pia::PIA* GetPrimaryPIA() { return primary_PIA; }
|
||||
|
||||
// Sets the transport protocol in use.
|
||||
|
@ -279,7 +278,7 @@ private:
|
|||
uint32_t hist_seen;
|
||||
std::string history;
|
||||
|
||||
analyzer::TransportLayerAnalyzer* root_analyzer;
|
||||
packet_analysis::IP::SessionAdapter* adapter;
|
||||
analyzer::pia::PIA* primary_PIA;
|
||||
|
||||
UID uid; // Globally unique connection ID.
|
||||
|
|
|
@ -177,6 +177,7 @@ public:
|
|||
bool operator!=( const DictIterator& that ) const { return !(*this == that); }
|
||||
|
||||
private:
|
||||
|
||||
friend class Dictionary;
|
||||
|
||||
DictIterator(const Dictionary* d, detail::DictEntry* begin, detail::DictEntry* end);
|
||||
|
|
|
@ -25,12 +25,12 @@ namespace zeek::detail {
|
|||
bool RuleConditionTCPState::DoMatch(Rule* rule, RuleEndpointState* state,
|
||||
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;
|
||||
|
||||
auto* ta = static_cast<analyzer::tcp::TCP_Analyzer*>(root);
|
||||
auto* ta = static_cast<analyzer::tcp::TCP_Analyzer*>(adapter);
|
||||
|
||||
if ( tcpstates & RULE_STATE_STATELESS )
|
||||
return true;
|
||||
|
@ -57,9 +57,9 @@ void RuleConditionTCPState::PrintDebug()
|
|||
bool RuleConditionUDPState::DoMatch(Rule* rule, RuleEndpointState* state,
|
||||
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;
|
||||
|
||||
if ( states & RULE_STATE_STATELESS )
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -25,6 +25,7 @@ using FilePtr = zeek::IntrusivePtr<File>;
|
|||
using RecordValPtr = zeek::IntrusivePtr<RecordVal>;
|
||||
|
||||
namespace detail { class Rule; }
|
||||
namespace packet_analysis::IP { class IPBasedAnalyzer; }
|
||||
|
||||
} // namespace zeek
|
||||
|
||||
|
@ -601,6 +602,7 @@ protected:
|
|||
friend class Manager;
|
||||
friend class zeek::Connection;
|
||||
friend class zeek::analyzer::tcp::TCP_ApplicationAnalyzer;
|
||||
friend class zeek::packet_analysis::IP::IPBasedAnalyzer;
|
||||
|
||||
/**
|
||||
* Return a string represantation of an analyzer, containing its name
|
||||
|
@ -844,83 +846,4 @@ private:
|
|||
#define CONTENTS_RESP 2
|
||||
#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
|
||||
|
|
|
@ -8,11 +8,11 @@
|
|||
#include "zeek/RunState.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/stepping-stone/SteppingStone.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"
|
||||
|
||||
|
@ -354,15 +354,10 @@ Manager::tag_set* Manager::LookupPort(TransportProto proto, uint32_t port, bool
|
|||
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)
|
||||
{
|
||||
analyzer::tcp::TCP_Analyzer* tcp = nullptr;
|
||||
TransportLayerAnalyzer* root = nullptr;
|
||||
packet_analysis::IP::SessionAdapter* root = nullptr;
|
||||
analyzer::pia::PIA* pia = nullptr;
|
||||
bool check_port = false;
|
||||
|
||||
|
@ -375,19 +370,6 @@ bool Manager::BuildInitialAnalyzerTree(Connection* conn)
|
|||
DBG_ANALYZER(conn, "activated TCP analyzer");
|
||||
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:
|
||||
reporter->InternalWarning("unknown protocol can't build analyzer tree");
|
||||
return false;
|
||||
|
@ -489,7 +471,7 @@ bool Manager::BuildInitialAnalyzerTree(Connection* conn)
|
|||
if ( pia )
|
||||
root->AddChildAnalyzer(pia->AsAnalyzer());
|
||||
|
||||
conn->SetRootAnalyzer(root, pia);
|
||||
conn->SetSessionAdapter(root, pia);
|
||||
root->Init();
|
||||
root->InitChildren();
|
||||
|
||||
|
@ -607,10 +589,11 @@ Manager::tag_set Manager::GetScheduled(const Connection* conn)
|
|||
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 )
|
||||
parent = conn->GetRootAnalyzer();
|
||||
parent = conn->GetSessionAdapter();
|
||||
|
||||
if ( ! parent )
|
||||
return false;
|
||||
|
|
|
@ -35,6 +35,14 @@
|
|||
#include "zeek/analyzer/analyzer.bif.h"
|
||||
|
||||
namespace zeek {
|
||||
|
||||
namespace packet_analysis::IP {
|
||||
|
||||
class IPBasedAnalyzer;
|
||||
class SessionAdapter;
|
||||
|
||||
} // namespace packet_analysis::IP
|
||||
|
||||
namespace analyzer {
|
||||
|
||||
/**
|
||||
|
@ -244,8 +252,8 @@ public:
|
|||
*
|
||||
* @param conn The connection to add the initial set of analyzers to.
|
||||
*
|
||||
* @return False if the tree cannot be build; that's usually an
|
||||
* internally error.
|
||||
* @return False if the tree cannot be built; that's usually an
|
||||
* internal error.
|
||||
*/
|
||||
bool BuildInitialAnalyzerTree(Connection* conn);
|
||||
|
||||
|
@ -313,7 +321,7 @@ public:
|
|||
* @return True if at least one scheduled analyzer was found.
|
||||
*/
|
||||
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
|
||||
|
@ -345,10 +353,11 @@ public:
|
|||
|
||||
private:
|
||||
|
||||
friend class packet_analysis::IP::IPBasedAnalyzer;
|
||||
|
||||
using tag_set = std::set<Tag>;
|
||||
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 GetScheduled(const Connection* conn);
|
||||
|
|
|
@ -14,7 +14,6 @@ add_subdirectory(gnutella)
|
|||
add_subdirectory(gssapi)
|
||||
add_subdirectory(gtpv1)
|
||||
add_subdirectory(http)
|
||||
add_subdirectory(icmp)
|
||||
add_subdirectory(ident)
|
||||
add_subdirectory(imap)
|
||||
add_subdirectory(irc)
|
||||
|
@ -45,7 +44,6 @@ add_subdirectory(stepping-stone)
|
|||
add_subdirectory(syslog)
|
||||
add_subdirectory(tcp)
|
||||
add_subdirectory(teredo)
|
||||
add_subdirectory(udp)
|
||||
add_subdirectory(vxlan)
|
||||
add_subdirectory(xmpp)
|
||||
add_subdirectory(zip)
|
||||
|
|
|
@ -2,9 +2,9 @@
|
|||
|
||||
#include "zeek/analyzer/protocol/ayiya/AYIYA.h"
|
||||
|
||||
#include "zeek/session/Manager.h"
|
||||
#include "zeek/Func.h"
|
||||
#include "zeek/packet_analysis/protocol/iptunnel/IPTunnel.h"
|
||||
#include "zeek/packet_analysis/protocol/ip/IP.h"
|
||||
|
||||
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;
|
||||
inner_packet_offset = -1;
|
||||
|
||||
IP_Hdr* inner = nullptr;
|
||||
int result = session_mgr->ParseIPPacket(len, data, next_header, inner);
|
||||
std::unique_ptr<IP_Hdr> inner;
|
||||
int result = packet_analysis::IP::ParsePacket(len, data, next_header, inner);
|
||||
|
||||
if ( result == 0 )
|
||||
{
|
||||
|
@ -66,9 +66,6 @@ void AYIYA_Analyzer::DeliverPacket(int len, const u_char* data, bool orig, uint6
|
|||
else
|
||||
ProtocolViolation("AYIYA payload length",
|
||||
reinterpret_cast<const char*>(data), len);
|
||||
|
||||
if ( result != 0 )
|
||||
delete inner;
|
||||
}
|
||||
|
||||
} // namespace zeek::analyzer::ayiya
|
||||
|
|
|
@ -1,7 +1,5 @@
|
|||
#pragma once
|
||||
|
||||
#include "zeek/analyzer/protocol/udp/UDP.h"
|
||||
|
||||
#include "analyzer/protocol/dhcp/dhcp_pac.h"
|
||||
|
||||
namespace zeek::analyzer::dhcp {
|
||||
|
|
|
@ -1,7 +1,6 @@
|
|||
#pragma once
|
||||
|
||||
#include "zeek/analyzer/protocol/tcp/TCP.h"
|
||||
#include "zeek/analyzer/protocol/udp/UDP.h"
|
||||
|
||||
#include "analyzer/protocol/dnp3/dnp3_pac.h"
|
||||
|
||||
|
|
|
@ -129,7 +129,7 @@ bool Gnutella_Analyzer::IsHTTP(std::string header)
|
|||
if ( Parent()->IsAnalyzer("TCP") )
|
||||
{
|
||||
// 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 )
|
||||
static_cast<analyzer::pia::PIA_TCP *>(pia)->ReplayStreamBuffer(a);
|
||||
}
|
||||
|
|
|
@ -2,8 +2,8 @@
|
|||
|
||||
#include "zeek/analyzer/protocol/gtpv1/GTPv1.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"
|
||||
|
||||
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;
|
||||
inner_packet_offset = -1;
|
||||
|
||||
IP_Hdr* inner = nullptr;
|
||||
int result = session_mgr->ParseIPPacket(len, data, next_header, inner);
|
||||
std::unique_ptr<IP_Hdr> inner = nullptr;
|
||||
int result = packet_analysis::IP::ParsePacket(len, data, next_header, inner);
|
||||
|
||||
if ( result == 0 )
|
||||
{
|
||||
|
@ -77,9 +77,6 @@ void GTPv1_Analyzer::DeliverPacket(int len, const u_char* data, bool orig, uint6
|
|||
else
|
||||
ProtocolViolation("GTPv1 payload length",
|
||||
reinterpret_cast<const char*>(odata), olen);
|
||||
|
||||
if ( result != 0 )
|
||||
delete inner;
|
||||
}
|
||||
|
||||
} // namespace zeek::analyzer::gtpv1
|
||||
|
|
|
@ -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
|
|
@ -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
|
|
@ -2,7 +2,6 @@
|
|||
|
||||
#pragma once
|
||||
|
||||
#include "zeek/analyzer/protocol/udp/UDP.h"
|
||||
#include "zeek/analyzer/protocol/tcp/TCP.h"
|
||||
|
||||
namespace zeek::analyzer::netbios_ssn {
|
||||
|
|
|
@ -1,7 +1,5 @@
|
|||
#pragma once
|
||||
|
||||
#include "zeek/analyzer/protocol/udp/UDP.h"
|
||||
|
||||
#include "zeek/analyzer/protocol/ntp/events.bif.h"
|
||||
#include "zeek/analyzer/protocol/ntp/types.bif.h"
|
||||
#include "zeek/analyzer/protocol/ntp/ntp_pac.h"
|
||||
|
|
|
@ -1,7 +1,5 @@
|
|||
#pragma once
|
||||
|
||||
#include "zeek/analyzer/protocol/udp/UDP.h"
|
||||
|
||||
#include "zeek/analyzer/protocol/radius/events.bif.h"
|
||||
#include "zeek/analyzer/protocol/radius/radius_pac.h"
|
||||
|
||||
|
|
|
@ -1,7 +1,5 @@
|
|||
#pragma once
|
||||
|
||||
#include "zeek/analyzer/protocol/udp/UDP.h"
|
||||
|
||||
#include "zeek/analyzer/protocol/rdp/events.bif.h"
|
||||
#include "zeek/analyzer/protocol/rdp/rdpeudp_pac.h"
|
||||
|
||||
|
|
|
@ -1,7 +1,5 @@
|
|||
#pragma once
|
||||
|
||||
#include "zeek/analyzer/protocol/udp/UDP.h"
|
||||
|
||||
#include "zeek/analyzer/protocol/sip/events.bif.h"
|
||||
#include "zeek/analyzer/protocol/sip/sip_pac.h"
|
||||
|
||||
|
|
|
@ -1,7 +1,5 @@
|
|||
#pragma once
|
||||
|
||||
#include "zeek/analyzer/protocol/udp/UDP.h"
|
||||
|
||||
#include "zeek/analyzer/protocol/ssl/events.bif.h"
|
||||
|
||||
namespace binpac { namespace DTLS { class SSL_Conn; } }
|
||||
|
|
|
@ -1,6 +1,5 @@
|
|||
#pragma once
|
||||
|
||||
#include "zeek/analyzer/protocol/udp/UDP.h"
|
||||
#include "zeek/analyzer/protocol/tcp/TCP.h"
|
||||
|
||||
#include "analyzer/protocol/syslog/syslog_pac.h"
|
||||
|
|
|
@ -123,7 +123,7 @@ static RecordVal* build_syn_packet_val(bool is_orig, const IP_Hdr* ip,
|
|||
|
||||
|
||||
TCP_Analyzer::TCP_Analyzer(Connection* conn)
|
||||
: TransportLayerAnalyzer("TCP", conn)
|
||||
: packet_analysis::IP::SessionAdapter("TCP", conn)
|
||||
{
|
||||
// Set a timer to eventually time out this connection.
|
||||
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* child = analyzer::TransportLayerAnalyzer::FindChild(arg_id);
|
||||
analyzer::Analyzer* child = packet_analysis::IP::SessionAdapter::FindChild(arg_id);
|
||||
|
||||
if ( 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* child = analyzer::TransportLayerAnalyzer::FindChild(arg_tag);
|
||||
analyzer::Analyzer* child = packet_analysis::IP::SessionAdapter::FindChild(arg_tag);
|
||||
|
||||
if ( child )
|
||||
return child;
|
||||
|
@ -214,7 +214,7 @@ analyzer::Analyzer* TCP_Analyzer::FindChild(analyzer::Tag arg_tag)
|
|||
|
||||
bool TCP_Analyzer::RemoveChildAnalyzer(analyzer::ID id)
|
||||
{
|
||||
auto rval = analyzer::TransportLayerAnalyzer::RemoveChildAnalyzer(id);
|
||||
auto rval = packet_analysis::IP::SessionAdapter::RemoveChildAnalyzer(id);
|
||||
|
||||
if ( 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,
|
||||
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);
|
||||
if ( ! tp )
|
||||
|
|
|
@ -6,6 +6,7 @@
|
|||
#include "zeek/IPAddr.h"
|
||||
#include "zeek/analyzer/protocol/tcp/TCP_Endpoint.h"
|
||||
#include "zeek/analyzer/protocol/tcp/TCP_Flags.h"
|
||||
#include "zeek/packet_analysis/protocol/ip/SessionAdapter.h"
|
||||
#include "zeek/Conn.h"
|
||||
|
||||
// We define two classes here:
|
||||
|
@ -22,7 +23,7 @@ class TCP_Endpoint;
|
|||
class TCP_Reassembler;
|
||||
class TCP_ApplicationAnalyzer;
|
||||
|
||||
class TCP_Analyzer final : public analyzer::TransportLayerAnalyzer {
|
||||
class TCP_Analyzer final : public packet_analysis::IP::SessionAdapter {
|
||||
public:
|
||||
explicit TCP_Analyzer(Connection* conn);
|
||||
~TCP_Analyzer() override;
|
||||
|
@ -72,6 +73,8 @@ public:
|
|||
static analyzer::Analyzer* Instantiate(Connection* conn)
|
||||
{ return new TCP_Analyzer(conn); }
|
||||
|
||||
void AddExtraAnalyzers(Connection* conn) override {}
|
||||
|
||||
protected:
|
||||
friend class TCP_ApplicationAnalyzer;
|
||||
friend class TCP_Reassembler;
|
||||
|
|
|
@ -101,7 +101,7 @@ function set_contents_file%(cid: conn_id, direction: count, f: file%): bool
|
|||
if ( ! c )
|
||||
return zeek::val_mgr->False();
|
||||
|
||||
c->GetRootAnalyzer()->SetContentsFile(direction, {zeek::NewRef{}, f});
|
||||
c->GetSessionAdapter()->SetContentsFile(direction, {zeek::NewRef{}, f});
|
||||
return zeek::val_mgr->True();
|
||||
%}
|
||||
|
||||
|
@ -124,7 +124,7 @@ function get_contents_file%(cid: conn_id, direction: count%): file
|
|||
|
||||
if ( c )
|
||||
{
|
||||
auto cf = c->GetRootAnalyzer()->GetContentsFile(direction);
|
||||
auto cf = c->GetSessionAdapter()->GetContentsFile(direction);
|
||||
|
||||
if ( cf )
|
||||
return zeek::make_intrusive<zeek::FileVal>(std::move(cf));
|
||||
|
|
|
@ -4,10 +4,10 @@
|
|||
#include "zeek/Conn.h"
|
||||
#include "zeek/IP.h"
|
||||
#include "zeek/Reporter.h"
|
||||
#include "zeek/session/Manager.h"
|
||||
#include "zeek/ZeekString.h"
|
||||
#include "zeek/RunState.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"
|
||||
|
||||
|
@ -94,7 +94,7 @@ bool TeredoEncapsulation::DoParse(const u_char* data, int& len,
|
|||
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_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;
|
||||
}
|
||||
|
||||
IP_Hdr* inner = nullptr;
|
||||
int rslt = session_mgr->ParseIPPacket(len, te.InnerIP(), IPPROTO_IPV6, inner);
|
||||
std::unique_ptr<IP_Hdr> inner = nullptr;
|
||||
int rslt = packet_analysis::IP::ParsePacket(len, te.InnerIP(), IPPROTO_IPV6, inner);
|
||||
|
||||
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);
|
||||
else
|
||||
{
|
||||
delete inner;
|
||||
ProtocolViolation("Teredo payload length", (const char*) data, len);
|
||||
return;
|
||||
}
|
||||
|
@ -193,7 +192,6 @@ void Teredo_Analyzer::DeliverPacket(int len, const u_char* data, bool orig,
|
|||
|
||||
else
|
||||
{
|
||||
delete inner;
|
||||
ProtocolViolation("Truncated Teredo or invalid inner IP version", (const char*) data, len);
|
||||
return;
|
||||
}
|
||||
|
|
|
@ -74,7 +74,7 @@ public:
|
|||
const u_char* Authentication() const
|
||||
{ return auth; }
|
||||
|
||||
RecordValPtr BuildVal(const IP_Hdr* inner) const;
|
||||
RecordValPtr BuildVal(const std::unique_ptr<IP_Hdr>& inner) const;
|
||||
|
||||
protected:
|
||||
bool DoParse(const u_char* data, int& len, bool found_orig, bool found_au);
|
||||
|
|
|
@ -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
|
|
@ -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
|
|
@ -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
|
|
@ -41,7 +41,7 @@ static zeek::analyzer::Analyzer* add_analyzer(zeek::Connection* conn)
|
|||
auto a = zeek::analyzer_mgr->InstantiateAnalyzer(ZEEK_FUZZ_ANALYZER, conn);
|
||||
tcp->AddChildAnalyzer(a);
|
||||
tcp->AddChildAnalyzer(pia->AsAnalyzer());
|
||||
conn->SetRootAnalyzer(tcp, pia);
|
||||
conn->SetSessionAdapter(tcp, pia);
|
||||
return a;
|
||||
}
|
||||
|
||||
|
|
|
@ -189,6 +189,13 @@ public:
|
|||
*/
|
||||
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
|
||||
// stored with the packet so they stay available as the packet is passed
|
||||
// around.
|
||||
|
|
|
@ -10,7 +10,8 @@
|
|||
|
||||
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);
|
||||
|
||||
|
@ -80,10 +81,15 @@ bool Analyzer::ForwardPacket(size_t len, const uint8_t* data, Packet* packet,
|
|||
|
||||
if ( inner_analyzer == nullptr )
|
||||
{
|
||||
DBG_LOG(DBG_PACKET_ANALYSIS, "Analysis in %s failed, could not find analyzer for identifier %#x.",
|
||||
GetAnalyzerName(), identifier);
|
||||
packet_mgr->ReportUnknownProtocol(GetAnalyzerName(), identifier, data, len);
|
||||
return false;
|
||||
if ( report_unknown_protocols )
|
||||
{
|
||||
DBG_LOG(DBG_PACKET_ANALYSIS, "Analysis in %s failed, could not find analyzer for identifier %#x.",
|
||||
GetAnalyzerName(), identifier);
|
||||
packet_mgr->ReportUnknownProtocol(GetAnalyzerName(), identifier, data, len);
|
||||
return false;
|
||||
}
|
||||
else
|
||||
return true;
|
||||
}
|
||||
|
||||
DBG_LOG(DBG_PACKET_ANALYSIS, "Analysis in %s succeeded, next layer identifier is %#x.",
|
||||
|
@ -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.",
|
||||
GetAnalyzerName());
|
||||
|
||||
Weird("no_suitable_analyzer_found", packet);
|
||||
if ( report_unknown_protocols )
|
||||
Weird("no_suitable_analyzer_found", packet);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
|
|
@ -17,8 +17,11 @@ public:
|
|||
*
|
||||
* @param name The name for the type of analyzer. The name must match
|
||||
* the one the corresponding Component registers.
|
||||
* @param report_unknown_protocols Flag for whether to report unknown
|
||||
* protocols during packet forwarding. This should generally always be
|
||||
* set to true.
|
||||
*/
|
||||
explicit Analyzer(std::string name);
|
||||
explicit Analyzer(std::string name, bool report_unknown_protocols=true);
|
||||
|
||||
/**
|
||||
* Constructor.
|
||||
|
@ -165,6 +168,11 @@ private:
|
|||
Dispatcher dispatcher;
|
||||
AnalyzerPtr default_analyzer = nullptr;
|
||||
|
||||
/**
|
||||
* Flag for whether to report unknown protocols in ForwardPacket.
|
||||
*/
|
||||
bool report_unknown_protocols = true;
|
||||
|
||||
void Init(const Tag& tag);
|
||||
};
|
||||
|
||||
|
|
|
@ -101,7 +101,7 @@ void Manager::ProcessPacket(Packet* packet)
|
|||
bool dumped_packet = false;
|
||||
if ( packet->dump_packet || zeek::detail::record_all_packets )
|
||||
{
|
||||
DumpPacket(packet);
|
||||
DumpPacket(packet, packet->dump_size);
|
||||
dumped_packet = true;
|
||||
}
|
||||
|
||||
|
@ -114,7 +114,7 @@ void Manager::ProcessPacket(Packet* packet)
|
|||
|
||||
// Check whether packet should be recorded based on session analysis
|
||||
if ( packet->dump_packet && ! dumped_packet )
|
||||
DumpPacket(packet);
|
||||
DumpPacket(packet, packet->dump_size);
|
||||
}
|
||||
|
||||
bool Manager::ProcessInnerPacket(Packet* packet)
|
||||
|
|
|
@ -15,6 +15,9 @@ add_subdirectory(linux_sll)
|
|||
|
||||
add_subdirectory(arp)
|
||||
add_subdirectory(ip)
|
||||
add_subdirectory(udp)
|
||||
add_subdirectory(tcp)
|
||||
add_subdirectory(icmp)
|
||||
add_subdirectory(gre)
|
||||
add_subdirectory(iptunnel)
|
||||
add_subdirectory(vntag)
|
||||
|
|
|
@ -1,55 +1,89 @@
|
|||
// See the file "COPYING" in the main distribution directory for copyright.
|
||||
|
||||
#include "zeek/zeek-config.h"
|
||||
#include "zeek/analyzer/protocol/icmp/ICMP.h"
|
||||
#include "zeek/packet_analysis/protocol/icmp/ICMP.h"
|
||||
|
||||
#include <netinet/icmp6.h>
|
||||
#include <algorithm>
|
||||
|
||||
#include "zeek/IP.h"
|
||||
#include "zeek/RunState.h"
|
||||
#include "zeek/NetVar.h"
|
||||
#include "zeek/Event.h"
|
||||
#include "zeek/Conn.h"
|
||||
#include "zeek/Desc.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)
|
||||
: TransportLayerAnalyzer("ICMP", c),
|
||||
icmp_conn_val(), type(), code(), request_len(-1), reply_len(-1)
|
||||
enum ICMP_EndpointState {
|
||||
ICMP_INACTIVE, // no packet seen
|
||||
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,
|
||||
bool is_orig, uint64_t seq, const IP_Hdr* ip, int caplen)
|
||||
SessionAdapter* ICMPAnalyzer::MakeSessionAdapter(Connection* conn)
|
||||
{
|
||||
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
|
||||
// caplen > len.
|
||||
if ( packet_contents )
|
||||
// Subtract off the common part of ICMP header.
|
||||
PacketContents(data + 8, std::min(len, caplen) - 8);
|
||||
bool ICMPAnalyzer::BuildConnTuple(size_t len, const uint8_t* data, Packet* packet,
|
||||
ConnTuple& tuple)
|
||||
{
|
||||
if ( ! CheckHeaderTrunc(ICMP_MINLEN, len, packet) )
|
||||
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;
|
||||
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 &&
|
||||
! zeek::id::find_val<TableVal>("ignore_checksums_nets")->Contains(ip->IPHeaderSrcAddr()) &&
|
||||
caplen >= len )
|
||||
remaining >= len )
|
||||
{
|
||||
int chksum = 0;
|
||||
|
||||
|
@ -60,94 +94,81 @@ void ICMP_Analyzer::DeliverPacket(int len, const u_char* data,
|
|||
break;
|
||||
|
||||
case IPPROTO_ICMPV6:
|
||||
chksum = icmp6_checksum(icmpp, ip, len);
|
||||
chksum = icmp6_checksum(icmpp, ip.get(), len);
|
||||
break;
|
||||
|
||||
default:
|
||||
reporter->AnalyzerError(
|
||||
this, "unexpected IP proto in ICMP analyzer: %d", ip->NextProto());
|
||||
reporter->Error("unexpected IP proto in ICMP analyzer: %d", ip->NextProto());
|
||||
return;
|
||||
}
|
||||
|
||||
if ( chksum != 0xffff )
|
||||
{
|
||||
Weird("bad_ICMP_checksum");
|
||||
adapter->Weird("bad_ICMP_checksum");
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
Conn()->SetLastTime(run_state::current_timestamp);
|
||||
|
||||
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;
|
||||
c->SetLastTime(run_state::current_timestamp);
|
||||
adapter->InitEndpointMatcher(ip.get(), len, is_orig);
|
||||
|
||||
// Move past common portion of ICMP header.
|
||||
data += 8;
|
||||
caplen -= 8;
|
||||
remaining -= 8;
|
||||
len -= 8;
|
||||
|
||||
int& len_stat = is_orig ? request_len : reply_len;
|
||||
if ( len_stat < 0 )
|
||||
len_stat = len;
|
||||
else
|
||||
len_stat += len;
|
||||
adapter->UpdateLength(is_orig, len);
|
||||
|
||||
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 )
|
||||
NextICMP6(run_state::current_timestamp, icmpp, len, caplen, data, ip);
|
||||
NextICMP6(run_state::current_timestamp, icmpp, len, remaining, data, ip.get(), adapter);
|
||||
else
|
||||
{
|
||||
reporter->AnalyzerError(
|
||||
this, "expected ICMP as IP packet's protocol, got %d", ip->NextProto());
|
||||
reporter->Error("expected ICMP as IP packet's protocol, got %d", ip->NextProto());
|
||||
return;
|
||||
}
|
||||
|
||||
ForwardPacket(len, data, pkt);
|
||||
|
||||
if ( caplen >= len )
|
||||
ForwardPacket(len, data, is_orig, seq, ip, caplen);
|
||||
if ( remaining >= len )
|
||||
adapter->ForwardPacket(len, data, is_orig, -1, ip.get(), remaining);
|
||||
|
||||
if ( zeek::detail::rule_matcher )
|
||||
matcher_state.Match(zeek::detail::Rule::PAYLOAD, data, len, is_orig,
|
||||
false, false, true);
|
||||
adapter->MatchEndpoint(data, len, is_orig);
|
||||
}
|
||||
|
||||
void ICMP_Analyzer::NextICMP4(double t, const struct icmp* icmpp, int len, int caplen,
|
||||
const u_char*& data, const IP_Hdr* ip_hdr )
|
||||
void ICMPAnalyzer::NextICMP4(double t, const struct icmp* icmpp, int len, int caplen,
|
||||
const u_char*& data, const IP_Hdr* ip_hdr,
|
||||
ICMPSessionAdapter* adapter)
|
||||
{
|
||||
switch ( icmpp->icmp_type )
|
||||
{
|
||||
case ICMP_ECHO:
|
||||
case ICMP_ECHOREPLY:
|
||||
Echo(t, icmpp, len, caplen, data, ip_hdr);
|
||||
Echo(t, icmpp, len, caplen, data, ip_hdr, adapter);
|
||||
break;
|
||||
|
||||
case ICMP_UNREACH:
|
||||
case ICMP_TIMXCEED:
|
||||
Context4(t, icmpp, len, caplen, data, ip_hdr);
|
||||
Context4(t, icmpp, len, caplen, data, ip_hdr, adapter);
|
||||
break;
|
||||
|
||||
default:
|
||||
ICMP_Sent(icmpp, len, caplen, 0, data, ip_hdr);
|
||||
ICMP_Sent(icmpp, len, caplen, 0, data, ip_hdr, adapter);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void ICMP_Analyzer::NextICMP6(double t, const struct icmp* icmpp, int len, int caplen,
|
||||
const u_char*& data, const IP_Hdr* ip_hdr )
|
||||
void ICMPAnalyzer::NextICMP6(double t, const struct icmp* icmpp, int len, int caplen,
|
||||
const u_char*& data, const IP_Hdr* ip_hdr,
|
||||
ICMPSessionAdapter* adapter)
|
||||
{
|
||||
switch ( icmpp->icmp_type )
|
||||
{
|
||||
// Echo types.
|
||||
case ICMP6_ECHO_REQUEST:
|
||||
case ICMP6_ECHO_REPLY:
|
||||
Echo(t, icmpp, len, caplen, data, ip_hdr);
|
||||
Echo(t, icmpp, len, caplen, data, ip_hdr, adapter);
|
||||
break;
|
||||
|
||||
// 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_PACKET_TOO_BIG:
|
||||
case ICMP6_DST_UNREACH:
|
||||
Context6(t, icmpp, len, caplen, data, ip_hdr);
|
||||
Context6(t, icmpp, len, caplen, data, ip_hdr, adapter);
|
||||
break;
|
||||
|
||||
// Router related messages.
|
||||
case ND_REDIRECT:
|
||||
Redirect(t, icmpp, len, caplen, data, ip_hdr);
|
||||
Redirect(t, icmpp, len, caplen, data, ip_hdr, adapter);
|
||||
break;
|
||||
case ND_ROUTER_ADVERT:
|
||||
RouterAdvert(t, icmpp, len, caplen, data, ip_hdr);
|
||||
RouterAdvert(t, icmpp, len, caplen, data, ip_hdr, adapter);
|
||||
break;
|
||||
case ND_NEIGHBOR_ADVERT:
|
||||
NeighborAdvert(t, icmpp, len, caplen, data, ip_hdr);
|
||||
NeighborAdvert(t, icmpp, len, caplen, data, ip_hdr, adapter);
|
||||
break;
|
||||
case ND_NEIGHBOR_SOLICIT:
|
||||
NeighborSolicit(t, icmpp, len, caplen, data, ip_hdr);
|
||||
NeighborSolicit(t, icmpp, len, caplen, data, ip_hdr, adapter);
|
||||
break;
|
||||
case ND_ROUTER_SOLICIT:
|
||||
RouterSolicit(t, icmpp, len, caplen, data, ip_hdr);
|
||||
RouterSolicit(t, icmpp, len, caplen, data, ip_hdr, adapter);
|
||||
break;
|
||||
case ICMP6_ROUTER_RENUMBERING:
|
||||
ICMP_Sent(icmpp, len, caplen, 1, data, ip_hdr);
|
||||
ICMP_Sent(icmpp, len, caplen, 1, data, ip_hdr, adapter);
|
||||
break;
|
||||
|
||||
#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
|
||||
// handled by the same function.
|
||||
if ( icmpp->icmp_type < 128 )
|
||||
Context6(t, icmpp, len, caplen, data, ip_hdr);
|
||||
Context6(t, icmpp, len, caplen, data, ip_hdr, adapter);
|
||||
else
|
||||
ICMP_Sent(icmpp, len, caplen, 1, data, ip_hdr);
|
||||
ICMP_Sent(icmpp, len, caplen, 1, data, ip_hdr, adapter);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void ICMP_Analyzer::ICMP_Sent(const struct icmp* icmpp, int len, int caplen,
|
||||
int icmpv6, const u_char* data,
|
||||
const IP_Hdr* ip_hdr)
|
||||
void ICMPAnalyzer::ICMP_Sent(const struct icmp* icmpp, int len, int caplen,
|
||||
int icmpv6, const u_char* data, const IP_Hdr* ip_hdr,
|
||||
ICMPSessionAdapter* adapter)
|
||||
{
|
||||
if ( icmp_sent )
|
||||
EnqueueConnEvent(icmp_sent,
|
||||
ConnVal(),
|
||||
BuildInfo(icmpp, len, icmpv6, ip_hdr)
|
||||
);
|
||||
adapter->EnqueueConnEvent(icmp_sent, adapter->ConnVal(),
|
||||
BuildInfo(icmpp, len, icmpv6, ip_hdr));
|
||||
|
||||
if ( icmp_sent_payload )
|
||||
{
|
||||
String* payload = new String(data, std::min(len, caplen), false);
|
||||
|
||||
EnqueueConnEvent(icmp_sent_payload,
|
||||
ConnVal(),
|
||||
BuildInfo(icmpp, len, icmpv6, ip_hdr),
|
||||
make_intrusive<StringVal>(payload)
|
||||
);
|
||||
adapter->EnqueueConnEvent(icmp_sent_payload, adapter->ConnVal(),
|
||||
BuildInfo(icmpp, len, icmpv6, ip_hdr),
|
||||
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)
|
||||
{
|
||||
static auto icmp_info = id::find_type<RecordType>("icmp_info");
|
||||
auto rval = make_intrusive<RecordVal>(icmp_info);
|
||||
rval->Assign(0, static_cast<bool>(icmpv6));
|
||||
rval->Assign(1, icmpp->icmp_type);
|
||||
rval->Assign(2, icmpp->icmp_code);
|
||||
rval->Assign(3, len);
|
||||
rval->Assign(4, ip_hdr->TTL());
|
||||
auto rval = make_intrusive<zeek::RecordVal>(icmp_info);
|
||||
rval->Assign(0, val_mgr->Bool(icmpv6));
|
||||
rval->Assign(1, val_mgr->Count(icmpp->icmp_type));
|
||||
rval->Assign(2, val_mgr->Count(icmpp->icmp_code));
|
||||
rval->Assign(3, val_mgr->Count(len));
|
||||
rval->Assign(4, val_mgr->Count(ip_hdr->TTL()));
|
||||
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;
|
||||
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;
|
||||
}
|
||||
|
||||
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 = &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");
|
||||
auto iprec = make_intrusive<RecordVal>(icmp_context);
|
||||
auto id_val = make_intrusive<RecordVal>(id::conn_id);
|
||||
auto iprec = make_intrusive<zeek::RecordVal>(icmp_context);
|
||||
auto id_val = make_intrusive<zeek::RecordVal>(id::conn_id);
|
||||
|
||||
id_val->Assign(0, make_intrusive<AddrVal>(src_addr));
|
||||
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));
|
||||
|
||||
iprec->Assign(0, std::move(id_val));
|
||||
iprec->Assign(1, ip_len);
|
||||
iprec->Assign(2, proto);
|
||||
iprec->Assign(3, frag_offset);
|
||||
iprec->Assign(4, static_cast<bool>(bad_hdr_len));
|
||||
iprec->Assign(5, static_cast<bool>(bad_checksum));
|
||||
iprec->Assign(6, static_cast<bool>(MF));
|
||||
iprec->Assign(7, static_cast<bool>(DF));
|
||||
iprec->Assign(1, val_mgr->Count(ip_len));
|
||||
iprec->Assign(2, val_mgr->Count(proto));
|
||||
iprec->Assign(3, val_mgr->Count(frag_offset));
|
||||
iprec->Assign(4, val_mgr->Bool(bad_hdr_len));
|
||||
iprec->Assign(5, val_mgr->Bool(bad_checksum));
|
||||
iprec->Assign(6, val_mgr->Bool(MF));
|
||||
iprec->Assign(7, val_mgr->Bool(DF));
|
||||
|
||||
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;
|
||||
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");
|
||||
auto iprec = make_intrusive<RecordVal>(icmp_context);
|
||||
auto id_val = make_intrusive<RecordVal>(id::conn_id);
|
||||
auto iprec = make_intrusive<zeek::RecordVal>(icmp_context);
|
||||
auto id_val = make_intrusive<zeek::RecordVal>(id::conn_id);
|
||||
|
||||
id_val->Assign(0, make_intrusive<AddrVal>(src_addr));
|
||||
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));
|
||||
|
||||
iprec->Assign(0, std::move(id_val));
|
||||
iprec->Assign(1, ip_len);
|
||||
iprec->Assign(2, proto);
|
||||
iprec->Assign(3, frag_offset);
|
||||
iprec->Assign(4, static_cast<bool>(bad_hdr_len));
|
||||
iprec->Assign(1, val_mgr->Count(ip_len));
|
||||
iprec->Assign(2, val_mgr->Count(proto));
|
||||
iprec->Assign(3, val_mgr->Count(frag_offset));
|
||||
iprec->Assign(4, val_mgr->Bool(bad_hdr_len));
|
||||
// bad_checksum is always false since IPv6 layer doesn't have a checksum.
|
||||
iprec->Assign(5, false);
|
||||
iprec->Assign(6, static_cast<bool>(MF));
|
||||
iprec->Assign(7, static_cast<bool>(DF));
|
||||
iprec->Assign(5, val_mgr->False());
|
||||
iprec->Assign(6, val_mgr->Bool(MF));
|
||||
iprec->Assign(7, val_mgr->Bool(DF));
|
||||
|
||||
return iprec;
|
||||
}
|
||||
|
||||
bool ICMP_Analyzer::IsReuse(double /* t */, const u_char* /* pkt */)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
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)
|
||||
void ICMPAnalyzer::Echo(double t, const struct icmp* icmpp, int len,
|
||||
int caplen, const u_char*& data, const IP_Hdr* ip_hdr,
|
||||
ICMPSessionAdapter* adapter)
|
||||
{
|
||||
// For handling all Echo related ICMP messages
|
||||
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);
|
||||
|
||||
EnqueueConnEvent(f,
|
||||
ConnVal(),
|
||||
adapter->EnqueueConnEvent(f,
|
||||
adapter->ConnVal(),
|
||||
BuildInfo(icmpp, len, ip_hdr->NextProto() != IPPROTO_ICMP, ip_hdr),
|
||||
val_mgr->Count(iid),
|
||||
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,
|
||||
int caplen, const u_char*& data, const IP_Hdr* ip_hdr)
|
||||
void ICMPAnalyzer::RouterAdvert(double t, const struct icmp* icmpp, int len,
|
||||
int caplen, const u_char*& data, const IP_Hdr* ip_hdr,
|
||||
ICMPSessionAdapter* adapter)
|
||||
{
|
||||
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);
|
||||
|
||||
EnqueueConnEvent(f,
|
||||
ConnVal(),
|
||||
adapter->EnqueueConnEvent(f,
|
||||
adapter->ConnVal(),
|
||||
BuildInfo(icmpp, len, 1, ip_hdr),
|
||||
val_mgr->Count(icmpp->icmp_num_addrs), // Cur Hop Limit
|
||||
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)ntohl(reachable), 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,
|
||||
int caplen, const u_char*& data, const IP_Hdr* ip_hdr)
|
||||
void ICMPAnalyzer::NeighborAdvert(double t, const struct icmp* icmpp, int len,
|
||||
int caplen, const u_char*& data, const IP_Hdr* ip_hdr,
|
||||
ICMPSessionAdapter* adapter)
|
||||
{
|
||||
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);
|
||||
|
||||
EnqueueConnEvent(f,
|
||||
ConnVal(),
|
||||
adapter->EnqueueConnEvent(f,
|
||||
adapter->ConnVal(),
|
||||
BuildInfo(icmpp, len, 1, ip_hdr),
|
||||
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 & 0x20), // Override
|
||||
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,
|
||||
int caplen, const u_char*& data, const IP_Hdr* ip_hdr)
|
||||
void ICMPAnalyzer::NeighborSolicit(double t, const struct icmp* icmpp, int len,
|
||||
int caplen, const u_char*& data, const IP_Hdr* ip_hdr,
|
||||
ICMPSessionAdapter* adapter)
|
||||
{
|
||||
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);
|
||||
|
||||
EnqueueConnEvent(f,
|
||||
ConnVal(),
|
||||
adapter->EnqueueConnEvent(f,
|
||||
adapter->ConnVal(),
|
||||
BuildInfo(icmpp, len, 1, ip_hdr),
|
||||
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,
|
||||
int caplen, const u_char*& data, const IP_Hdr* ip_hdr)
|
||||
void ICMPAnalyzer::Redirect(double t, const struct icmp* icmpp, int len,
|
||||
int caplen, const u_char*& data, const IP_Hdr* ip_hdr,
|
||||
ICMPSessionAdapter* adapter)
|
||||
{
|
||||
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);
|
||||
|
||||
EnqueueConnEvent(f,
|
||||
ConnVal(),
|
||||
adapter->EnqueueConnEvent(f,
|
||||
adapter->ConnVal(),
|
||||
BuildInfo(icmpp, len, 1, ip_hdr),
|
||||
make_intrusive<AddrVal>(tgtaddr),
|
||||
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,
|
||||
int caplen, const u_char*& data, const IP_Hdr* ip_hdr)
|
||||
void ICMPAnalyzer::RouterSolicit(double t, const struct icmp* icmpp, int len,
|
||||
int caplen, const u_char*& data, const IP_Hdr* ip_hdr,
|
||||
ICMPSessionAdapter* adapter)
|
||||
{
|
||||
EventHandlerPtr f = icmp_router_solicitation;
|
||||
|
||||
if ( ! f )
|
||||
return;
|
||||
|
||||
EnqueueConnEvent(f,
|
||||
ConnVal(),
|
||||
adapter->EnqueueConnEvent(f,
|
||||
adapter->ConnVal(),
|
||||
BuildInfo(icmpp, len, 1, ip_hdr),
|
||||
BuildNDOptionsVal(caplen, data)
|
||||
BuildNDOptionsVal(caplen, data, adapter)
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
void ICMP_Analyzer::Context4(double t, const struct icmp* icmpp,
|
||||
int len, int caplen, const u_char*& data, const IP_Hdr* ip_hdr)
|
||||
void ICMPAnalyzer::Context4(double t, const struct icmp* icmpp, int len,
|
||||
int caplen, const u_char*& data, const IP_Hdr* ip_hdr,
|
||||
ICMPSessionAdapter* adapter)
|
||||
{
|
||||
EventHandlerPtr f = nullptr;
|
||||
|
||||
|
@ -670,8 +630,8 @@ void ICMP_Analyzer::Context4(double t, const struct icmp* icmpp,
|
|||
}
|
||||
|
||||
if ( f )
|
||||
EnqueueConnEvent(f,
|
||||
ConnVal(),
|
||||
adapter->EnqueueConnEvent(f,
|
||||
adapter->ConnVal(),
|
||||
BuildInfo(icmpp, len, 0, ip_hdr),
|
||||
val_mgr->Count(icmpp->icmp_code),
|
||||
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,
|
||||
int len, int caplen, const u_char*& data, const IP_Hdr* ip_hdr)
|
||||
void ICMPAnalyzer::Context6(double t, const struct icmp* icmpp, int len,
|
||||
int caplen, const u_char*& data, const IP_Hdr* ip_hdr,
|
||||
ICMPSessionAdapter* adapter)
|
||||
{
|
||||
EventHandlerPtr f = nullptr;
|
||||
|
||||
|
@ -708,20 +669,21 @@ void ICMP_Analyzer::Context6(double t, const struct icmp* icmpp,
|
|||
}
|
||||
|
||||
if ( f )
|
||||
EnqueueConnEvent(f,
|
||||
ConnVal(),
|
||||
adapter->EnqueueConnEvent(f,
|
||||
adapter->ConnVal(),
|
||||
BuildInfo(icmpp, len, 1, ip_hdr),
|
||||
val_mgr->Count(icmpp->icmp_code),
|
||||
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_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"));
|
||||
|
||||
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.
|
||||
if ( caplen < 2 )
|
||||
{
|
||||
Weird("truncated_ICMPv6_ND_options");
|
||||
adapter->Weird("truncated_ICMPv6_ND_options");
|
||||
break;
|
||||
}
|
||||
|
||||
|
@ -738,13 +700,13 @@ VectorValPtr ICMP_Analyzer::BuildNDOptionsVal(int caplen, const u_char* data)
|
|||
|
||||
if ( length == 0 )
|
||||
{
|
||||
Weird("zero_length_ICMPv6_ND_option");
|
||||
adapter->Weird("zero_length_ICMPv6_ND_option");
|
||||
break;
|
||||
}
|
||||
|
||||
auto rv = make_intrusive<RecordVal>(icmp6_nd_option_type);
|
||||
rv->Assign(0, type);
|
||||
rv->Assign(1, length);
|
||||
auto rv = make_intrusive<zeek::RecordVal>(icmp6_nd_option_type);
|
||||
rv->Assign(0, val_mgr->Count(type));
|
||||
rv->Assign(1, val_mgr->Count(length));
|
||||
|
||||
// Adjust length to be in units of bytes, exclude type/length fields.
|
||||
length = length * 8 - 2;
|
||||
|
@ -763,7 +725,7 @@ VectorValPtr ICMP_Analyzer::BuildNDOptionsVal(int caplen, const u_char* data)
|
|||
if ( caplen >= length )
|
||||
{
|
||||
String* link_addr = new String(data, length, false);
|
||||
rv->Assign(2, link_addr);
|
||||
rv->Assign(2, make_intrusive<StringVal>(link_addr));
|
||||
}
|
||||
else
|
||||
set_payload_field = true;
|
||||
|
@ -776,18 +738,18 @@ VectorValPtr ICMP_Analyzer::BuildNDOptionsVal(int caplen, const u_char* data)
|
|||
{
|
||||
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));
|
||||
bool L_flag = (*((const uint8_t*)(data + 1)) & 0x80) != 0;
|
||||
bool A_flag = (*((const uint8_t*)(data + 1)) & 0x40) != 0;
|
||||
uint32_t valid_life = *((const uint32_t*)(data + 2));
|
||||
uint32_t prefer_life = *((const uint32_t*)(data + 6));
|
||||
in6_addr prefix = *((const in6_addr*)(data + 14));
|
||||
info->Assign(0, prefix_len);
|
||||
info->Assign(1, L_flag);
|
||||
info->Assign(2, A_flag);
|
||||
info->AssignInterval(3, double(ntohl(valid_life)));
|
||||
info->AssignInterval(4, double(ntohl(prefer_life)));
|
||||
info->Assign(0, val_mgr->Count(prefix_len));
|
||||
info->Assign(1, val_mgr->Bool(L_flag));
|
||||
info->Assign(2, val_mgr->Bool(A_flag));
|
||||
info->Assign(3, make_intrusive<IntervalVal>((double)ntohl(valid_life), Seconds));
|
||||
info->Assign(4, make_intrusive<IntervalVal>((double)ntohl(prefer_life), Seconds));
|
||||
info->Assign(5, make_intrusive<AddrVal>(IPAddr(prefix)));
|
||||
rv->Assign(3, std::move(info));
|
||||
}
|
||||
|
@ -816,7 +778,7 @@ VectorValPtr ICMP_Analyzer::BuildNDOptionsVal(int caplen, const u_char* data)
|
|||
// MTU option
|
||||
{
|
||||
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
|
||||
set_payload_field = true;
|
||||
|
||||
|
@ -833,7 +795,7 @@ VectorValPtr ICMP_Analyzer::BuildNDOptionsVal(int caplen, const u_char* data)
|
|||
if ( set_payload_field )
|
||||
{
|
||||
String* payload = new String(data, std::min((int)length, caplen), false);
|
||||
rv->Assign(6, payload);
|
||||
rv->Assign(6, make_intrusive<StringVal>(payload));
|
||||
}
|
||||
|
||||
data += length;
|
||||
|
@ -845,7 +807,7 @@ VectorValPtr ICMP_Analyzer::BuildNDOptionsVal(int caplen, const u_char* data)
|
|||
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;
|
||||
|
||||
|
@ -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;
|
||||
|
||||
|
@ -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();
|
||||
}
|
138
src/packet_analysis/protocol/icmp/ICMP.h
Normal file
138
src/packet_analysis/protocol/icmp/ICMP.h
Normal 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
|
26
src/packet_analysis/protocol/icmp/Plugin.cc
Normal file
26
src/packet_analysis/protocol/icmp/Plugin.cc
Normal 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;
|
||||
|
||||
}
|
|
@ -4,5 +4,5 @@ include(ZeekPlugin)
|
|||
include_directories(BEFORE ${CMAKE_CURRENT_SOURCE_DIR} ${CMAKE_CURRENT_BINARY_DIR})
|
||||
|
||||
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()
|
||||
|
|
|
@ -10,6 +10,7 @@
|
|||
#include "zeek/Frag.h"
|
||||
#include "zeek/Event.h"
|
||||
#include "zeek/TunnelEncapsulation.h"
|
||||
#include "zeek/IPAddr.h"
|
||||
|
||||
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;
|
||||
|
||||
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:
|
||||
// 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
|
||||
|
@ -268,3 +261,40 @@ bool IPAnalyzer::AnalyzePacket(size_t len, const uint8_t* data, Packet* packet)
|
|||
|
||||
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;
|
||||
}
|
||||
|
|
|
@ -32,4 +32,28 @@ private:
|
|||
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);
|
||||
}
|
||||
|
|
273
src/packet_analysis/protocol/ip/IPBasedAnalyzer.cc
Normal file
273
src/packet_analysis/protocol/ip/IPBasedAnalyzer.cc
Normal 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;
|
||||
}
|
149
src/packet_analysis/protocol/ip/IPBasedAnalyzer.h
Normal file
149
src/packet_analysis/protocol/ip/IPBasedAnalyzer.h
Normal 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;
|
||||
};
|
||||
|
||||
}
|
39
src/packet_analysis/protocol/ip/SessionAdapter.cc
Normal file
39
src/packet_analysis/protocol/ip/SessionAdapter.cc
Normal 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));
|
||||
}
|
||||
}
|
102
src/packet_analysis/protocol/ip/SessionAdapter.h
Normal file
102
src/packet_analysis/protocol/ip/SessionAdapter.h
Normal 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
|
|
@ -4,10 +4,10 @@
|
|||
|
||||
#include <pcap.h> // For DLT_ constants
|
||||
|
||||
#include "zeek/session/Manager.h"
|
||||
#include "zeek/RunState.h"
|
||||
#include "zeek/IP.h"
|
||||
#include "zeek/TunnelEncapsulation.h"
|
||||
#include "zeek/packet_analysis/protocol/ip/IP.h"
|
||||
|
||||
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;
|
||||
int gre_link_type = packet->gre_link_type;
|
||||
|
||||
IP_Hdr* inner = nullptr;
|
||||
std::unique_ptr<IP_Hdr> inner = nullptr;
|
||||
|
||||
if ( gre_version != 0 )
|
||||
{
|
||||
// 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 )
|
||||
Weird("invalid_inner_IP_version", packet);
|
||||
else if ( result < 0 )
|
||||
|
@ -59,10 +59,7 @@ bool IPTunnelAnalyzer::AnalyzePacket(size_t len, const uint8_t* data, Packet* pa
|
|||
Weird("inner_IP_payload_length_mismatch", packet);
|
||||
|
||||
if ( result != 0 )
|
||||
{
|
||||
delete inner;
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
// Look up to see if we've already seen this IP tunnel, identified
|
||||
|
@ -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.
|
||||
*/
|
||||
bool IPTunnelAnalyzer::ProcessEncapsulatedPacket(double t, const Packet* pkt,
|
||||
const IP_Hdr* inner,
|
||||
const std::unique_ptr<IP_Hdr>& inner,
|
||||
std::shared_ptr<EncapsulationStack> prev,
|
||||
const EncapsulatingConn& ec)
|
||||
{
|
||||
|
@ -138,8 +135,6 @@ bool IPTunnelAnalyzer::ProcessEncapsulatedPacket(double t, const Packet* pkt,
|
|||
// Forward the packet back to the IP analyzer.
|
||||
bool return_val = ForwardPacket(len, data, &p);
|
||||
|
||||
delete inner;
|
||||
|
||||
return return_val;
|
||||
}
|
||||
|
||||
|
|
|
@ -40,7 +40,7 @@ public:
|
|||
* @param ec The most-recently found depth of encapsulation.
|
||||
*/
|
||||
bool ProcessEncapsulatedPacket(double t, const Packet *pkt,
|
||||
const IP_Hdr* inner,
|
||||
const std::unique_ptr<IP_Hdr>& inner,
|
||||
std::shared_ptr<EncapsulationStack> prev,
|
||||
const EncapsulatingConn& ec);
|
||||
|
||||
|
|
8
src/packet_analysis/protocol/tcp/CMakeLists.txt
Normal file
8
src/packet_analysis/protocol/tcp/CMakeLists.txt
Normal 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()
|
24
src/packet_analysis/protocol/tcp/Plugin.cc
Normal file
24
src/packet_analysis/protocol/tcp/Plugin.cc
Normal 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;
|
||||
|
||||
}
|
76
src/packet_analysis/protocol/tcp/TCP.cc
Normal file
76
src/packet_analysis/protocol/tcp/TCP.cc
Normal 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;
|
||||
}
|
54
src/packet_analysis/protocol/tcp/TCP.h
Normal file
54
src/packet_analysis/protocol/tcp/TCP.h
Normal 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;
|
||||
};
|
||||
|
||||
}
|
26
src/packet_analysis/protocol/udp/Plugin.cc
Normal file
26
src/packet_analysis/protocol/udp/Plugin.cc
Normal 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;
|
||||
|
||||
}
|
338
src/packet_analysis/protocol/udp/UDP.cc
Normal file
338
src/packet_analysis/protocol/udp/UDP.cc
Normal 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);
|
||||
}
|
100
src/packet_analysis/protocol/udp/UDP.h
Normal file
100
src/packet_analysis/protocol/udp/UDP.h
Normal 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;
|
||||
};
|
||||
|
||||
}
|
|
@ -4,7 +4,8 @@
|
|||
|
||||
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);
|
||||
|
||||
|
@ -63,6 +64,8 @@ bool Key::operator<(const Key& rhs) const
|
|||
{
|
||||
if ( size != rhs.size )
|
||||
return size < rhs.size;
|
||||
else if ( type != rhs.type )
|
||||
return type < rhs.type;
|
||||
|
||||
return memcmp(data, rhs.data, size) < 0;
|
||||
}
|
||||
|
|
|
@ -20,16 +20,22 @@ namespace zeek::session::detail {
|
|||
class Key final {
|
||||
public:
|
||||
|
||||
const static size_t CONNECTION_KEY_TYPE=0;
|
||||
|
||||
/**
|
||||
* Create a new session key from a data pointer.
|
||||
*
|
||||
* @param session A pointer to the data for the key.
|
||||
* @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
|
||||
* 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.
|
||||
*/
|
||||
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();
|
||||
|
||||
|
@ -55,6 +61,7 @@ public:
|
|||
private:
|
||||
const uint8_t* data = nullptr;
|
||||
size_t size = 0;
|
||||
size_t type = CONNECTION_KEY_TYPE;
|
||||
bool copied = false;
|
||||
};
|
||||
|
||||
|
|
|
@ -21,9 +21,6 @@
|
|||
#include "zeek/session/Session.h"
|
||||
#include "zeek/TunnelEncapsulation.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/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)
|
||||
{
|
||||
const auto& vt = v->GetType();
|
||||
|
@ -380,14 +149,19 @@ Connection* Manager::FindConnection(Val* v)
|
|||
htons((unsigned short) resp_portv->Port()),
|
||||
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);
|
||||
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)
|
||||
|
@ -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;
|
||||
detail::Key key = s->SessionKey(true);
|
||||
|
||||
auto it = session_map.find(key);
|
||||
if ( it != session_map.end() )
|
||||
old = it->second;
|
||||
if ( remove_existing )
|
||||
{
|
||||
auto it = session_map.find(key);
|
||||
if ( it != session_map.end() )
|
||||
old = it->second;
|
||||
|
||||
session_map.erase(key);
|
||||
}
|
||||
|
||||
session_map.erase(key);
|
||||
InsertSession(std::move(key), s);
|
||||
|
||||
if ( old && old != s )
|
||||
|
@ -482,140 +260,6 @@ void Manager::GetStats(Stats& s)
|
|||
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)
|
||||
{
|
||||
const char* weird_name = name;
|
||||
|
|
|
@ -60,14 +60,13 @@ public:
|
|||
/**
|
||||
* Looks up the connection referred to by a given key.
|
||||
*
|
||||
* @param key The key for the connection to search for.
|
||||
* @param proto The transport protocol for the connection.
|
||||
* @param conn_key The key for the connection to search for.
|
||||
* @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 Insert(Session* c);
|
||||
void Insert(Session* c, bool remove_existing=true);
|
||||
|
||||
// Generating connection_pending events for all connections
|
||||
// that are still active.
|
||||
|
@ -94,43 +93,6 @@ public:
|
|||
[[deprecated("Remove in v5.1. Use 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 SessionMemoryUsageVals();
|
||||
|
||||
|
@ -148,32 +110,6 @@ private:
|
|||
|
||||
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
|
||||
// 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
|
||||
|
|
|
@ -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
|
||||
#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
|
||||
XXXXXXXXXX.XXXXXX - 10.0.0.1 0 192.0.43.10 0 internally_truncated_header - F zeek -
|
||||
XXXXXXXXXX.XXXXXX - 192.0.43.10 0 10.0.0.1 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 ICMP
|
||||
#close XXXX-XX-XX-XX-XX-XX
|
||||
#separator \x09
|
||||
#set_separator ,
|
||||
|
|
|
@ -57,6 +57,12 @@ scripts/base/init-bare.zeek
|
|||
scripts/base/packet-protocols/iptunnel/main.zeek
|
||||
scripts/base/packet-protocols/vntag/__load__.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/frameworks/logging/__load__.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_HTTP.events.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_IMAP.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.functions.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_XMPP.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_FileExtract.events.bif.zeek
|
||||
build/scripts/base/bif/plugins/Zeek_FileExtract.functions.bif.zeek
|
||||
|
|
|
@ -57,6 +57,12 @@ scripts/base/init-bare.zeek
|
|||
scripts/base/packet-protocols/iptunnel/main.zeek
|
||||
scripts/base/packet-protocols/vntag/__load__.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/frameworks/logging/__load__.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_HTTP.events.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_IMAP.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.functions.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_XMPP.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_FileExtract.events.bif.zeek
|
||||
build/scripts/base/bif/plugins/Zeek_FileExtract.functions.bif.zeek
|
||||
|
|
|
@ -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, 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_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, 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, 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, 2054, 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_hrw, <...>/hash_hrw.zeek) -> -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_radio, <...>/ieee802_11_radio) -> -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.bif, <...>/supervisor.bif.zeek) -> -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<...>/time, <...>/time.zeek) -> -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<...>/udp, <...>/udp) -> -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<...>/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, 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_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, 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, 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, 2054, 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_hrw, <...>/hash_hrw.zeek)
|
||||
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_radio, <...>/ieee802_11_radio)
|
||||
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.bif, <...>/supervisor.bif.zeek)
|
||||
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<...>/time, <...>/time.zeek)
|
||||
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<...>/udp, <...>/udp)
|
||||
0.000000 MetaHookPre LoadFile(0, base<...>/urls, <...>/urls.zeek)
|
||||
0.000000 MetaHookPre LoadFile(0, base<...>/utils, <...>/utils.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, 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_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, 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, 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, 2054, 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_hrw <...>/hash_hrw.zeek
|
||||
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_radio <...>/ieee802_11_radio
|
||||
0.000000 | HookLoadFile base<...>/imap <...>/imap
|
||||
|
@ -3010,10 +3029,12 @@
|
|||
0.000000 | HookLoadFile base<...>/supervisor <...>/supervisor
|
||||
0.000000 | HookLoadFile base<...>/supervisor.bif <...>/supervisor.bif.zeek
|
||||
0.000000 | HookLoadFile base<...>/syslog <...>/syslog
|
||||
0.000000 | HookLoadFile base<...>/tcp <...>/tcp
|
||||
0.000000 | HookLoadFile base<...>/thresholds <...>/thresholds.zeek
|
||||
0.000000 | HookLoadFile base<...>/time <...>/time.zeek
|
||||
0.000000 | HookLoadFile base<...>/tunnels <...>/tunnels
|
||||
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<...>/utils <...>/utils.zeek
|
||||
0.000000 | HookLoadFile base<...>/version <...>/version.zeek
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue