mirror of
https://github.com/zeek/zeek.git
synced 2025-10-10 10:38:20 +00:00
219 lines
4.6 KiB
C++
219 lines
4.6 KiB
C++
// See the file "COPYING" in the main distribution directory for copyright.
|
|
|
|
#include "config.h"
|
|
|
|
#include <stdlib.h>
|
|
|
|
#include "Event.h"
|
|
#include "Net.h"
|
|
#include "NetVar.h"
|
|
#include "TCP.h"
|
|
#include "SteppingStone.h"
|
|
#include "util.h"
|
|
|
|
SteppingStoneEndpoint::SteppingStoneEndpoint(TCP_Endpoint* e, SteppingStoneManager* m)
|
|
{
|
|
endp = e;
|
|
stp_max_top_seq = 0;
|
|
stp_last_time = stp_resume_time = 0.0;
|
|
stp_manager = m;
|
|
stp_id = stp_manager->NextID();
|
|
stp_key = new HashKey(bro_int_t(stp_id));
|
|
|
|
CreateEndpEvent(e->IsOrig());
|
|
|
|
// Make sure the connection does not get deleted.
|
|
Ref(endp->TCP()->Conn());
|
|
}
|
|
|
|
SteppingStoneEndpoint::~SteppingStoneEndpoint()
|
|
{
|
|
delete stp_key;
|
|
Unref(endp->TCP()->Conn());
|
|
}
|
|
|
|
void SteppingStoneEndpoint::Done()
|
|
{
|
|
if ( RefCnt() > 1 )
|
|
return;
|
|
|
|
SteppingStoneEndpoint* ep;
|
|
IterCookie* cookie;
|
|
|
|
cookie = stp_inbound_endps.InitForIteration();
|
|
while ( (ep = stp_inbound_endps.NextEntry(cookie)) )
|
|
{
|
|
ep->stp_outbound_endps.Remove(stp_key);
|
|
Event(stp_remove_pair, ep->stp_id, stp_id);
|
|
Unref(ep);
|
|
}
|
|
|
|
cookie = stp_outbound_endps.InitForIteration();
|
|
while ( (ep = stp_outbound_endps.NextEntry(cookie)) )
|
|
{
|
|
ep->stp_inbound_endps.Remove(stp_key);
|
|
Event(stp_remove_pair, stp_id, ep->stp_id);
|
|
Unref(ep);
|
|
}
|
|
|
|
Event(stp_remove_endp, stp_id);
|
|
}
|
|
|
|
int SteppingStoneEndpoint::DataSent(double t, int seq, int len, int caplen,
|
|
const u_char* data, const IP_Hdr* /* ip */,
|
|
const struct tcphdr* tp)
|
|
{
|
|
if ( caplen < len )
|
|
len = caplen;
|
|
|
|
if ( len <= 0 )
|
|
return 0;
|
|
|
|
double tmin = t - stp_delta;
|
|
|
|
while ( stp_manager->OrderedEndpoints().length() > 0 )
|
|
{
|
|
int f = stp_manager->OrderedEndpoints().front();
|
|
|
|
if ( stp_manager->OrderedEndpoints()[f]->stp_resume_time < tmin )
|
|
{
|
|
SteppingStoneEndpoint* e =
|
|
stp_manager->OrderedEndpoints().pop_front();
|
|
e->Done();
|
|
Unref(e);
|
|
}
|
|
else
|
|
break;
|
|
}
|
|
|
|
int ack = endp->AckSeq() - endp->StartSeq();
|
|
int top_seq = seq + len;
|
|
|
|
if ( top_seq <= ack || top_seq <= stp_max_top_seq )
|
|
// There is no new data in this packet
|
|
return 0;
|
|
|
|
stp_max_top_seq = top_seq;
|
|
|
|
if ( stp_last_time && t <= stp_last_time + stp_idle_min )
|
|
{
|
|
stp_last_time = t;
|
|
return 1;
|
|
}
|
|
|
|
// Either just starts, or resumes from an idle period.
|
|
stp_last_time = stp_resume_time = t;
|
|
|
|
Event(stp_resume_endp, stp_id);
|
|
loop_over_queue(stp_manager->OrderedEndpoints(), i)
|
|
{
|
|
SteppingStoneEndpoint* ep = stp_manager->OrderedEndpoints()[i];
|
|
if ( ep->endp->TCP() != endp->TCP() )
|
|
{
|
|
Ref(ep);
|
|
Ref(this);
|
|
|
|
stp_inbound_endps.Insert(ep->stp_key, ep);
|
|
ep->stp_outbound_endps.Insert(stp_key, this);
|
|
|
|
Event(stp_correlate_pair, ep->stp_id, stp_id);
|
|
}
|
|
|
|
else
|
|
{ // ep and this belong to same connection
|
|
}
|
|
}
|
|
|
|
stp_manager->OrderedEndpoints().push_back(this);
|
|
Ref(this);
|
|
|
|
return 1;
|
|
}
|
|
|
|
void SteppingStoneEndpoint::Event(EventHandlerPtr f, int id1, int id2)
|
|
{
|
|
if ( ! f )
|
|
return;
|
|
|
|
val_list* vl = new val_list;
|
|
|
|
vl->append(new Val(id1, TYPE_INT));
|
|
|
|
if ( id2 >= 0 )
|
|
vl->append(new Val(id2, TYPE_INT));
|
|
|
|
endp->TCP()->ConnectionEvent(f, vl);
|
|
}
|
|
|
|
void SteppingStoneEndpoint::CreateEndpEvent(int is_orig)
|
|
{
|
|
val_list* vl = new val_list;
|
|
|
|
vl->append(endp->TCP()->BuildConnVal());
|
|
vl->append(new Val(stp_id, TYPE_INT));
|
|
vl->append(new Val(is_orig, TYPE_BOOL));
|
|
|
|
endp->TCP()->ConnectionEvent(stp_create_endp, vl);
|
|
}
|
|
|
|
SteppingStone_Analyzer::SteppingStone_Analyzer(Connection* c)
|
|
: TCP_ApplicationAnalyzer(AnalyzerTag::SteppingStone, c)
|
|
{
|
|
stp_manager = sessions->GetSTPManager();
|
|
|
|
orig_endp = resp_endp = 0;
|
|
orig_stream_pos = resp_stream_pos = 1;
|
|
}
|
|
|
|
void SteppingStone_Analyzer::Init()
|
|
{
|
|
TCP_ApplicationAnalyzer::Init();
|
|
|
|
assert(TCP());
|
|
orig_endp = new SteppingStoneEndpoint(TCP()->Orig(), stp_manager);
|
|
resp_endp = new SteppingStoneEndpoint(TCP()->Resp(), stp_manager);
|
|
}
|
|
|
|
void SteppingStone_Analyzer::DeliverPacket(int len, const u_char* data,
|
|
bool is_orig, int seq,
|
|
const IP_Hdr* ip, int caplen)
|
|
{
|
|
TCP_ApplicationAnalyzer::DeliverPacket(len, data, is_orig, seq,
|
|
ip, caplen);
|
|
|
|
if ( is_orig )
|
|
orig_endp->DataSent(network_time, seq, len, caplen, data, 0, 0);
|
|
else
|
|
resp_endp->DataSent(network_time, seq, len, caplen, data, 0, 0);
|
|
}
|
|
|
|
void SteppingStone_Analyzer::DeliverStream(int len, const u_char* data,
|
|
bool is_orig)
|
|
{
|
|
TCP_ApplicationAnalyzer::DeliverStream(len, data, is_orig);
|
|
|
|
if ( is_orig )
|
|
{
|
|
orig_endp->DataSent(network_time, orig_stream_pos, len, len,
|
|
data, 0, 0);
|
|
orig_stream_pos += len;
|
|
}
|
|
|
|
else
|
|
{
|
|
resp_endp->DataSent(network_time, resp_stream_pos, len, len,
|
|
data, 0, 0);
|
|
resp_stream_pos += len;
|
|
}
|
|
}
|
|
|
|
void SteppingStone_Analyzer::Done()
|
|
{
|
|
TCP_ApplicationAnalyzer::Done();
|
|
|
|
orig_endp->Done();
|
|
resp_endp->Done();
|
|
|
|
Unref(orig_endp);
|
|
Unref(resp_endp);
|
|
}
|