diff --git a/src/Conn.cc b/src/Conn.cc index f3ebaca0c9..bc2e7fb5cf 100644 --- a/src/Conn.cc +++ b/src/Conn.cc @@ -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); } } diff --git a/src/Conn.h b/src/Conn.h index b3798cfb36..782d41a801 100644 --- a/src/Conn.h +++ b/src/Conn.h @@ -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; diff --git a/src/Sessions.cc b/src/Sessions.cc index 84c881b0ef..10126f45b1 100644 --- a/src/Sessions.cc +++ b/src/Sessions.cc @@ -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(), diff --git a/src/Sessions.h b/src/Sessions.h index 548c0903be..613eebe5ca 100644 --- a/src/Sessions.h +++ b/src/Sessions.h @@ -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; diff --git a/src/Teredo.cc b/src/Teredo.cc index e537edb916..ac68bdbed1 100644 --- a/src/Teredo.cc +++ b/src/Teredo.cc @@ -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); } diff --git a/src/TunnelEncapsulation.cc b/src/TunnelEncapsulation.cc index f023a40b6a..edbabef81f 100644 --- a/src/TunnelEncapsulation.cc +++ b/src/TunnelEncapsulation.cc @@ -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; diff --git a/src/TunnelEncapsulation.h b/src/TunnelEncapsulation.h index 9dcf134536..e8ca7a48b6 100644 --- a/src/TunnelEncapsulation.h +++ b/src/TunnelEncapsulation.h @@ -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(*(other.conns)); @@ -127,15 +127,7 @@ public: conns = 0; } - Encapsulation(const Encapsulation* other) - { - if ( other && other->conns ) - conns = new vector(*(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 ); } diff --git a/src/ayiya-analyzer.pac b/src/ayiya-analyzer.pac index f1b144ff44..89d1143ad7 100644 --- a/src/ayiya-analyzer.pac +++ b/src/ayiya-analyzer.pac @@ -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; %}