Change Packet::ip_hdr to be a shared_ptr so it can be copied into EncapsulatingConn

This commit is contained in:
Tim Wojtulewicz 2021-08-19 14:05:38 -07:00
parent d4f57a6100
commit ed798c6aba
24 changed files with 91 additions and 42 deletions

View file

@ -34,7 +34,7 @@ bool Discarder::IsActive()
return check_ip || check_tcp || check_udp || check_icmp;
}
bool Discarder::NextPacket(const std::unique_ptr<IP_Hdr>& ip, int len, int caplen)
bool Discarder::NextPacket(const std::shared_ptr<IP_Hdr>& ip, int len, int caplen)
{
bool discard_packet = false;

View file

@ -26,7 +26,7 @@ public:
bool IsActive();
bool NextPacket(const std::unique_ptr<IP_Hdr>& ip, int len, int caplen);
bool NextPacket(const std::shared_ptr<IP_Hdr>& ip, int len, int caplen);
protected:
Val* BuildData(const u_char* data, int hdrlen, int len, int caplen);

View file

@ -31,7 +31,7 @@ void FragTimer::Dispatch(double t, bool /* is_expire */)
reporter->InternalWarning("fragment timer dispatched w/o reassembler");
}
FragReassembler::FragReassembler(session::Manager* arg_s, const std::unique_ptr<IP_Hdr>& ip,
FragReassembler::FragReassembler(session::Manager* arg_s, const std::shared_ptr<IP_Hdr>& ip,
const u_char* pkt, const FragReassemblerKey& k, double t)
: Reassembler(0, REASSEM_FRAG)
{
@ -74,7 +74,7 @@ FragReassembler::~FragReassembler()
delete[] proto_hdr;
}
void FragReassembler::AddFragment(double t, const std::unique_ptr<IP_Hdr>& ip, const u_char* pkt)
void FragReassembler::AddFragment(double t, const std::shared_ptr<IP_Hdr>& ip, const u_char* pkt)
{
const struct ip* ip4 = ip->IP4_Hdr();
@ -294,7 +294,7 @@ void FragReassembler::BlockInserted(DataBlockMap::const_iterator /* it */)
{
struct ip* reassem4 = (struct ip*)pkt_start;
reassem4->ip_len = htons(frag_size + proto_hdr_len);
reassembled_pkt = std::make_unique<IP_Hdr>(reassem4, true, true);
reassembled_pkt = std::make_shared<IP_Hdr>(reassem4, true, true);
DeleteTimer();
}
@ -303,7 +303,7 @@ void FragReassembler::BlockInserted(DataBlockMap::const_iterator /* it */)
struct ip6_hdr* reassem6 = (struct ip6_hdr*)pkt_start;
reassem6->ip6_plen = htons(frag_size + proto_hdr_len - 40);
const IPv6_Hdr_Chain* chain = new IPv6_Hdr_Chain(reassem6, next_proto, n);
reassembled_pkt = std::make_unique<IP_Hdr>(reassem6, true, n, chain, true);
reassembled_pkt = std::make_shared<IP_Hdr>(reassem6, true, n, chain, true);
DeleteTimer();
}
@ -338,7 +338,7 @@ FragmentManager::~FragmentManager()
Clear();
}
FragReassembler* FragmentManager::NextFragment(double t, const std::unique_ptr<IP_Hdr>& ip,
FragReassembler* FragmentManager::NextFragment(double t, const std::shared_ptr<IP_Hdr>& ip,
const u_char* pkt)
{
uint32_t frag_id = ip->ID();

View file

@ -31,17 +31,17 @@ using FragReassemblerKey = std::tuple<IPAddr, IPAddr, bro_uint_t>;
class FragReassembler : public Reassembler
{
public:
FragReassembler(session::Manager* s, const std::unique_ptr<IP_Hdr>& ip, const u_char* pkt,
FragReassembler(session::Manager* s, const std::shared_ptr<IP_Hdr>& ip, const u_char* pkt,
const FragReassemblerKey& k, double t);
~FragReassembler() override;
void AddFragment(double t, const std::unique_ptr<IP_Hdr>& ip, const u_char* pkt);
void AddFragment(double t, const std::shared_ptr<IP_Hdr>& ip, const u_char* pkt);
void Expire(double t);
void DeleteTimer();
void ClearTimer() { expire_timer = nullptr; }
std::unique_ptr<IP_Hdr> ReassembledPkt() { return std::move(reassembled_pkt); }
std::shared_ptr<IP_Hdr> ReassembledPkt() { return std::move(reassembled_pkt); }
const FragReassemblerKey& Key() const { return key; }
protected:
@ -50,7 +50,7 @@ protected:
void Weird(const char* name) const;
u_char* proto_hdr;
std::unique_ptr<IP_Hdr> reassembled_pkt;
std::shared_ptr<IP_Hdr> reassembled_pkt;
session::Manager* s;
uint64_t frag_size; // size of fully reassembled fragment
FragReassemblerKey key;
@ -81,7 +81,7 @@ public:
FragmentManager() = default;
~FragmentManager();
FragReassembler* NextFragment(double t, const std::unique_ptr<IP_Hdr>& ip, const u_char* pkt);
FragReassembler* NextFragment(double t, const std::shared_ptr<IP_Hdr>& ip, const u_char* pkt);
void Clear();
void Remove(detail::FragReassembler* f);

View file

@ -82,7 +82,7 @@ bool PacketFilter::RemoveDst(Val* dst)
return f != nullptr;
}
bool PacketFilter::Match(const std::unique_ptr<IP_Hdr>& ip, int len, int caplen)
bool PacketFilter::Match(const std::shared_ptr<IP_Hdr>& ip, int len, int caplen)
{
Filter* f = (Filter*)src_filter.Lookup(ip->SrcAddr(), 128);
if ( f )

View file

@ -38,7 +38,7 @@ public:
bool RemoveDst(Val* dst);
// Returns true if packet matches a drop filter
bool Match(const std::unique_ptr<IP_Hdr>& ip, int len, int caplen);
bool Match(const std::shared_ptr<IP_Hdr>& ip, int len, int caplen);
private:
struct Filter

View file

@ -7,6 +7,7 @@
#include <vector>
#include "zeek/ID.h"
#include "zeek/IP.h"
#include "zeek/IPAddr.h"
#include "zeek/NetVar.h"
#include "zeek/UID.h"
@ -66,8 +67,9 @@ public:
* Copy constructor.
*/
EncapsulatingConn(const EncapsulatingConn& other)
: src_addr(other.src_addr), dst_addr(other.dst_addr), src_port(other.src_port),
dst_port(other.dst_port), proto(other.proto), type(other.type), uid(other.uid)
: ip_hdr(other.ip_hdr), src_addr(other.src_addr), dst_addr(other.dst_addr),
src_port(other.src_port), dst_port(other.dst_port), proto(other.proto), type(other.type),
uid(other.uid)
{
}
@ -87,6 +89,7 @@ public:
proto = other.proto;
type = other.type;
uid = other.uid;
ip_hdr = other.ip_hdr;
}
return *this;
@ -127,6 +130,9 @@ public:
return ! (ec1 == ec2);
}
// TODO: temporarily public
std::shared_ptr<IP_Hdr> ip_hdr;
protected:
IPAddr src_addr;
IPAddr dst_addr;
@ -221,6 +227,28 @@ public:
return ! (e1 == e2);
}
/**
* Returns a pointer the last element in the stack. Returns a nullptr
* if the stack is empty or hasn't been initialized yet.
*/
EncapsulatingConn* Last() { return Depth() > 0 ? &(conns->back()) : nullptr; }
/**
* Returns an EncapsulatingConn from the requested index in the stack.
*
* @param index An index to look up. Note this is one-indexed, since it's generally
* looked up using a value from Depth().
* @return The corresponding EncapsulatingConn, or a nullptr if the requested index is
* out of range.
*/
EncapsulatingConn* At(size_t index)
{
if ( index > 0 && index <= Depth() )
return &(conns->at(index - 1));
return nullptr;
}
protected:
std::vector<EncapsulatingConn>* conns;
};

View file

@ -47,7 +47,7 @@ void AYIYA_Analyzer::DeliverPacket(int len, const u_char* data, bool orig, uint6
caplen -= inner_packet_offset;
inner_packet_offset = -1;
std::unique_ptr<IP_Hdr> inner;
std::shared_ptr<IP_Hdr> inner;
int result = packet_analysis::IP::ParsePacket(len, data, next_header, inner);
if ( result == 0 )

View file

@ -46,6 +46,7 @@ void Geneve_Analyzer::DeliverPacket(int len, const u_char* data, bool orig, uint
EncapsulatingConn inner(Conn(), BifEnum::Tunnel::GENEVE);
outer->Add(inner);
int encap_index = outer->Depth();
uint8_t tunnel_opt_len = (data[0] & 0x3F) * 4;
auto vni = (data[4] << 16) + (data[5] << 8) + (data[6] << 0);
@ -83,8 +84,12 @@ void Geneve_Analyzer::DeliverPacket(int len, const u_char* data, bool orig, uint
ProtocolConfirmation();
if ( geneve_packet )
Conn()->EnqueueEvent(geneve_packet, nullptr, ConnVal(), pkt.ip_hdr->ToPktHdrVal(),
val_mgr->Count(vni));
{
EncapsulatingConn* ec = pkt.encap->At(encap_index);
if ( ec && ec->ip_hdr )
Conn()->EnqueueEvent(geneve_packet, nullptr, ConnVal(), pkt.ip_hdr->ToPktHdrVal(),
val_mgr->Count(vni));
}
}
} // namespace zeek::analyzer::geneve

View file

@ -48,7 +48,7 @@ void GTPv1_Analyzer::DeliverPacket(int len, const u_char* data, bool orig, uint6
caplen -= inner_packet_offset;
inner_packet_offset = -1;
std::unique_ptr<IP_Hdr> inner = nullptr;
std::shared_ptr<IP_Hdr> inner = nullptr;
int result = packet_analysis::IP::ParsePacket(len, data, next_header, inner);
if ( result == 0 )

View file

@ -94,7 +94,7 @@ bool TeredoEncapsulation::DoParse(const u_char* data, int& len, bool found_origi
return false;
}
RecordValPtr TeredoEncapsulation::BuildVal(const std::unique_ptr<IP_Hdr>& inner) const
RecordValPtr TeredoEncapsulation::BuildVal(const std::shared_ptr<IP_Hdr>& inner) const
{
static auto teredo_hdr_type = id::find_type<RecordType>("teredo_hdr");
static auto teredo_auth_type = id::find_type<RecordType>("teredo_auth");
@ -164,7 +164,7 @@ void Teredo_Analyzer::DeliverPacket(int len, const u_char* data, bool orig, uint
return;
}
std::unique_ptr<IP_Hdr> inner = nullptr;
std::shared_ptr<IP_Hdr> inner = nullptr;
int rslt = packet_analysis::IP::ParsePacket(len, te.InnerIP(), IPPROTO_IPV6, inner);
if ( rslt > 0 )

View file

@ -75,7 +75,7 @@ public:
const u_char* Authentication() const { return auth; }
RecordValPtr BuildVal(const std::unique_ptr<IP_Hdr>& inner) const;
RecordValPtr BuildVal(const std::shared_ptr<IP_Hdr>& inner) const;
protected:
bool DoParse(const u_char* data, int& len, bool found_orig, bool found_au);

View file

@ -60,6 +60,7 @@ void VXLAN_Analyzer::DeliverPacket(int len, const u_char* data, bool orig, uint6
EncapsulatingConn inner(Conn(), BifEnum::Tunnel::VXLAN);
outer->Add(inner);
int encap_index = outer->Depth();
int vni = (data[4] << 16) + (data[5] << 8) + (data[6] << 0);
@ -88,8 +89,14 @@ void VXLAN_Analyzer::DeliverPacket(int len, const u_char* data, bool orig, uint6
ProtocolConfirmation();
if ( vxlan_packet )
Conn()->EnqueueEvent(vxlan_packet, nullptr, ConnVal(), pkt.ip_hdr->ToPktHdrVal(),
val_mgr->Count(vni));
{
EncapsulatingConn* ec = pkt.encap->At(encap_index);
if ( ec && ec->ip_hdr )
{
Conn()->EnqueueEvent(vxlan_packet, nullptr, ConnVal(), ec->ip_hdr->ToPktHdrVal(),
val_mgr->Count(vni));
}
}
}
} // namespace zeek::analyzer::vxlan

View file

@ -218,7 +218,7 @@ public:
* The IP header for this packet. This is filled in by the IP analyzer
* during processing if the packet contains an IP header.
*/
std::unique_ptr<IP_Hdr> ip_hdr = nullptr;
std::shared_ptr<IP_Hdr> ip_hdr = nullptr;
/**
* The protocol of the packet. This is used by the tunnel analyzers to

View file

@ -72,7 +72,7 @@ void ICMPAnalyzer::DeliverPacket(Connection* c, double t, bool is_orig, int rema
adapter->PacketContents(data + 8, std::min(len, remaining) - 8);
const struct icmp* icmpp = (const struct icmp*)data;
const std::unique_ptr<IP_Hdr>& ip = pkt->ip_hdr;
const std::shared_ptr<IP_Hdr>& ip = pkt->ip_hdr;
if ( ! zeek::detail::ignore_checksums &&
! GetIgnoreChecksumsNets()->Contains(ip->IPHeaderSrcAddr()) && remaining >= len )

View file

@ -51,7 +51,7 @@ bool IPAnalyzer::AnalyzePacket(size_t len, const uint8_t* data, Packet* packet)
// This is a unique pointer because of the mass of early returns from this method.
if ( protocol == 4 )
{
packet->ip_hdr = std::make_unique<IP_Hdr>(ip, false);
packet->ip_hdr = std::make_shared<IP_Hdr>(ip, false);
packet->l3_proto = L3_IPV4;
}
else if ( protocol == 6 )
@ -62,7 +62,7 @@ bool IPAnalyzer::AnalyzePacket(size_t len, const uint8_t* data, Packet* packet)
return false;
}
packet->ip_hdr = std::make_unique<IP_Hdr>((const struct ip6_hdr*)data, false, len);
packet->ip_hdr = std::make_shared<IP_Hdr>((const struct ip6_hdr*)data, false, len);
packet->l3_proto = L3_IPV6;
}
else
@ -71,6 +71,15 @@ bool IPAnalyzer::AnalyzePacket(size_t len, const uint8_t* data, Packet* packet)
return false;
}
// If there's an encapsulation stack in this packet, meaning this packet is part of a chain
// of tunnels, make sure to store the IP header in the last flow in the stack so it can be
// used by previous analyzers as we return up the chain.
if ( packet->encap )
{
if ( auto* ec = packet->encap->Last() )
ec->ip_hdr = packet->ip_hdr;
}
const struct ip* ip4 = packet->ip_hdr->IP4_Hdr();
// TotalLen() returns the full length of the IP portion of the packet, including
@ -164,7 +173,7 @@ bool IPAnalyzer::AnalyzePacket(size_t len, const uint8_t* data, Packet* packet)
{
f = detail::fragment_mgr->NextFragment(run_state::processing_start_time, packet->ip_hdr,
packet->data + hdr_size);
std::unique_ptr<IP_Hdr> ih = f->ReassembledPkt();
std::shared_ptr<IP_Hdr> ih = f->ReassembledPkt();
if ( ! ih )
// It didn't reassemble into anything yet.
@ -275,7 +284,7 @@ bool IPAnalyzer::AnalyzePacket(size_t len, const uint8_t* data, Packet* packet)
}
int zeek::packet_analysis::IP::ParsePacket(int caplen, const u_char* const pkt, int proto,
std::unique_ptr<zeek::IP_Hdr>& inner)
std::shared_ptr<zeek::IP_Hdr>& inner)
{
if ( proto == IPPROTO_IPV6 )
{
@ -283,7 +292,7 @@ int zeek::packet_analysis::IP::ParsePacket(int caplen, const u_char* const pkt,
return -1;
const struct ip6_hdr* ip6 = (const struct ip6_hdr*)pkt;
inner = std::make_unique<zeek::IP_Hdr>(ip6, false, caplen);
inner = std::make_shared<zeek::IP_Hdr>(ip6, false, caplen);
if ( (ip6->ip6_ctlun.ip6_un2_vfc & 0xF0) != 0x60 )
return -2;
}
@ -294,7 +303,7 @@ int zeek::packet_analysis::IP::ParsePacket(int caplen, const u_char* const pkt,
return -1;
const struct ip* ip4 = (const struct ip*)pkt;
inner = std::make_unique<zeek::IP_Hdr>(ip4, false);
inner = std::make_shared<zeek::IP_Hdr>(ip4, false);
if ( ip4->ip_v != 4 )
return -2;
}

View file

@ -57,5 +57,5 @@ private:
* long enough to be an IP header, and \a inner is always non-null
* for other return values.
*/
int ParsePacket(int caplen, const u_char* const pkt, int proto, std::unique_ptr<IP_Hdr>& inner);
int ParsePacket(int caplen, const u_char* const pkt, int proto, std::shared_ptr<IP_Hdr>& inner);
}

View file

@ -32,7 +32,7 @@ bool IPBasedAnalyzer::AnalyzePacket(size_t len, const uint8_t* data, Packet* pkt
if ( ! BuildConnTuple(len, data, pkt, tuple) )
return false;
const std::unique_ptr<IP_Hdr>& ip_hdr = pkt->ip_hdr;
const std::shared_ptr<IP_Hdr>& ip_hdr = pkt->ip_hdr;
detail::ConnKey key(tuple);
Connection* conn = session_mgr->FindConnection(key);

View file

@ -44,7 +44,7 @@ bool IPTunnelAnalyzer::AnalyzePacket(size_t len, const uint8_t* data, Packet* pa
BifEnum::Tunnel::Type tunnel_type = packet->tunnel_type;
int gre_link_type = packet->gre_link_type;
std::unique_ptr<IP_Hdr> inner = nullptr;
std::shared_ptr<IP_Hdr> inner = nullptr;
if ( gre_version != 0 )
{
@ -96,7 +96,7 @@ bool IPTunnelAnalyzer::AnalyzePacket(size_t len, const uint8_t* data, Packet* pa
* Handles a packet that contains an IP header directly after the tunnel header.
*/
bool IPTunnelAnalyzer::ProcessEncapsulatedPacket(double t, const Packet* pkt,
const std::unique_ptr<IP_Hdr>& inner,
const std::shared_ptr<IP_Hdr>& inner,
std::shared_ptr<EncapsulationStack> prev,
const EncapsulatingConn& ec)
{

View file

@ -44,7 +44,7 @@ public:
* @param ec The most-recently found depth of encapsulation.
*/
bool ProcessEncapsulatedPacket(double t, const Packet* pkt,
const std::unique_ptr<IP_Hdr>& inner,
const std::shared_ptr<IP_Hdr>& inner,
std::shared_ptr<EncapsulationStack> prev,
const EncapsulatingConn& ec);

View file

@ -113,7 +113,7 @@ void TCPAnalyzer::DeliverPacket(Connection* c, double t, bool is_orig, int remai
analyzer::tcp::TCP_Endpoint* endpoint = is_orig ? adapter->orig : adapter->resp;
analyzer::tcp::TCP_Endpoint* peer = endpoint->peer;
const std::unique_ptr<IP_Hdr>& ip = pkt->ip_hdr;
const std::shared_ptr<IP_Hdr>& ip = pkt->ip_hdr;
if ( ! ValidateChecksum(ip.get(), tp, endpoint, len, remaining, adapter) )
return;

View file

@ -542,7 +542,7 @@ static int32_t update_last_seq(analyzer::tcp::TCP_Endpoint* endpoint, uint32_t l
}
void TCPSessionAdapter::Process(bool is_orig, const struct tcphdr* tp, int len,
const std::unique_ptr<IP_Hdr>& ip, const u_char* data,
const std::shared_ptr<IP_Hdr>& ip, const u_char* data,
int remaining)
{
analyzer::tcp::TCP_Flags flags(tp);

View file

@ -33,7 +33,7 @@ public:
explicit TCPSessionAdapter(Connection* conn);
~TCPSessionAdapter() override;
void Process(bool is_orig, const struct tcphdr* tp, int len, const std::unique_ptr<IP_Hdr>& ip,
void Process(bool is_orig, const struct tcphdr* tp, int len, const std::shared_ptr<IP_Hdr>& ip,
const u_char* data, int remaining);
void EnableReassembly();

View file

@ -86,7 +86,7 @@ void UDPAnalyzer::DeliverPacket(Connection* c, double t, bool is_orig, int remai
int len = pkt->ip_hdr->PayloadLen();
const struct udphdr* up = (const struct udphdr*)data;
const std::unique_ptr<IP_Hdr>& ip = pkt->ip_hdr;
const std::shared_ptr<IP_Hdr>& ip = pkt->ip_hdr;
adapter->DeliverPacket(len, data, is_orig, -1, ip.get(), remaining);