mirror of
https://github.com/zeek/zeek.git
synced 2025-10-06 00:28:21 +00:00
Add new Session base class
This is mostly code copied from the existing Connection class, as that class now inherits from Session.
This commit is contained in:
parent
c752d76052
commit
8fbab9408a
8 changed files with 618 additions and 319 deletions
|
@ -286,6 +286,7 @@ set(MAIN_SRCS
|
||||||
Scope.cc
|
Scope.cc
|
||||||
ScriptCoverageManager.cc
|
ScriptCoverageManager.cc
|
||||||
SerializationFormat.cc
|
SerializationFormat.cc
|
||||||
|
Session.cc
|
||||||
Sessions.cc
|
Sessions.cc
|
||||||
SmithWaterman.cc
|
SmithWaterman.cc
|
||||||
Stats.cc
|
Stats.cc
|
||||||
|
|
186
src/Conn.cc
186
src/Conn.cc
|
@ -21,53 +21,18 @@
|
||||||
#include "zeek/iosource/IOSource.h"
|
#include "zeek/iosource/IOSource.h"
|
||||||
|
|
||||||
namespace zeek {
|
namespace zeek {
|
||||||
namespace detail {
|
|
||||||
|
|
||||||
void ConnectionTimer::Init(Connection* arg_conn, timer_func arg_timer,
|
|
||||||
bool arg_do_expire)
|
|
||||||
{
|
|
||||||
conn = arg_conn;
|
|
||||||
timer = arg_timer;
|
|
||||||
do_expire = arg_do_expire;
|
|
||||||
Ref(conn);
|
|
||||||
}
|
|
||||||
|
|
||||||
ConnectionTimer::~ConnectionTimer()
|
|
||||||
{
|
|
||||||
if ( conn->RefCnt() < 1 )
|
|
||||||
reporter->InternalError("reference count inconsistency in ~ConnectionTimer");
|
|
||||||
|
|
||||||
conn->RemoveTimer(this);
|
|
||||||
Unref(conn);
|
|
||||||
}
|
|
||||||
|
|
||||||
void ConnectionTimer::Dispatch(double t, bool is_expire)
|
|
||||||
{
|
|
||||||
if ( is_expire && ! do_expire )
|
|
||||||
return;
|
|
||||||
|
|
||||||
// Remove ourselves from the connection's set of timers so
|
|
||||||
// it doesn't try to cancel us.
|
|
||||||
conn->RemoveTimer(this);
|
|
||||||
|
|
||||||
(conn->*timer)(t);
|
|
||||||
|
|
||||||
if ( conn->RefCnt() < 1 )
|
|
||||||
reporter->InternalError("reference count inconsistency in ConnectionTimer::Dispatch");
|
|
||||||
}
|
|
||||||
|
|
||||||
} // namespace detail
|
|
||||||
|
|
||||||
uint64_t Connection::total_connections = 0;
|
uint64_t Connection::total_connections = 0;
|
||||||
uint64_t Connection::current_connections = 0;
|
uint64_t Connection::current_connections = 0;
|
||||||
|
|
||||||
Connection::Connection(NetSessions* s, const detail::ConnIDKey& k, double t,
|
Connection::Connection(NetSessions* s, const detail::ConnIDKey& k, double t,
|
||||||
const ConnID* id, uint32_t flow, const Packet* pkt)
|
const ConnID* id, uint32_t flow, const Packet* pkt)
|
||||||
|
: Session(t, connection_timeout, connection_status_update,
|
||||||
|
detail::connection_status_update_interval)
|
||||||
{
|
{
|
||||||
sessions = s;
|
sessions = s;
|
||||||
key = k;
|
key = k;
|
||||||
key_valid = true;
|
key_valid = true;
|
||||||
start_time = last_time = t;
|
|
||||||
|
|
||||||
orig_addr = id->src_addr;
|
orig_addr = id->src_addr;
|
||||||
resp_addr = id->dst_addr;
|
resp_addr = id->dst_addr;
|
||||||
|
@ -92,19 +57,11 @@ Connection::Connection(NetSessions* s, const detail::ConnIDKey& k, double t,
|
||||||
vlan = pkt->vlan;
|
vlan = pkt->vlan;
|
||||||
inner_vlan = pkt->inner_vlan;
|
inner_vlan = pkt->inner_vlan;
|
||||||
|
|
||||||
is_active = 1;
|
|
||||||
skip = 0;
|
skip = 0;
|
||||||
weird = 0;
|
weird = 0;
|
||||||
|
|
||||||
suppress_event = 0;
|
suppress_event = 0;
|
||||||
|
|
||||||
record_contents = record_packets = 1;
|
|
||||||
record_current_packet = record_current_content = 0;
|
|
||||||
|
|
||||||
timers_canceled = 0;
|
|
||||||
inactivity_timeout = 0;
|
|
||||||
installed_status_timer = 0;
|
|
||||||
|
|
||||||
finished = 0;
|
finished = 0;
|
||||||
|
|
||||||
hist_seen = 0;
|
hist_seen = 0;
|
||||||
|
@ -217,12 +174,6 @@ void Connection::NextPacket(double t, bool is_orig,
|
||||||
run_state::current_pkt = nullptr;
|
run_state::current_pkt = nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
void Connection::SetLifetime(double lifetime)
|
|
||||||
{
|
|
||||||
ADD_TIMER(&Connection::DeleteTimer, run_state::network_time + lifetime, 0,
|
|
||||||
detail::TIMER_CONN_DELETE);
|
|
||||||
}
|
|
||||||
|
|
||||||
bool Connection::IsReuse(double t, const u_char* pkt)
|
bool Connection::IsReuse(double t, const u_char* pkt)
|
||||||
{
|
{
|
||||||
return root_analyzer && root_analyzer->IsReuse(t, pkt);
|
return root_analyzer && root_analyzer->IsReuse(t, pkt);
|
||||||
|
@ -271,76 +222,6 @@ void Connection::HistoryThresholdEvent(EventHandlerPtr e, bool is_orig,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Connection::DeleteTimer(double /* t */)
|
|
||||||
{
|
|
||||||
if ( is_active )
|
|
||||||
Event(connection_timeout, nullptr);
|
|
||||||
|
|
||||||
sessions->Remove(this);
|
|
||||||
}
|
|
||||||
|
|
||||||
void Connection::InactivityTimer(double t)
|
|
||||||
{
|
|
||||||
if ( last_time + inactivity_timeout <= t )
|
|
||||||
{
|
|
||||||
Event(connection_timeout, nullptr);
|
|
||||||
sessions->Remove(this);
|
|
||||||
++detail::killed_by_inactivity;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
ADD_TIMER(&Connection::InactivityTimer,
|
|
||||||
last_time + inactivity_timeout, 0,
|
|
||||||
detail::TIMER_CONN_INACTIVITY);
|
|
||||||
}
|
|
||||||
|
|
||||||
void Connection::RemoveConnectionTimer(double t)
|
|
||||||
{
|
|
||||||
RemovalEvent();
|
|
||||||
sessions->Remove(this);
|
|
||||||
}
|
|
||||||
|
|
||||||
void Connection::SetInactivityTimeout(double timeout)
|
|
||||||
{
|
|
||||||
if ( timeout == inactivity_timeout )
|
|
||||||
return;
|
|
||||||
|
|
||||||
// First cancel and remove any existing inactivity timer.
|
|
||||||
for ( const auto& timer : timers )
|
|
||||||
if ( timer->Type() == detail::TIMER_CONN_INACTIVITY )
|
|
||||||
{
|
|
||||||
detail::timer_mgr->Cancel(timer);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
if ( timeout )
|
|
||||||
ADD_TIMER(&Connection::InactivityTimer,
|
|
||||||
last_time + timeout, 0, detail::TIMER_CONN_INACTIVITY);
|
|
||||||
|
|
||||||
inactivity_timeout = timeout;
|
|
||||||
}
|
|
||||||
|
|
||||||
void Connection::EnableStatusUpdateTimer()
|
|
||||||
{
|
|
||||||
if ( installed_status_timer )
|
|
||||||
return;
|
|
||||||
|
|
||||||
if ( connection_status_update && zeek::detail::connection_status_update_interval )
|
|
||||||
{
|
|
||||||
ADD_TIMER(&Connection::StatusUpdateTimer,
|
|
||||||
run_state::network_time + detail::connection_status_update_interval, 0,
|
|
||||||
detail::TIMER_CONN_STATUS_UPDATE);
|
|
||||||
installed_status_timer = 1;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void Connection::StatusUpdateTimer(double t)
|
|
||||||
{
|
|
||||||
EnqueueEvent(connection_status_update, nullptr, ConnVal());
|
|
||||||
ADD_TIMER(&Connection::StatusUpdateTimer,
|
|
||||||
run_state::network_time + detail::connection_status_update_interval, 0,
|
|
||||||
detail::TIMER_CONN_STATUS_UPDATE);
|
|
||||||
}
|
|
||||||
|
|
||||||
const RecordValPtr& Connection::ConnVal()
|
const RecordValPtr& Connection::ConnVal()
|
||||||
{
|
{
|
||||||
if ( ! conn_val )
|
if ( ! conn_val )
|
||||||
|
@ -460,68 +341,12 @@ void Connection::RemovalEvent()
|
||||||
EnqueueEvent(connection_state_remove, nullptr, ConnVal());
|
EnqueueEvent(connection_state_remove, nullptr, ConnVal());
|
||||||
}
|
}
|
||||||
|
|
||||||
void Connection::Event(EventHandlerPtr f, analyzer::Analyzer* analyzer, const char* name)
|
|
||||||
{
|
|
||||||
if ( ! f )
|
|
||||||
return;
|
|
||||||
|
|
||||||
if ( name )
|
|
||||||
EnqueueEvent(f, analyzer, make_intrusive<StringVal>(name), ConnVal());
|
|
||||||
else
|
|
||||||
EnqueueEvent(f, analyzer, ConnVal());
|
|
||||||
}
|
|
||||||
|
|
||||||
void Connection::EnqueueEvent(EventHandlerPtr f, analyzer::Analyzer* a,
|
|
||||||
Args args)
|
|
||||||
{
|
|
||||||
// "this" is passed as a cookie for the event
|
|
||||||
event_mgr.Enqueue(f, std::move(args), util::detail::SOURCE_LOCAL, a ? a->GetID() : 0, this);
|
|
||||||
}
|
|
||||||
|
|
||||||
void Connection::Weird(const char* name, const char* addl, const char* source)
|
void Connection::Weird(const char* name, const char* addl, const char* source)
|
||||||
{
|
{
|
||||||
weird = 1;
|
weird = 1;
|
||||||
reporter->Weird(this, name, addl ? addl : "", source ? source : "");
|
reporter->Weird(this, name, addl ? addl : "", source ? source : "");
|
||||||
}
|
}
|
||||||
|
|
||||||
void Connection::AddTimer(timer_func timer, double t, bool do_expire,
|
|
||||||
detail::TimerType type)
|
|
||||||
{
|
|
||||||
if ( timers_canceled )
|
|
||||||
return;
|
|
||||||
|
|
||||||
// If the key is cleared, the connection isn't stored in the connection
|
|
||||||
// table anymore and will soon be deleted. We're not installing new
|
|
||||||
// timers anymore then.
|
|
||||||
if ( ! key_valid )
|
|
||||||
return;
|
|
||||||
|
|
||||||
detail::Timer* conn_timer = new detail::ConnectionTimer(this, timer, t, do_expire, type);
|
|
||||||
detail::timer_mgr->Add(conn_timer);
|
|
||||||
timers.push_back(conn_timer);
|
|
||||||
}
|
|
||||||
|
|
||||||
void Connection::RemoveTimer(detail::Timer* t)
|
|
||||||
{
|
|
||||||
timers.remove(t);
|
|
||||||
}
|
|
||||||
|
|
||||||
void Connection::CancelTimers()
|
|
||||||
{
|
|
||||||
// We are going to cancel our timers which, in turn, may cause them to
|
|
||||||
// call RemoveTimer(), which would then modify the list we're just
|
|
||||||
// traversing. Thus, we first make a copy of the list which we then
|
|
||||||
// iterate through.
|
|
||||||
TimerPList tmp(timers.length());
|
|
||||||
std::copy(timers.begin(), timers.end(), std::back_inserter(tmp));
|
|
||||||
|
|
||||||
for ( const auto& timer : tmp )
|
|
||||||
detail::timer_mgr->Cancel(timer);
|
|
||||||
|
|
||||||
timers_canceled = 1;
|
|
||||||
timers.clear();
|
|
||||||
}
|
|
||||||
|
|
||||||
void Connection::FlipRoles()
|
void Connection::FlipRoles()
|
||||||
{
|
{
|
||||||
IPAddr tmp_addr = resp_addr;
|
IPAddr tmp_addr = resp_addr;
|
||||||
|
@ -558,7 +383,7 @@ void Connection::FlipRoles()
|
||||||
|
|
||||||
unsigned int Connection::MemoryAllocation() const
|
unsigned int Connection::MemoryAllocation() const
|
||||||
{
|
{
|
||||||
return padded_sizeof(*this)
|
return Session::MemoryAllocation() + padded_sizeof(*this)
|
||||||
+ (timers.MemoryAllocation() - padded_sizeof(timers))
|
+ (timers.MemoryAllocation() - padded_sizeof(timers))
|
||||||
+ (conn_val ? conn_val->MemoryAllocation() : 0)
|
+ (conn_val ? conn_val->MemoryAllocation() : 0)
|
||||||
+ (root_analyzer ? root_analyzer->MemoryAllocation(): 0)
|
+ (root_analyzer ? root_analyzer->MemoryAllocation(): 0)
|
||||||
|
@ -573,10 +398,7 @@ unsigned int Connection::MemoryAllocationConnVal() const
|
||||||
|
|
||||||
void Connection::Describe(ODesc* d) const
|
void Connection::Describe(ODesc* d) const
|
||||||
{
|
{
|
||||||
d->Add(start_time);
|
Session::Describe(d);
|
||||||
d->Add("(");
|
|
||||||
d->Add(last_time);
|
|
||||||
d->AddSP(")");
|
|
||||||
|
|
||||||
switch ( proto ) {
|
switch ( proto ) {
|
||||||
case TRANSPORT_TCP:
|
case TRANSPORT_TCP:
|
||||||
|
|
171
src/Conn.h
171
src/Conn.h
|
@ -16,6 +16,7 @@
|
||||||
#include "zeek/WeirdState.h"
|
#include "zeek/WeirdState.h"
|
||||||
#include "zeek/ZeekArgs.h"
|
#include "zeek/ZeekArgs.h"
|
||||||
#include "zeek/IntrusivePtr.h"
|
#include "zeek/IntrusivePtr.h"
|
||||||
|
#include "zeek/Session.h"
|
||||||
#include "zeek/iosource/Packet.h"
|
#include "zeek/iosource/Packet.h"
|
||||||
|
|
||||||
#include "zeek/analyzer/Tag.h"
|
#include "zeek/analyzer/Tag.h"
|
||||||
|
@ -34,7 +35,6 @@ using RecordValPtr = IntrusivePtr<RecordVal>;
|
||||||
|
|
||||||
namespace detail {
|
namespace detail {
|
||||||
|
|
||||||
class ConnectionTimer;
|
|
||||||
class Specific_RE_Matcher;
|
class Specific_RE_Matcher;
|
||||||
class RuleEndpointState;
|
class RuleEndpointState;
|
||||||
class RuleHdrTest;
|
class RuleHdrTest;
|
||||||
|
@ -55,8 +55,6 @@ enum ConnEventToFlag {
|
||||||
NUM_EVENTS_TO_FLAG,
|
NUM_EVENTS_TO_FLAG,
|
||||||
};
|
};
|
||||||
|
|
||||||
typedef void (Connection::*timer_func)(double t);
|
|
||||||
|
|
||||||
struct ConnID {
|
struct ConnID {
|
||||||
IPAddr src_addr;
|
IPAddr src_addr;
|
||||||
IPAddr dst_addr;
|
IPAddr dst_addr;
|
||||||
|
@ -71,25 +69,29 @@ static inline int addr_port_canon_lt(const IPAddr& addr1, uint32_t p1,
|
||||||
return addr1 < addr2 || (addr1 == addr2 && p1 < p2);
|
return addr1 < addr2 || (addr1 == addr2 && p1 < p2);
|
||||||
}
|
}
|
||||||
|
|
||||||
class Connection final : public Obj {
|
class Connection final : public Session {
|
||||||
public:
|
public:
|
||||||
|
|
||||||
Connection(NetSessions* s, const detail::ConnIDKey& k, double t, const ConnID* id,
|
Connection(NetSessions* s, const detail::ConnIDKey& k, double t, const ConnID* id,
|
||||||
uint32_t flow, const Packet* pkt);
|
uint32_t flow, const Packet* pkt);
|
||||||
~Connection() override;
|
~Connection() override;
|
||||||
|
|
||||||
// Invoked when an encapsulation is discovered. It records the
|
/**
|
||||||
// encapsulation with the connection and raises a "tunnel_changed"
|
* Invoked when an encapsulation is discovered. It records the encapsulation
|
||||||
// event if it's different from the previous encapsulation (or the
|
* with the connection and raises a "tunnel_changed" event if it's different
|
||||||
// first encountered). encap can be null to indicate no
|
* from the previous encapsulation or if it's the first one encountered.
|
||||||
// encapsulation.
|
*
|
||||||
|
* @param encap The new encapsulation. Can be set to null to indicated no
|
||||||
|
* encapsulation or clear an old one.
|
||||||
|
*/
|
||||||
void CheckEncapsulation(const std::shared_ptr<EncapsulationStack>& encap);
|
void CheckEncapsulation(const std::shared_ptr<EncapsulationStack>& encap);
|
||||||
|
|
||||||
// Invoked when connection is about to be removed. Use Ref(this)
|
/**
|
||||||
// inside Done to keep the connection object around (though it'll
|
* Invoked when the session is about to be removed. Use Ref(this)
|
||||||
// no longer be accessible from the dictionary of active
|
* inside Done to keep the session object around, though it'll
|
||||||
// connections).
|
* no longer be accessible from the SessionManager.
|
||||||
void Done();
|
*/
|
||||||
|
void Done() override;
|
||||||
|
|
||||||
// Process the connection's next packet. "data" points just
|
// Process the connection's next packet. "data" points just
|
||||||
// beyond the IP header. It's updated to point just beyond
|
// beyond the IP header. It's updated to point just beyond
|
||||||
|
@ -111,13 +113,10 @@ public:
|
||||||
// connection is in the session map. If it is removed, the key
|
// connection is in the session map. If it is removed, the key
|
||||||
// should be marked invalid.
|
// should be marked invalid.
|
||||||
const detail::ConnIDKey& Key() const { return key; }
|
const detail::ConnIDKey& Key() const { return key; }
|
||||||
void ClearKey() { key_valid = false; }
|
detail::SessionKey SessionKey(bool copy) const override
|
||||||
bool IsKeyValid() const { return key_valid; }
|
{ return detail::SessionKey{&key, sizeof(key), copy}; }
|
||||||
|
void ClearKey() override { key_valid = false; }
|
||||||
double StartTime() const { return start_time; }
|
bool IsKeyValid() const override { return key_valid; }
|
||||||
void SetStartTime(double t) { start_time = t; }
|
|
||||||
double LastTime() const { return last_time; }
|
|
||||||
void SetLastTime(double t) { last_time = t; }
|
|
||||||
|
|
||||||
const IPAddr& OrigAddr() const { return orig_addr; }
|
const IPAddr& OrigAddr() const { return orig_addr; }
|
||||||
const IPAddr& RespAddr() const { return resp_addr; }
|
const IPAddr& RespAddr() const { return resp_addr; }
|
||||||
|
@ -133,23 +132,6 @@ public:
|
||||||
|
|
||||||
TransportProto ConnTransport() const { return proto; }
|
TransportProto ConnTransport() const { return proto; }
|
||||||
|
|
||||||
// True if we should record subsequent packets (either headers or
|
|
||||||
// in their entirety, depending on record_contents). We still
|
|
||||||
// record subsequent SYN/FIN/RST, regardless of how this is set.
|
|
||||||
bool RecordPackets() const { return record_packets; }
|
|
||||||
void SetRecordPackets(bool do_record) { record_packets = do_record ? 1 : 0; }
|
|
||||||
|
|
||||||
// True if we should record full packets for this connection,
|
|
||||||
// false if we should just record headers.
|
|
||||||
bool RecordContents() const { return record_contents; }
|
|
||||||
void SetRecordContents(bool do_record) { record_contents = do_record ? 1 : 0; }
|
|
||||||
|
|
||||||
// Set whether to record *current* packet header/full.
|
|
||||||
void SetRecordCurrentPacket(bool do_record)
|
|
||||||
{ record_current_packet = do_record ? 1 : 0; }
|
|
||||||
void SetRecordCurrentContent(bool do_record)
|
|
||||||
{ record_current_content = do_record ? 1 : 0; }
|
|
||||||
|
|
||||||
// FIXME: Now this is in Analyzer and should eventually be removed here.
|
// FIXME: Now this is in Analyzer and should eventually be removed here.
|
||||||
//
|
//
|
||||||
// If true, skip processing of remainder of connection. Note
|
// If true, skip processing of remainder of connection. Note
|
||||||
|
@ -158,26 +140,19 @@ public:
|
||||||
void SetSkip(bool do_skip) { skip = do_skip ? 1 : 0; }
|
void SetSkip(bool do_skip) { skip = do_skip ? 1 : 0; }
|
||||||
bool Skipping() const { return skip; }
|
bool Skipping() const { return skip; }
|
||||||
|
|
||||||
// Arrange for the connection to expire after the given amount of time.
|
|
||||||
void SetLifetime(double lifetime);
|
|
||||||
|
|
||||||
// Returns true if the packet reflects a reuse of this
|
// Returns true if the packet reflects a reuse of this
|
||||||
// connection (i.e., not a continuation but the beginning of
|
// connection (i.e., not a continuation but the beginning of
|
||||||
// a new connection).
|
// a new connection).
|
||||||
bool IsReuse(double t, const u_char* pkt);
|
bool IsReuse(double t, const u_char* pkt);
|
||||||
|
|
||||||
// Get/set the inactivity timeout for this connection.
|
|
||||||
void SetInactivityTimeout(double timeout);
|
|
||||||
double InactivityTimeout() const { return inactivity_timeout; }
|
|
||||||
|
|
||||||
// Activate connection_status_update timer.
|
|
||||||
void EnableStatusUpdateTimer();
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns the associated "connection" record.
|
* Returns the associated "connection" record.
|
||||||
*/
|
*/
|
||||||
const RecordValPtr& ConnVal();
|
const RecordValPtr& ConnVal() override;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Append additional entries to the history field in the connection record.
|
||||||
|
*/
|
||||||
void AppendAddl(const char* str);
|
void AppendAddl(const char* str);
|
||||||
|
|
||||||
void Match(detail::Rule::PatternType type, const u_char* data, int len,
|
void Match(detail::Rule::PatternType type, const u_char* data, int len,
|
||||||
|
@ -186,36 +161,11 @@ public:
|
||||||
/**
|
/**
|
||||||
* Generates connection removal event(s).
|
* Generates connection removal event(s).
|
||||||
*/
|
*/
|
||||||
void RemovalEvent();
|
void RemovalEvent() override;
|
||||||
|
|
||||||
// If a handler exists for 'f', an event will be generated. If 'name' is
|
|
||||||
// given that event's first argument will be it, and it's second will be
|
|
||||||
// the connection value. If 'name' is null, then the event's first
|
|
||||||
// argument is the connection value.
|
|
||||||
void Event(EventHandlerPtr f, analyzer::Analyzer* analyzer, const char* name = nullptr);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Enqueues an event associated with this connection and given analyzer.
|
|
||||||
*/
|
|
||||||
void EnqueueEvent(EventHandlerPtr f, analyzer::Analyzer* analyzer,
|
|
||||||
Args args);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* A version of EnqueueEvent() taking a variable number of arguments.
|
|
||||||
*/
|
|
||||||
template <class... Args>
|
|
||||||
std::enable_if_t<
|
|
||||||
std::is_convertible_v<
|
|
||||||
std::tuple_element_t<0, std::tuple<Args...>>, ValPtr>>
|
|
||||||
EnqueueEvent(EventHandlerPtr h, analyzer::Analyzer* analyzer, Args&&... args)
|
|
||||||
{ return EnqueueEvent(h, analyzer, zeek::Args{std::forward<Args>(args)...}); }
|
|
||||||
|
|
||||||
void Weird(const char* name, const char* addl = "", const char* source = "");
|
void Weird(const char* name, const char* addl = "", const char* source = "");
|
||||||
bool DidWeird() const { return weird != 0; }
|
bool DidWeird() const { return weird != 0; }
|
||||||
|
|
||||||
// Cancel all associated timers.
|
|
||||||
void CancelTimers();
|
|
||||||
|
|
||||||
inline bool FlagEvent(ConnEventToFlag e)
|
inline bool FlagEvent(ConnEventToFlag e)
|
||||||
{
|
{
|
||||||
if ( e >= 0 && e < NUM_EVENTS_TO_FLAG )
|
if ( e >= 0 && e < NUM_EVENTS_TO_FLAG )
|
||||||
|
@ -234,8 +184,8 @@ public:
|
||||||
// Statistics.
|
// Statistics.
|
||||||
|
|
||||||
// Just a lower bound.
|
// Just a lower bound.
|
||||||
unsigned int MemoryAllocation() const;
|
unsigned int MemoryAllocation() const override;
|
||||||
unsigned int MemoryAllocationConnVal() const;
|
unsigned int MemoryAllocationConnVal() const override;
|
||||||
|
|
||||||
static uint64_t TotalConnections()
|
static uint64_t TotalConnections()
|
||||||
{ return total_connections; }
|
{ return total_connections; }
|
||||||
|
@ -268,8 +218,6 @@ public:
|
||||||
|
|
||||||
void AddHistory(char code) { history += code; }
|
void AddHistory(char code) { history += code; }
|
||||||
|
|
||||||
void DeleteTimer(double t);
|
|
||||||
|
|
||||||
// Sets the root of the analyzer tree as well as the primary PIA.
|
// Sets the root of the analyzer tree as well as the primary PIA.
|
||||||
void SetRootAnalyzer(analyzer::TransportLayerAnalyzer* analyzer, analyzer::pia::PIA* pia);
|
void SetRootAnalyzer(analyzer::TransportLayerAnalyzer* analyzer, analyzer::pia::PIA* pia);
|
||||||
analyzer::TransportLayerAnalyzer* GetRootAnalyzer() { return root_analyzer; }
|
analyzer::TransportLayerAnalyzer* GetRootAnalyzer() { return root_analyzer; }
|
||||||
|
@ -295,26 +243,10 @@ public:
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
|
|
||||||
// Add the given timer to expire at time t. If do_expire
|
|
||||||
// is true, then the timer is also evaluated when Bro terminates,
|
|
||||||
// otherwise not.
|
|
||||||
void AddTimer(timer_func timer, double t, bool do_expire,
|
|
||||||
detail::TimerType type);
|
|
||||||
|
|
||||||
void RemoveTimer(detail::Timer* t);
|
|
||||||
|
|
||||||
// Allow other classes to access pointers to these:
|
// Allow other classes to access pointers to these:
|
||||||
friend class detail::ConnectionTimer;
|
friend class detail::SessionTimer;
|
||||||
|
|
||||||
void InactivityTimer(double t);
|
|
||||||
void StatusUpdateTimer(double t);
|
|
||||||
void RemoveConnectionTimer(double t);
|
|
||||||
|
|
||||||
NetSessions* sessions;
|
NetSessions* sessions;
|
||||||
detail::ConnIDKey key;
|
|
||||||
bool key_valid;
|
|
||||||
|
|
||||||
TimerPList timers;
|
|
||||||
|
|
||||||
IPAddr orig_addr;
|
IPAddr orig_addr;
|
||||||
IPAddr resp_addr;
|
IPAddr resp_addr;
|
||||||
|
@ -324,59 +256,30 @@ protected:
|
||||||
uint32_t vlan, inner_vlan; // VLAN this connection traverses, if available
|
uint32_t vlan, inner_vlan; // VLAN this connection traverses, if available
|
||||||
u_char orig_l2_addr[Packet::L2_ADDR_LEN]; // Link-layer originator address, if available
|
u_char orig_l2_addr[Packet::L2_ADDR_LEN]; // Link-layer originator address, if available
|
||||||
u_char resp_l2_addr[Packet::L2_ADDR_LEN]; // Link-layer responder address, if available
|
u_char resp_l2_addr[Packet::L2_ADDR_LEN]; // Link-layer responder address, if available
|
||||||
double start_time, last_time;
|
int suppress_event; // suppress certain events to once per conn.
|
||||||
double inactivity_timeout;
|
|
||||||
RecordValPtr conn_val;
|
RecordValPtr conn_val;
|
||||||
std::shared_ptr<EncapsulationStack> encapsulation; // tunnels
|
std::shared_ptr<EncapsulationStack> encapsulation; // tunnels
|
||||||
int suppress_event; // suppress certain events to once per conn.
|
|
||||||
|
|
||||||
unsigned int installed_status_timer:1;
|
detail::ConnIDKey key;
|
||||||
unsigned int timers_canceled:1;
|
bool key_valid;
|
||||||
unsigned int is_active:1;
|
|
||||||
unsigned int skip:1;
|
unsigned int skip:1;
|
||||||
unsigned int weird:1;
|
unsigned int weird:1;
|
||||||
unsigned int finished:1;
|
unsigned int finished:1;
|
||||||
unsigned int record_packets:1, record_contents:1;
|
|
||||||
unsigned int record_current_packet:1, record_current_content:1;
|
|
||||||
unsigned int saw_first_orig_packet:1, saw_first_resp_packet:1;
|
unsigned int saw_first_orig_packet:1, saw_first_resp_packet:1;
|
||||||
|
|
||||||
// Count number of connections.
|
|
||||||
static uint64_t total_connections;
|
|
||||||
static uint64_t current_connections;
|
|
||||||
|
|
||||||
std::string history;
|
|
||||||
uint32_t hist_seen;
|
uint32_t hist_seen;
|
||||||
|
std::string history;
|
||||||
|
|
||||||
analyzer::TransportLayerAnalyzer* root_analyzer;
|
analyzer::TransportLayerAnalyzer* root_analyzer;
|
||||||
analyzer::pia::PIA* primary_PIA;
|
analyzer::pia::PIA* primary_PIA;
|
||||||
|
|
||||||
UID uid; // Globally unique connection ID.
|
UID uid; // Globally unique connection ID.
|
||||||
detail::WeirdStateMap weird_state;
|
detail::WeirdStateMap weird_state;
|
||||||
|
|
||||||
|
// Count number of connections.
|
||||||
|
static uint64_t total_connections;
|
||||||
|
static uint64_t current_connections;
|
||||||
};
|
};
|
||||||
|
|
||||||
namespace detail {
|
|
||||||
|
|
||||||
class ConnectionTimer final : public Timer {
|
|
||||||
public:
|
|
||||||
ConnectionTimer(Connection* arg_conn, timer_func arg_timer,
|
|
||||||
double arg_t, bool arg_do_expire, TimerType arg_type)
|
|
||||||
: Timer(arg_t, arg_type)
|
|
||||||
{ Init(arg_conn, arg_timer, arg_do_expire); }
|
|
||||||
~ConnectionTimer() override;
|
|
||||||
|
|
||||||
void Dispatch(double t, bool is_expire) override;
|
|
||||||
|
|
||||||
protected:
|
|
||||||
|
|
||||||
void Init(Connection* conn, timer_func timer, bool do_expire);
|
|
||||||
|
|
||||||
Connection* conn;
|
|
||||||
timer_func timer;
|
|
||||||
bool do_expire;
|
|
||||||
};
|
|
||||||
|
|
||||||
} // namespace detail
|
|
||||||
} // namespace zeek
|
} // namespace zeek
|
||||||
|
|
||||||
#define ADD_TIMER(timer, t, do_expire, type) \
|
|
||||||
AddTimer(timer_func(timer), (t), (do_expire), (type))
|
|
||||||
|
|
273
src/Session.cc
Normal file
273
src/Session.cc
Normal file
|
@ -0,0 +1,273 @@
|
||||||
|
// See the file "COPYING" in the main distribution directory for copyright.
|
||||||
|
|
||||||
|
#include "zeek/Session.h"
|
||||||
|
|
||||||
|
#include "zeek/Reporter.h"
|
||||||
|
#include "zeek/analyzer/Analyzer.h"
|
||||||
|
#include "zeek/Val.h"
|
||||||
|
#include "zeek/Event.h"
|
||||||
|
#include "zeek/Desc.h"
|
||||||
|
#include "zeek/Sessions.h"
|
||||||
|
#include "zeek/IP.h"
|
||||||
|
|
||||||
|
namespace zeek {
|
||||||
|
|
||||||
|
namespace detail {
|
||||||
|
|
||||||
|
void SessionTimer::Init(Session* arg_conn, timer_func arg_timer,
|
||||||
|
bool arg_do_expire)
|
||||||
|
{
|
||||||
|
conn = arg_conn;
|
||||||
|
timer = arg_timer;
|
||||||
|
do_expire = arg_do_expire;
|
||||||
|
Ref(conn);
|
||||||
|
}
|
||||||
|
|
||||||
|
SessionTimer::~SessionTimer()
|
||||||
|
{
|
||||||
|
if ( conn->RefCnt() < 1 )
|
||||||
|
reporter->InternalError("reference count inconsistency in ~SessionTimer");
|
||||||
|
|
||||||
|
conn->RemoveTimer(this);
|
||||||
|
Unref(conn);
|
||||||
|
}
|
||||||
|
|
||||||
|
void SessionTimer::Dispatch(double t, bool is_expire)
|
||||||
|
{
|
||||||
|
if ( is_expire && ! do_expire )
|
||||||
|
return;
|
||||||
|
|
||||||
|
// Remove ourselves from the connection's set of timers so
|
||||||
|
// it doesn't try to cancel us.
|
||||||
|
conn->RemoveTimer(this);
|
||||||
|
|
||||||
|
(conn->*timer)(t);
|
||||||
|
|
||||||
|
if ( conn->RefCnt() < 1 )
|
||||||
|
reporter->InternalError("reference count inconsistency in SessionTimer::Dispatch");
|
||||||
|
}
|
||||||
|
|
||||||
|
SessionKey::SessionKey(const void* session, size_t size, bool copy) : size(size)
|
||||||
|
{
|
||||||
|
data = reinterpret_cast<const uint8_t*>(session);
|
||||||
|
if ( copy )
|
||||||
|
CopyData();
|
||||||
|
}
|
||||||
|
|
||||||
|
SessionKey::SessionKey(SessionKey&& rhs)
|
||||||
|
{
|
||||||
|
data = rhs.data;
|
||||||
|
size = rhs.size;
|
||||||
|
copied = rhs.copied;
|
||||||
|
|
||||||
|
rhs.data = nullptr;
|
||||||
|
rhs.size = 0;
|
||||||
|
rhs.copied = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
SessionKey& SessionKey::operator=(SessionKey&& rhs)
|
||||||
|
{
|
||||||
|
if ( this != &rhs )
|
||||||
|
{
|
||||||
|
data = rhs.data;
|
||||||
|
size = rhs.size;
|
||||||
|
copied = rhs.copied;
|
||||||
|
|
||||||
|
rhs.data = nullptr;
|
||||||
|
rhs.size = 0;
|
||||||
|
rhs.copied = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
SessionKey::~SessionKey()
|
||||||
|
{
|
||||||
|
if ( copied )
|
||||||
|
delete [] data;
|
||||||
|
}
|
||||||
|
|
||||||
|
void SessionKey::CopyData()
|
||||||
|
{
|
||||||
|
if ( copied )
|
||||||
|
return;
|
||||||
|
|
||||||
|
copied = true;
|
||||||
|
|
||||||
|
uint8_t *temp = new uint8_t[size];
|
||||||
|
memcpy(temp, data, size);
|
||||||
|
data = temp;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool SessionKey::operator<(const SessionKey& rhs) const
|
||||||
|
{
|
||||||
|
if ( size != rhs.size )
|
||||||
|
return size < rhs.size;
|
||||||
|
|
||||||
|
return memcmp(data, rhs.data, size) < 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace detail
|
||||||
|
|
||||||
|
Session::Session(double t,
|
||||||
|
EventHandlerPtr timeout_event,
|
||||||
|
EventHandlerPtr status_update_event,
|
||||||
|
double status_update_interval)
|
||||||
|
: start_time(t), last_time(t),
|
||||||
|
session_timeout_event(timeout_event),
|
||||||
|
session_status_update_event(status_update_event),
|
||||||
|
session_status_update_interval(status_update_interval)
|
||||||
|
{
|
||||||
|
record_contents = record_packets = 1;
|
||||||
|
record_current_packet = record_current_content = 0;
|
||||||
|
is_active = 1;
|
||||||
|
timers_canceled = 0;
|
||||||
|
inactivity_timeout = 0;
|
||||||
|
installed_status_timer = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
unsigned int Session::MemoryAllocation() const
|
||||||
|
{
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
void Session::Event(EventHandlerPtr f, analyzer::Analyzer* analyzer, const char* name)
|
||||||
|
{
|
||||||
|
if ( ! f )
|
||||||
|
return;
|
||||||
|
|
||||||
|
if ( name )
|
||||||
|
EnqueueEvent(f, analyzer, make_intrusive<StringVal>(name), ConnVal());
|
||||||
|
else
|
||||||
|
EnqueueEvent(f, analyzer, ConnVal());
|
||||||
|
}
|
||||||
|
|
||||||
|
void Session::EnqueueEvent(EventHandlerPtr f, analyzer::Analyzer* a, Args args)
|
||||||
|
{
|
||||||
|
// "this" is passed as a cookie for the event
|
||||||
|
event_mgr.Enqueue(f, std::move(args), util::detail::SOURCE_LOCAL, a ? a->GetID() : 0, this);
|
||||||
|
}
|
||||||
|
|
||||||
|
void Session::Describe(ODesc* d) const
|
||||||
|
{
|
||||||
|
d->Add(start_time);
|
||||||
|
d->Add("(");
|
||||||
|
d->Add(last_time);
|
||||||
|
d->AddSP(")");
|
||||||
|
}
|
||||||
|
|
||||||
|
void Session::SetLifetime(double lifetime)
|
||||||
|
{
|
||||||
|
ADD_TIMER(&Session::DeleteTimer, run_state::network_time + lifetime, 0,
|
||||||
|
detail::TIMER_CONN_DELETE);
|
||||||
|
}
|
||||||
|
|
||||||
|
void Session::SetInactivityTimeout(double timeout)
|
||||||
|
{
|
||||||
|
if ( timeout == inactivity_timeout )
|
||||||
|
return;
|
||||||
|
|
||||||
|
// First cancel and remove any existing inactivity timer.
|
||||||
|
for ( const auto& timer : timers )
|
||||||
|
if ( timer->Type() == detail::TIMER_CONN_INACTIVITY )
|
||||||
|
{
|
||||||
|
detail::timer_mgr->Cancel(timer);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ( timeout )
|
||||||
|
ADD_TIMER(&Session::InactivityTimer,
|
||||||
|
last_time + timeout, 0, detail::TIMER_CONN_INACTIVITY);
|
||||||
|
|
||||||
|
inactivity_timeout = timeout;
|
||||||
|
}
|
||||||
|
|
||||||
|
void Session::EnableStatusUpdateTimer()
|
||||||
|
{
|
||||||
|
if ( installed_status_timer )
|
||||||
|
return;
|
||||||
|
|
||||||
|
if ( session_status_update_event && session_status_update_interval )
|
||||||
|
{
|
||||||
|
ADD_TIMER(&Session::StatusUpdateTimer,
|
||||||
|
run_state::network_time + session_status_update_interval, 0,
|
||||||
|
detail::TIMER_CONN_STATUS_UPDATE);
|
||||||
|
installed_status_timer = 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void Session::CancelTimers()
|
||||||
|
{
|
||||||
|
// We are going to cancel our timers which, in turn, may cause them to
|
||||||
|
// call RemoveTimer(), which would then modify the list we're just
|
||||||
|
// traversing. Thus, we first make a copy of the list which we then
|
||||||
|
// iterate through.
|
||||||
|
TimerPList tmp(timers.length());
|
||||||
|
std::copy(timers.begin(), timers.end(), std::back_inserter(tmp));
|
||||||
|
|
||||||
|
for ( const auto& timer : tmp )
|
||||||
|
detail::timer_mgr->Cancel(timer);
|
||||||
|
|
||||||
|
timers_canceled = 1;
|
||||||
|
timers.clear();
|
||||||
|
}
|
||||||
|
|
||||||
|
void Session::DeleteTimer(double /* t */)
|
||||||
|
{
|
||||||
|
if ( is_active )
|
||||||
|
Event(session_timeout_event, nullptr);
|
||||||
|
|
||||||
|
sessions->Remove(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
void Session::AddTimer(timer_func timer, double t, bool do_expire,
|
||||||
|
detail::TimerType type)
|
||||||
|
{
|
||||||
|
if ( timers_canceled )
|
||||||
|
return;
|
||||||
|
|
||||||
|
// If the key is cleared, the session isn't stored in the session table
|
||||||
|
// anymore and will soon be deleted. We're not installed new timers
|
||||||
|
// anymore then.
|
||||||
|
if ( ! IsKeyValid() )
|
||||||
|
return;
|
||||||
|
|
||||||
|
detail::Timer* conn_timer = new detail::SessionTimer(this, timer, t, do_expire, type);
|
||||||
|
detail::timer_mgr->Add(conn_timer);
|
||||||
|
timers.push_back(conn_timer);
|
||||||
|
}
|
||||||
|
|
||||||
|
void Session::RemoveTimer(detail::Timer* t)
|
||||||
|
{
|
||||||
|
timers.remove(t);
|
||||||
|
}
|
||||||
|
|
||||||
|
void Session::InactivityTimer(double t)
|
||||||
|
{
|
||||||
|
if ( last_time + inactivity_timeout <= t )
|
||||||
|
{
|
||||||
|
Event(session_timeout_event, nullptr);
|
||||||
|
sessions->Remove(this);
|
||||||
|
++detail::killed_by_inactivity;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
ADD_TIMER(&Session::InactivityTimer,
|
||||||
|
last_time + inactivity_timeout, 0,
|
||||||
|
detail::TIMER_CONN_INACTIVITY);
|
||||||
|
}
|
||||||
|
|
||||||
|
void Session::StatusUpdateTimer(double t)
|
||||||
|
{
|
||||||
|
EnqueueEvent(session_status_update_event, nullptr, ConnVal());
|
||||||
|
ADD_TIMER(&Session::StatusUpdateTimer,
|
||||||
|
run_state::network_time + session_status_update_interval, 0,
|
||||||
|
detail::TIMER_CONN_STATUS_UPDATE);
|
||||||
|
}
|
||||||
|
|
||||||
|
void Session::RemoveConnectionTimer(double t)
|
||||||
|
{
|
||||||
|
RemovalEvent();
|
||||||
|
sessions->Remove(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace zeek
|
287
src/Session.h
Normal file
287
src/Session.h
Normal file
|
@ -0,0 +1,287 @@
|
||||||
|
// See the file "COPYING" in the main distribution directory for copyright.
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <memory>
|
||||||
|
|
||||||
|
#include "zeek/Hash.h"
|
||||||
|
#include "zeek/Obj.h"
|
||||||
|
#include "zeek/EventHandler.h"
|
||||||
|
#include "zeek/Timer.h"
|
||||||
|
|
||||||
|
namespace zeek {
|
||||||
|
|
||||||
|
class RecordVal;
|
||||||
|
using RecordValPtr = IntrusivePtr<RecordVal>;
|
||||||
|
class Session;
|
||||||
|
|
||||||
|
namespace analyzer { class Analyzer; }
|
||||||
|
namespace detail {
|
||||||
|
class SessionTimer;
|
||||||
|
class SessionKey;
|
||||||
|
}
|
||||||
|
|
||||||
|
typedef void (Session::*timer_func)(double t);
|
||||||
|
|
||||||
|
class Session : public Obj {
|
||||||
|
public:
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Construct a new session.
|
||||||
|
*
|
||||||
|
* @param t The timestamp for the start and end of the session when it's initially
|
||||||
|
* created. The end time will be updated as later packets are processed.
|
||||||
|
* @param timeout_event The event that will be emitted when the session times out.
|
||||||
|
* @param status_update_event The event that will be emitted for session status
|
||||||
|
* updates. This can be set to null to disable status updates. This event also
|
||||||
|
* won't be emitted unless the EnableStatusUpdateTimer() method is called on the
|
||||||
|
* session, and the interval is set to a non-zero value.
|
||||||
|
* @param status_update_interval The interval in seconds for the status update
|
||||||
|
* event to be emitted. Setting this to zero disables the status update timer.
|
||||||
|
*/
|
||||||
|
Session(double t, EventHandlerPtr timeout_event,
|
||||||
|
EventHandlerPtr status_update_event = nullptr,
|
||||||
|
double status_update_interval = 0);
|
||||||
|
|
||||||
|
virtual ~Session() {}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Invoked when the session is about to be removed. Use Ref(this)
|
||||||
|
* inside Done to keep the session object around, though it'll
|
||||||
|
* no longer be accessible from the SessionManager.
|
||||||
|
*/
|
||||||
|
virtual void Done() = 0;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns a key for the session. This is used as the key for storing
|
||||||
|
* the session in SessionManager.
|
||||||
|
*
|
||||||
|
* @param copy Flag to indicate that the key returned has a copy of the
|
||||||
|
* key data instead of just a pointer to it.
|
||||||
|
*/
|
||||||
|
virtual detail::SessionKey SessionKey(bool copy) const = 0;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set the key as invalid.
|
||||||
|
*/
|
||||||
|
virtual void ClearKey() = 0;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Return whether the key is valid.
|
||||||
|
*/
|
||||||
|
virtual bool IsKeyValid() const = 0;
|
||||||
|
|
||||||
|
double StartTime() const { return start_time; }
|
||||||
|
void SetStartTime(double t) { start_time = t; }
|
||||||
|
double LastTime() const { return last_time; }
|
||||||
|
void SetLastTime(double t) { last_time = t; }
|
||||||
|
|
||||||
|
// True if we should record subsequent packets (either headers or
|
||||||
|
// in their entirety, depending on record_contents). We still
|
||||||
|
// record subsequent SYN/FIN/RST, regardless of how this is set.
|
||||||
|
bool RecordPackets() const { return record_packets; }
|
||||||
|
void SetRecordPackets(bool do_record) { record_packets = do_record ? 1 : 0; }
|
||||||
|
|
||||||
|
// True if we should record full packets for this connection,
|
||||||
|
// false if we should just record headers.
|
||||||
|
bool RecordContents() const { return record_contents; }
|
||||||
|
void SetRecordContents(bool do_record) { record_contents = do_record ? 1 : 0; }
|
||||||
|
|
||||||
|
// Set whether to record *current* packet header/full.
|
||||||
|
void SetRecordCurrentPacket(bool do_record)
|
||||||
|
{ record_current_packet = do_record ? 1 : 0; }
|
||||||
|
void SetRecordCurrentContent(bool do_record)
|
||||||
|
{ record_current_content = do_record ? 1 : 0; }
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the associated "session" record.
|
||||||
|
* TODO: rename this to SessionVal(). This requires a swath of other changes.
|
||||||
|
*/
|
||||||
|
virtual const RecordValPtr& ConnVal() = 0;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Return the memory allocation required by the session record. This requires at
|
||||||
|
* least one call to ConnVal() first in order to setup the record object.
|
||||||
|
*/
|
||||||
|
virtual unsigned int MemoryAllocationConnVal() const = 0;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A lower-bound calculation of how much memory a session object is using.
|
||||||
|
*/
|
||||||
|
virtual unsigned int MemoryAllocation() const;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Generates session removal event(s). Must be overridden by child classes to
|
||||||
|
* provide specific removal events.
|
||||||
|
*/
|
||||||
|
virtual void RemovalEvent() = 0;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Generate an event for this session.
|
||||||
|
*
|
||||||
|
* @param f The handler for the event to be generated. If the handler doesn't
|
||||||
|
* exist, this method doesn't generate anything.
|
||||||
|
* @param analyzer
|
||||||
|
* @param name If given, this will be passed as the first argument to the
|
||||||
|
* handler, followed by the session value. If null, then the event's first
|
||||||
|
* argument is the session value.
|
||||||
|
*/
|
||||||
|
void Event(EventHandlerPtr f, analyzer::Analyzer* analyzer = nullptr,
|
||||||
|
const char* name = nullptr);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Enqueues an event associated with this connection and given analyzer.
|
||||||
|
*/
|
||||||
|
void EnqueueEvent(EventHandlerPtr f, analyzer::Analyzer* analyzer, Args args);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A version of EnqueueEvent() taking a variable number of arguments.
|
||||||
|
*/
|
||||||
|
template <class... Args>
|
||||||
|
std::enable_if_t<
|
||||||
|
std::is_convertible_v<
|
||||||
|
std::tuple_element_t<0, std::tuple<Args...>>, ValPtr>>
|
||||||
|
EnqueueEvent(EventHandlerPtr h, analyzer::Analyzer* analyzer, Args&&... args)
|
||||||
|
{ return EnqueueEvent(h, analyzer, zeek::Args{std::forward<Args>(args)...}); }
|
||||||
|
|
||||||
|
virtual void Describe(ODesc* d) const override;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sets the session to expire after a given amount of time.
|
||||||
|
*
|
||||||
|
* @param lifetime The amount of time in seconds from the current network time.
|
||||||
|
*/
|
||||||
|
void SetLifetime(double lifetime);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sets the inactivity timeout for this session.
|
||||||
|
*
|
||||||
|
* @param timeout The number of seconds of inactivity allowed for this session
|
||||||
|
* before it times out.
|
||||||
|
*/
|
||||||
|
void SetInactivityTimeout(double timeout);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the inactivity timeout for the session.
|
||||||
|
*/
|
||||||
|
double InactivityTimeout() const { return inactivity_timeout; }
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Activates the timer for the status update event.
|
||||||
|
*/
|
||||||
|
void EnableStatusUpdateTimer();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Cancels all timers associated with this session.
|
||||||
|
*/
|
||||||
|
void CancelTimers();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Called when the lifetime of the session expires. Fires a timeout event and
|
||||||
|
* removes the session from the manager.
|
||||||
|
* TODO: This function has a terrible name considering there's an AddTimer() and
|
||||||
|
* a RemoveTimer() method in this class as well.
|
||||||
|
*
|
||||||
|
* @param t This argument is ignored.
|
||||||
|
*/
|
||||||
|
void DeleteTimer(double t);
|
||||||
|
|
||||||
|
protected:
|
||||||
|
|
||||||
|
friend class detail::SessionTimer;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Add a given timer to expire at a specific time.
|
||||||
|
*
|
||||||
|
* @param timer A pointer to a method that will be called when the timer expires.
|
||||||
|
* @param t The time when the timer expires. This is an absolute time, not a time
|
||||||
|
* relative to the current network time.
|
||||||
|
* @param do_expire If set to true, the timer is also evaluated when Zeek
|
||||||
|
* terminates.
|
||||||
|
* @param type The type of timer being added.
|
||||||
|
*/
|
||||||
|
void AddTimer(timer_func timer, double t, bool do_expire,
|
||||||
|
detail::TimerType type);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Remove a specific timer from firing.
|
||||||
|
*/
|
||||||
|
void RemoveTimer(detail::Timer* t);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The handler method for inactivity timers.
|
||||||
|
*/
|
||||||
|
void InactivityTimer(double t);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The handler method for status update timers.
|
||||||
|
*/
|
||||||
|
void StatusUpdateTimer(double t);
|
||||||
|
|
||||||
|
// TODO: is this method used by anyone?
|
||||||
|
void RemoveConnectionTimer(double t);
|
||||||
|
|
||||||
|
double start_time, last_time;
|
||||||
|
TimerPList timers;
|
||||||
|
double inactivity_timeout;
|
||||||
|
|
||||||
|
EventHandlerPtr session_timeout_event;
|
||||||
|
EventHandlerPtr session_status_update_event;
|
||||||
|
double session_status_update_interval;
|
||||||
|
|
||||||
|
unsigned int installed_status_timer:1;
|
||||||
|
unsigned int timers_canceled:1;
|
||||||
|
unsigned int is_active:1;
|
||||||
|
unsigned int record_packets:1, record_contents:1;
|
||||||
|
unsigned int record_current_packet:1, record_current_content:1;
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
namespace detail {
|
||||||
|
|
||||||
|
class SessionTimer final : public Timer {
|
||||||
|
public:
|
||||||
|
SessionTimer(Session* arg_conn, timer_func arg_timer,
|
||||||
|
double arg_t, bool arg_do_expire, TimerType arg_type)
|
||||||
|
: Timer(arg_t, arg_type)
|
||||||
|
{ Init(arg_conn, arg_timer, arg_do_expire); }
|
||||||
|
~SessionTimer() override;
|
||||||
|
|
||||||
|
void Dispatch(double t, bool is_expire) override;
|
||||||
|
|
||||||
|
protected:
|
||||||
|
|
||||||
|
void Init(Session* conn, timer_func timer, bool do_expire);
|
||||||
|
|
||||||
|
Session* conn;
|
||||||
|
timer_func timer;
|
||||||
|
bool do_expire;
|
||||||
|
};
|
||||||
|
|
||||||
|
class SessionKey final {
|
||||||
|
public:
|
||||||
|
SessionKey(const void* session, size_t size, bool copy=false);
|
||||||
|
~SessionKey();
|
||||||
|
|
||||||
|
// Implement move semantics for SessionKey, since they're used as keys
|
||||||
|
// in a map and copying them would cause double-free issues. Adding this
|
||||||
|
// constructor and operator explicitly disables the equivalent copy
|
||||||
|
// operations.
|
||||||
|
SessionKey(SessionKey&& rhs);
|
||||||
|
SessionKey& operator=(SessionKey&& rhs);
|
||||||
|
|
||||||
|
void CopyData();
|
||||||
|
|
||||||
|
bool operator<(const SessionKey& rhs) const;
|
||||||
|
|
||||||
|
private:
|
||||||
|
const uint8_t* data = nullptr;
|
||||||
|
size_t size = 0;
|
||||||
|
bool copied = false;
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace detail
|
||||||
|
} // namespace zeek
|
||||||
|
|
||||||
|
#define ADD_TIMER(timer, t, do_expire, type) \
|
||||||
|
AddTimer(timer_func(timer), (t), (do_expire), (type))
|
|
@ -18,6 +18,7 @@
|
||||||
#include "zeek/NetVar.h"
|
#include "zeek/NetVar.h"
|
||||||
#include "zeek/Reporter.h"
|
#include "zeek/Reporter.h"
|
||||||
#include "zeek/RuleMatcher.h"
|
#include "zeek/RuleMatcher.h"
|
||||||
|
#include "zeek/Session.h"
|
||||||
#include "zeek/TunnelEncapsulation.h"
|
#include "zeek/TunnelEncapsulation.h"
|
||||||
|
|
||||||
#include "zeek/analyzer/protocol/icmp/ICMP.h"
|
#include "zeek/analyzer/protocol/icmp/ICMP.h"
|
||||||
|
@ -363,8 +364,10 @@ Connection* NetSessions::FindConnection(Val* v)
|
||||||
return conn;
|
return conn;
|
||||||
}
|
}
|
||||||
|
|
||||||
void NetSessions::Remove(Connection* c)
|
void NetSessions::Remove(Session* s)
|
||||||
{
|
{
|
||||||
|
Connection* c = static_cast<Connection*>(s);
|
||||||
|
|
||||||
if ( c->IsKeyValid() )
|
if ( c->IsKeyValid() )
|
||||||
{
|
{
|
||||||
const detail::ConnIDKey& key = c->Key();
|
const detail::ConnIDKey& key = c->Key();
|
||||||
|
|
|
@ -17,6 +17,7 @@ namespace detail { class PacketFilter; }
|
||||||
class EncapsulationStack;
|
class EncapsulationStack;
|
||||||
class Packet;
|
class Packet;
|
||||||
class Connection;
|
class Connection;
|
||||||
|
class Session;
|
||||||
struct ConnID;
|
struct ConnID;
|
||||||
|
|
||||||
struct SessionStats {
|
struct SessionStats {
|
||||||
|
@ -49,7 +50,16 @@ public:
|
||||||
// no such connection or the Val is ill-formed.
|
// no such connection or the Val is ill-formed.
|
||||||
Connection* FindConnection(Val* v);
|
Connection* FindConnection(Val* v);
|
||||||
|
|
||||||
void Remove(Connection* c);
|
/**
|
||||||
|
* 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.
|
||||||
|
* @return The connection, or nullptr if one doesn't exist.
|
||||||
|
*/
|
||||||
|
Connection* FindConnection(const detail::ConnIDKey& key, TransportProto proto);
|
||||||
|
|
||||||
|
void Remove(Session* s);
|
||||||
void Insert(Connection* c);
|
void Insert(Connection* c);
|
||||||
|
|
||||||
// Generating connection_pending events for all connections
|
// Generating connection_pending events for all connections
|
||||||
|
|
|
@ -143,7 +143,7 @@ protected:
|
||||||
void CheckRecording(bool need_contents, TCP_Flags flags);
|
void CheckRecording(bool need_contents, TCP_Flags flags);
|
||||||
void CheckPIA_FirstPacket(bool is_orig, const IP_Hdr* ip);
|
void CheckPIA_FirstPacket(bool is_orig, const IP_Hdr* ip);
|
||||||
|
|
||||||
friend class detail::ConnectionTimer;
|
friend class detail::SessionTimer;
|
||||||
void AttemptTimer(double t);
|
void AttemptTimer(double t);
|
||||||
void PartialCloseTimer(double t);
|
void PartialCloseTimer(double t);
|
||||||
void ExpireTimer(double t);
|
void ExpireTimer(double t);
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue