Refactor of interal tunnel analysis code.

- Pulled more common code into NetSessions::DoNextInnerPacket()
  and made the pcap header it makes internally use network_time

- Remove Encapsulation class ctor from pointer

- Rename Encapsulation class to EncapsulationStack
This commit is contained in:
Jon Siwek 2012-06-18 16:56:19 -05:00
parent e04d629733
commit ce58a3e908
8 changed files with 60 additions and 65 deletions

View file

@ -113,7 +113,7 @@ unsigned int Connection::external_connections = 0;
IMPLEMENT_SERIAL(Connection, SER_CONNECTION);
Connection::Connection(NetSessions* s, HashKey* k, double t, const ConnID* id,
uint32 flow, const Encapsulation* arg_encap)
uint32 flow, const EncapsulationStack* arg_encap)
{
sessions = s;
key = k;
@ -162,7 +162,7 @@ Connection::Connection(NetSessions* s, HashKey* k, double t, const ConnID* id,
uid = 0; // Will set later.
if ( arg_encap )
encapsulation = new Encapsulation(arg_encap);
encapsulation = new EncapsulationStack(*arg_encap);
else
encapsulation = 0;
@ -200,7 +200,7 @@ Connection::~Connection()
--external_connections;
}
void Connection::CheckEncapsulation(const Encapsulation* arg_encap)
void Connection::CheckEncapsulation(const EncapsulationStack* arg_encap)
{
if ( encapsulation && arg_encap )
{
@ -208,22 +208,22 @@ void Connection::CheckEncapsulation(const Encapsulation* arg_encap)
{
Event(tunnel_changed, 0, arg_encap->GetVectorVal());
delete encapsulation;
encapsulation = new Encapsulation(arg_encap);
encapsulation = new EncapsulationStack(*arg_encap);
}
}
else if ( encapsulation )
{
Encapsulation empty;
EncapsulationStack empty;
Event(tunnel_changed, 0, empty.GetVectorVal());
delete encapsulation;
encapsulation = new Encapsulation(arg_encap);
encapsulation = 0;
}
else if ( arg_encap )
{
Event(tunnel_changed, 0, arg_encap->GetVectorVal());
encapsulation = new Encapsulation(arg_encap);
encapsulation = new EncapsulationStack(*arg_encap);
}
}

View file

@ -52,7 +52,7 @@ class Analyzer;
class Connection : public BroObj {
public:
Connection(NetSessions* s, HashKey* k, double t, const ConnID* id,
uint32 flow, const Encapsulation* arg_encap);
uint32 flow, const EncapsulationStack* arg_encap);
virtual ~Connection();
// Invoked when an encapsulation is discovered. It records the
@ -60,7 +60,7 @@ public:
// event if it's different from the previous encapsulation (or the
// first encountered). encap can be null to indicate no
// encapsulation.
void CheckEncapsulation(const Encapsulation* encap);
void CheckEncapsulation(const EncapsulationStack* encap);
// Invoked when connection is about to be removed. Use Ref(this)
// inside Done to keep the connection object around (though it'll
@ -252,7 +252,7 @@ public:
uint64 GetUID() const { return uid; }
const Encapsulation* GetEncapsulation() const
const EncapsulationStack* GetEncapsulation() const
{ return encapsulation; }
void CheckFlowLabel(bool is_orig, uint32 flow_label);
@ -292,7 +292,7 @@ protected:
double inactivity_timeout;
RecordVal* conn_val;
LoginConn* login_conn; // either nil, or this
const Encapsulation* encapsulation; // tunnels
const EncapsulationStack* encapsulation; // tunnels
int suppress_event; // suppress certain events to once per conn.
unsigned int installed_status_timer:1;

View file

@ -367,7 +367,7 @@ int NetSessions::CheckConnectionTag(Connection* conn)
void NetSessions::DoNextPacket(double t, const struct pcap_pkthdr* hdr,
const IP_Hdr* ip_hdr, const u_char* const pkt,
int hdr_size, const Encapsulation* encapsulation)
int hdr_size, const EncapsulationStack* encapsulation)
{
uint32 caplen = hdr->caplen - hdr_size;
const struct ip* ip4 = ip_hdr->IP4_Hdr();
@ -576,8 +576,6 @@ void NetSessions::DoNextPacket(double t, const struct pcap_pkthdr* hdr,
return;
}
Encapsulation* outer = new Encapsulation(encapsulation);
// Look up to see if we've already seen this IP tunnel, identified
// by the pair of IP addresses, so that we can always associate the
// same UID with it.
@ -594,18 +592,13 @@ void NetSessions::DoNextPacket(double t, const struct pcap_pkthdr* hdr,
EncapsulatingConn ec(ip_hdr->SrcAddr(), ip_hdr->DstAddr());
ip_tunnels[tunnel_idx] = TunnelActivity(ec, network_time);
timer_mgr->Add(new IPTunnelTimer(network_time, tunnel_idx));
outer->Add(ec);
}
else
{
it->second.second = network_time;
outer->Add(it->second.first);
}
DoNextInnerPacket(t, hdr, inner, outer);
DoNextInnerPacket(t, hdr, inner, encapsulation,
ip_tunnels[tunnel_idx].first);
delete inner;
delete outer;
Remove(f);
return;
}
@ -724,7 +717,8 @@ void NetSessions::DoNextPacket(double t, const struct pcap_pkthdr* hdr,
}
void NetSessions::DoNextInnerPacket(double t, const struct pcap_pkthdr* hdr,
const IP_Hdr* inner, const Encapsulation* outer)
const IP_Hdr* inner, const EncapsulationStack* prev,
const EncapsulatingConn& ec)
{
struct pcap_pkthdr fake_hdr;
fake_hdr.caplen = fake_hdr.len = inner->TotalLen();
@ -732,7 +726,11 @@ void NetSessions::DoNextInnerPacket(double t, const struct pcap_pkthdr* hdr,
if ( hdr )
fake_hdr.ts = hdr->ts;
else
fake_hdr.ts.tv_sec = fake_hdr.ts.tv_usec = 0;
{
fake_hdr.ts.tv_sec = (time_t) network_time;
fake_hdr.ts.tv_usec = (suseconds_t)
((network_time - (double)fake_hdr.ts.tv_sec) * 1000000);
}
const u_char* pkt = 0;
@ -741,7 +739,14 @@ void NetSessions::DoNextInnerPacket(double t, const struct pcap_pkthdr* hdr,
else
pkt = (const u_char*) inner->IP6_Hdr();
EncapsulationStack* outer = prev ?
new EncapsulationStack(*prev) : new EncapsulationStack();
outer->Add(ec);
DoNextPacket(t, &fake_hdr, inner, pkt, 0, outer);
delete inner;
delete outer;
}
int NetSessions::ParseIPPacket(int caplen, const u_char* const pkt, int proto,
@ -778,7 +783,7 @@ int NetSessions::ParseIPPacket(int caplen, const u_char* const pkt, int proto,
bool NetSessions::CheckHeaderTrunc(int proto, uint32 len, uint32 caplen,
const struct pcap_pkthdr* h,
const u_char* p, const Encapsulation* encap)
const u_char* p, const EncapsulationStack* encap)
{
uint32 min_hdr_len = 0;
switch ( proto ) {
@ -1110,7 +1115,7 @@ void NetSessions::GetStats(SessionStats& s) const
Connection* NetSessions::NewConn(HashKey* k, double t, const ConnID* id,
const u_char* data, int proto, uint32 flow_label,
const Encapsulation* encapsulation)
const EncapsulationStack* encapsulation)
{
// 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.
@ -1331,7 +1336,7 @@ void NetSessions::Internal(const char* msg, const struct pcap_pkthdr* hdr,
}
void NetSessions::Weird(const char* name, const struct pcap_pkthdr* hdr,
const u_char* pkt, const Encapsulation* encap)
const u_char* pkt, const EncapsulationStack* encap)
{
if ( hdr )
dump_this_packet = 1;
@ -1343,7 +1348,7 @@ void NetSessions::Weird(const char* name, const struct pcap_pkthdr* hdr,
}
void NetSessions::Weird(const char* name, const IP_Hdr* ip,
const Encapsulation* encap)
const EncapsulationStack* encap)
{
if ( encap && encap->LastType() != BifEnum::Tunnel::NONE )
reporter->Weird(ip->SrcAddr(), ip->DstAddr(),

View file

@ -16,7 +16,7 @@
struct pcap_pkthdr;
class Encapsulation;
class EncapsulationStack;
class Connection;
class ConnID;
class OSFingerprint;
@ -109,9 +109,9 @@ public:
void GetStats(SessionStats& s) const;
void Weird(const char* name, const struct pcap_pkthdr* hdr,
const u_char* pkt, const Encapsulation* encap = 0);
const u_char* pkt, const EncapsulationStack* encap = 0);
void Weird(const char* name, const IP_Hdr* ip,
const Encapsulation* encap = 0);
const EncapsulationStack* encap = 0);
PacketFilter* GetPacketFilter()
{
@ -137,7 +137,7 @@ public:
void DoNextPacket(double t, const struct pcap_pkthdr* hdr,
const IP_Hdr* ip_hdr, const u_char* const pkt,
int hdr_size, const Encapsulation* encapsulation);
int hdr_size, const EncapsulationStack* encapsulation);
/**
* Wrapper that recurses on DoNextPacket for encapsulated IP packets.
@ -147,10 +147,15 @@ public:
* so that the fake pcap header passed to DoNextPacket will use
* the same timeval. The caplen and len fields of the fake pcap
* header are always set to the TotalLength() of \a inner.
* @param outer The encapsulation information for the inner IP packet.
* @param inner Pointer to IP header wrapper of the inner packet, ownership
* of the pointer's memory is assumed by this function.
* @param prev Any previous encapsulation stack of the caller, not including
* the most-recently found depth of encapsulation.
* @param ec The most-recently found depth of encapsulation.
*/
void DoNextInnerPacket(double t, const struct pcap_pkthdr* hdr,
const IP_Hdr* inner, const Encapsulation* outer);
const IP_Hdr* inner, const EncapsulationStack* prev,
const EncapsulatingConn& ec);
/**
* Returns a wrapper IP_Hdr object if \a pkt appears to be a valid IPv4
@ -185,7 +190,7 @@ protected:
Connection* NewConn(HashKey* k, double t, const ConnID* id,
const u_char* data, int proto, uint32 flow_lable,
const Encapsulation* encapsulation);
const EncapsulationStack* encapsulation);
// Check whether the tag of the current packet is consistent with
// the given connection. Returns:
@ -234,7 +239,7 @@ protected:
// than that protocol's minimum header size.
bool CheckHeaderTrunc(int proto, uint32 len, uint32 caplen,
const struct pcap_pkthdr* hdr, const u_char* pkt,
const Encapsulation* encap);
const EncapsulationStack* encap);
CompositeHash* ch;
PDict(Connection) tcp_conns;

View file

@ -149,7 +149,7 @@ void Teredo_Analyzer::DeliverPacket(int len, const u_char* data, bool orig,
return;
}
const Encapsulation* e = Conn()->GetEncapsulation();
const EncapsulationStack* e = Conn()->GetEncapsulation();
if ( e && e->Depth() >= BifConst::Tunnel::max_depth )
{
@ -222,12 +222,7 @@ void Teredo_Analyzer::DeliverPacket(int len, const u_char* data, bool orig,
Conn()->Event(teredo_bubble, 0, teredo_hdr);
}
Encapsulation* outer = new Encapsulation(e);
EncapsulatingConn ec(Conn(), BifEnum::Tunnel::TEREDO);
outer->Add(ec);
sessions->DoNextInnerPacket(network_time, 0, inner, outer);
delete inner;
delete outer;
sessions->DoNextInnerPacket(network_time, 0, inner, e, ec);
}

View file

@ -34,7 +34,7 @@ RecordVal* EncapsulatingConn::GetRecordVal() const
return rv;
}
bool operator==(const Encapsulation& e1, const Encapsulation& e2)
bool operator==(const EncapsulationStack& e1, const EncapsulationStack& e2)
{
if ( ! e1.conns )
return e2.conns;

View file

@ -114,12 +114,12 @@ protected:
/**
* Abstracts an arbitrary amount of nested tunneling.
*/
class Encapsulation {
class EncapsulationStack {
public:
Encapsulation() : conns(0)
EncapsulationStack() : conns(0)
{}
Encapsulation(const Encapsulation& other)
EncapsulationStack(const EncapsulationStack& other)
{
if ( other.conns )
conns = new vector<EncapsulatingConn>(*(other.conns));
@ -127,15 +127,7 @@ public:
conns = 0;
}
Encapsulation(const Encapsulation* other)
{
if ( other && other->conns )
conns = new vector<EncapsulatingConn>(*(other->conns));
else
conns = 0;
}
Encapsulation& operator=(const Encapsulation& other)
EncapsulationStack& operator=(const EncapsulationStack& other)
{
if ( this == &other )
return *this;
@ -150,10 +142,10 @@ public:
return *this;
}
~Encapsulation() { delete conns; }
~EncapsulationStack() { delete conns; }
/**
* Add a new inner-most tunnel to the Encapsulation.
* Add a new inner-most tunnel to the EncapsulationStack.
*
* @param c The new inner-most tunnel to append to the tunnel chain.
*/
@ -200,9 +192,11 @@ public:
return vv;
}
friend bool operator==(const Encapsulation& e1, const Encapsulation& e2);
friend bool operator==(const EncapsulationStack& e1,
const EncapsulationStack& e2);
friend bool operator!=(const Encapsulation& e1, const Encapsulation& e2)
friend bool operator!=(const EncapsulationStack& e1,
const EncapsulationStack& e2)
{
return ! ( e1 == e2 );
}

View file

@ -12,7 +12,7 @@ flow AYIYA_Flow
function process_ayiya(pdu: PDU): bool
%{
Connection *c = connection()->bro_analyzer()->Conn();
const Encapsulation* e = c->GetEncapsulation();
const EncapsulationStack* e = c->GetEncapsulation();
if ( e && e->Depth() >= BifConst::Tunnel::max_depth )
{
@ -72,14 +72,10 @@ flow AYIYA_Flow
if ( result != 0 )
return false;
Encapsulation* outer = new Encapsulation(e);
EncapsulatingConn ec(c, BifEnum::Tunnel::AYIYA);
outer->Add(ec);
sessions->DoNextInnerPacket(network_time(), 0, inner, outer);
sessions->DoNextInnerPacket(network_time(), 0, inner, e, ec);
delete inner;
delete outer;
return (result == 0) ? true : false;
%}