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); IMPLEMENT_SERIAL(Connection, SER_CONNECTION);
Connection::Connection(NetSessions* s, HashKey* k, double t, const ConnID* id, 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; sessions = s;
key = k; key = k;
@ -162,7 +162,7 @@ Connection::Connection(NetSessions* s, HashKey* k, double t, const ConnID* id,
uid = 0; // Will set later. uid = 0; // Will set later.
if ( arg_encap ) if ( arg_encap )
encapsulation = new Encapsulation(arg_encap); encapsulation = new EncapsulationStack(*arg_encap);
else else
encapsulation = 0; encapsulation = 0;
@ -200,7 +200,7 @@ Connection::~Connection()
--external_connections; --external_connections;
} }
void Connection::CheckEncapsulation(const Encapsulation* arg_encap) void Connection::CheckEncapsulation(const EncapsulationStack* arg_encap)
{ {
if ( encapsulation && arg_encap ) if ( encapsulation && arg_encap )
{ {
@ -208,22 +208,22 @@ void Connection::CheckEncapsulation(const Encapsulation* arg_encap)
{ {
Event(tunnel_changed, 0, arg_encap->GetVectorVal()); Event(tunnel_changed, 0, arg_encap->GetVectorVal());
delete encapsulation; delete encapsulation;
encapsulation = new Encapsulation(arg_encap); encapsulation = new EncapsulationStack(*arg_encap);
} }
} }
else if ( encapsulation ) else if ( encapsulation )
{ {
Encapsulation empty; EncapsulationStack empty;
Event(tunnel_changed, 0, empty.GetVectorVal()); Event(tunnel_changed, 0, empty.GetVectorVal());
delete encapsulation; delete encapsulation;
encapsulation = new Encapsulation(arg_encap); encapsulation = 0;
} }
else if ( arg_encap ) else if ( arg_encap )
{ {
Event(tunnel_changed, 0, arg_encap->GetVectorVal()); 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 { class Connection : public BroObj {
public: public:
Connection(NetSessions* s, HashKey* k, double t, const ConnID* id, Connection(NetSessions* s, HashKey* k, double t, const ConnID* id,
uint32 flow, const Encapsulation* arg_encap); uint32 flow, const EncapsulationStack* arg_encap);
virtual ~Connection(); virtual ~Connection();
// Invoked when an encapsulation is discovered. It records the // 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 // event if it's different from the previous encapsulation (or the
// first encountered). encap can be null to indicate no // first encountered). encap can be null to indicate no
// encapsulation. // encapsulation.
void CheckEncapsulation(const Encapsulation* encap); void CheckEncapsulation(const EncapsulationStack* encap);
// Invoked when connection is about to be removed. Use Ref(this) // Invoked when connection is about to be removed. Use Ref(this)
// inside Done to keep the connection object around (though it'll // inside Done to keep the connection object around (though it'll
@ -252,7 +252,7 @@ public:
uint64 GetUID() const { return uid; } uint64 GetUID() const { return uid; }
const Encapsulation* GetEncapsulation() const const EncapsulationStack* GetEncapsulation() const
{ return encapsulation; } { return encapsulation; }
void CheckFlowLabel(bool is_orig, uint32 flow_label); void CheckFlowLabel(bool is_orig, uint32 flow_label);
@ -292,7 +292,7 @@ protected:
double inactivity_timeout; double inactivity_timeout;
RecordVal* conn_val; RecordVal* conn_val;
LoginConn* login_conn; // either nil, or this 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. int suppress_event; // suppress certain events to once per conn.
unsigned int installed_status_timer:1; 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, void NetSessions::DoNextPacket(double t, const struct pcap_pkthdr* hdr,
const IP_Hdr* ip_hdr, const u_char* const pkt, 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; uint32 caplen = hdr->caplen - hdr_size;
const struct ip* ip4 = ip_hdr->IP4_Hdr(); const struct ip* ip4 = ip_hdr->IP4_Hdr();
@ -576,8 +576,6 @@ void NetSessions::DoNextPacket(double t, const struct pcap_pkthdr* hdr,
return; return;
} }
Encapsulation* outer = new Encapsulation(encapsulation);
// Look up to see if we've already seen this IP tunnel, identified // Look up to see if we've already seen this IP tunnel, identified
// by the pair of IP addresses, so that we can always associate the // by the pair of IP addresses, so that we can always associate the
// same UID with it. // 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()); EncapsulatingConn ec(ip_hdr->SrcAddr(), ip_hdr->DstAddr());
ip_tunnels[tunnel_idx] = TunnelActivity(ec, network_time); ip_tunnels[tunnel_idx] = TunnelActivity(ec, network_time);
timer_mgr->Add(new IPTunnelTimer(network_time, tunnel_idx)); timer_mgr->Add(new IPTunnelTimer(network_time, tunnel_idx));
outer->Add(ec);
} }
else else
{
it->second.second = network_time; 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); Remove(f);
return; 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, 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; struct pcap_pkthdr fake_hdr;
fake_hdr.caplen = fake_hdr.len = inner->TotalLen(); fake_hdr.caplen = fake_hdr.len = inner->TotalLen();
@ -732,7 +726,11 @@ void NetSessions::DoNextInnerPacket(double t, const struct pcap_pkthdr* hdr,
if ( hdr ) if ( hdr )
fake_hdr.ts = hdr->ts; fake_hdr.ts = hdr->ts;
else 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; const u_char* pkt = 0;
@ -741,7 +739,14 @@ void NetSessions::DoNextInnerPacket(double t, const struct pcap_pkthdr* hdr,
else else
pkt = (const u_char*) inner->IP6_Hdr(); 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); DoNextPacket(t, &fake_hdr, inner, pkt, 0, outer);
delete inner;
delete outer;
} }
int NetSessions::ParseIPPacket(int caplen, const u_char* const pkt, int proto, 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, bool NetSessions::CheckHeaderTrunc(int proto, uint32 len, uint32 caplen,
const struct pcap_pkthdr* h, const struct pcap_pkthdr* h,
const u_char* p, const Encapsulation* encap) const u_char* p, const EncapsulationStack* encap)
{ {
uint32 min_hdr_len = 0; uint32 min_hdr_len = 0;
switch ( proto ) { switch ( proto ) {
@ -1110,7 +1115,7 @@ void NetSessions::GetStats(SessionStats& s) const
Connection* NetSessions::NewConn(HashKey* k, double t, const ConnID* id, Connection* NetSessions::NewConn(HashKey* k, double t, const ConnID* id,
const u_char* data, int proto, uint32 flow_label, 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. // 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. // 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, 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 ) if ( hdr )
dump_this_packet = 1; 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, void NetSessions::Weird(const char* name, const IP_Hdr* ip,
const Encapsulation* encap) const EncapsulationStack* encap)
{ {
if ( encap && encap->LastType() != BifEnum::Tunnel::NONE ) if ( encap && encap->LastType() != BifEnum::Tunnel::NONE )
reporter->Weird(ip->SrcAddr(), ip->DstAddr(), reporter->Weird(ip->SrcAddr(), ip->DstAddr(),

View file

@ -16,7 +16,7 @@
struct pcap_pkthdr; struct pcap_pkthdr;
class Encapsulation; class EncapsulationStack;
class Connection; class Connection;
class ConnID; class ConnID;
class OSFingerprint; class OSFingerprint;
@ -109,9 +109,9 @@ public:
void GetStats(SessionStats& s) const; void GetStats(SessionStats& s) const;
void Weird(const char* name, const struct pcap_pkthdr* hdr, 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, void Weird(const char* name, const IP_Hdr* ip,
const Encapsulation* encap = 0); const EncapsulationStack* encap = 0);
PacketFilter* GetPacketFilter() PacketFilter* GetPacketFilter()
{ {
@ -137,7 +137,7 @@ public:
void DoNextPacket(double t, const struct pcap_pkthdr* hdr, void DoNextPacket(double t, const struct pcap_pkthdr* hdr,
const IP_Hdr* ip_hdr, const u_char* const pkt, 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. * 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 * so that the fake pcap header passed to DoNextPacket will use
* the same timeval. The caplen and len fields of the fake pcap * the same timeval. The caplen and len fields of the fake pcap
* header are always set to the TotalLength() of \a inner. * 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, 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 * 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, Connection* NewConn(HashKey* k, double t, const ConnID* id,
const u_char* data, int proto, uint32 flow_lable, 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 // Check whether the tag of the current packet is consistent with
// the given connection. Returns: // the given connection. Returns:
@ -234,7 +239,7 @@ protected:
// than that protocol's minimum header size. // than that protocol's minimum header size.
bool CheckHeaderTrunc(int proto, uint32 len, uint32 caplen, bool CheckHeaderTrunc(int proto, uint32 len, uint32 caplen,
const struct pcap_pkthdr* hdr, const u_char* pkt, const struct pcap_pkthdr* hdr, const u_char* pkt,
const Encapsulation* encap); const EncapsulationStack* encap);
CompositeHash* ch; CompositeHash* ch;
PDict(Connection) tcp_conns; PDict(Connection) tcp_conns;

View file

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

View file

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

View file

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

View file

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