mirror of
https://github.com/zeek/zeek.git
synced 2025-10-16 05:28:20 +00:00
Move IP and IP tunnel code from Sessions into packet analyzers
This commit is contained in:
parent
69da2d7b1d
commit
1cf251d1ca
53 changed files with 1226 additions and 907 deletions
659
src/Sessions.cc
659
src/Sessions.cc
|
@ -22,7 +22,6 @@
|
|||
|
||||
#include "analyzer/protocol/stepping-stone/SteppingStone.h"
|
||||
#include "analyzer/protocol/stepping-stone/events.bif.h"
|
||||
#include "Discard.h"
|
||||
#include "RuleMatcher.h"
|
||||
|
||||
#include "TunnelEncapsulation.h"
|
||||
|
@ -46,29 +45,6 @@ zeek::NetSessions* zeek::sessions;
|
|||
zeek::NetSessions*& sessions = zeek::sessions;
|
||||
|
||||
namespace zeek {
|
||||
namespace detail {
|
||||
|
||||
void IPTunnelTimer::Dispatch(double t, bool is_expire)
|
||||
{
|
||||
NetSessions::IPTunnelMap::const_iterator it =
|
||||
sessions->ip_tunnels.find(tunnel_idx);
|
||||
|
||||
if ( it == sessions->ip_tunnels.end() )
|
||||
return;
|
||||
|
||||
double last_active = it->second.second;
|
||||
double inactive_time = t > last_active ? t - last_active : 0;
|
||||
|
||||
if ( inactive_time >= BifConst::Tunnel::ip_tunnel_timeout )
|
||||
// tunnel activity timed out, delete it from map
|
||||
sessions->ip_tunnels.erase(tunnel_idx);
|
||||
|
||||
else if ( ! is_expire )
|
||||
// tunnel activity didn't timeout, schedule another timer
|
||||
timer_mgr->Add(new IPTunnelTimer(t, tunnel_idx));
|
||||
}
|
||||
|
||||
} // namespace detail
|
||||
|
||||
NetSessions::NetSessions()
|
||||
{
|
||||
|
@ -77,33 +53,14 @@ NetSessions::NetSessions()
|
|||
else
|
||||
stp_manager = nullptr;
|
||||
|
||||
discarder = new detail::Discarder();
|
||||
if ( ! discarder->IsActive() )
|
||||
{
|
||||
delete discarder;
|
||||
discarder = nullptr;
|
||||
}
|
||||
|
||||
packet_filter = nullptr;
|
||||
|
||||
num_packets_processed = 0;
|
||||
static auto pkt_profile_file = id::find_val("pkt_profile_file");
|
||||
|
||||
if ( detail::pkt_profile_mode && detail::pkt_profile_freq > 0 && pkt_profile_file )
|
||||
pkt_profiler = new detail::PacketProfiler(detail::pkt_profile_mode,
|
||||
detail::pkt_profile_freq,
|
||||
pkt_profile_file->AsFile());
|
||||
else
|
||||
pkt_profiler = nullptr;
|
||||
|
||||
memset(&stats, 0, sizeof(SessionStats));
|
||||
}
|
||||
|
||||
NetSessions::~NetSessions()
|
||||
{
|
||||
delete packet_filter;
|
||||
delete pkt_profiler;
|
||||
delete discarder;
|
||||
delete stp_manager;
|
||||
|
||||
for ( const auto& entry : tcp_conns )
|
||||
|
@ -112,8 +69,8 @@ NetSessions::~NetSessions()
|
|||
Unref(entry.second);
|
||||
for ( const auto& entry : icmp_conns )
|
||||
Unref(entry.second);
|
||||
for ( const auto& entry : fragments )
|
||||
Unref(entry.second);
|
||||
|
||||
detail::fragment_mgr->Clear();
|
||||
}
|
||||
|
||||
void NetSessions::Done()
|
||||
|
@ -122,25 +79,12 @@ void NetSessions::Done()
|
|||
|
||||
void NetSessions::NextPacket(double t, const Packet* pkt)
|
||||
{
|
||||
detail::SegmentProfiler prof(detail::segment_logger, "dispatching-packet");
|
||||
|
||||
if ( raw_packet )
|
||||
event_mgr.Enqueue(raw_packet, pkt->ToRawPktHdrVal());
|
||||
|
||||
if ( pkt_profiler )
|
||||
pkt_profiler->ProfilePkt(t, pkt->cap_len);
|
||||
|
||||
++num_packets_processed;
|
||||
EncapsulationStack* encapsulation = nullptr;
|
||||
auto it = pkt->key_store.find("encap");
|
||||
if ( it != pkt->key_store.end() )
|
||||
encapsulation = std::any_cast<EncapsulationStack*>(*it);
|
||||
|
||||
bool dumped_packet = false;
|
||||
if ( pkt->dump_packet || zeek::detail::record_all_packets )
|
||||
{
|
||||
DumpPacket(pkt);
|
||||
dumped_packet = true;
|
||||
}
|
||||
|
||||
if ( ! pkt->session_analysis )
|
||||
return;
|
||||
|
||||
if ( pkt->hdr_size > pkt->cap_len )
|
||||
{
|
||||
|
@ -158,9 +102,26 @@ void NetSessions::NextPacket(double t, const Packet* pkt)
|
|||
return;
|
||||
}
|
||||
|
||||
auto ip = (const struct ip*) (pkt->data + pkt->hdr_size);
|
||||
IP_Hdr ip_hdr(ip, false);
|
||||
DoNextPacket(t, pkt, &ip_hdr, nullptr);
|
||||
if ( ! encapsulation )
|
||||
{
|
||||
const struct ip* ip = (const struct ip*) (pkt->data + pkt->hdr_size);
|
||||
IP_Hdr ip_hdr(ip, false);
|
||||
DoNextPacket(t, pkt, &ip_hdr, encapsulation);
|
||||
}
|
||||
else
|
||||
{
|
||||
const IP_Hdr* ip_hdr;
|
||||
auto it = pkt->key_store.find("encap_inner_ip");
|
||||
if ( it != pkt->key_store.end() )
|
||||
ip_hdr = std::any_cast<IP_Hdr*>(*it);
|
||||
else
|
||||
{
|
||||
IP_Hdr pkt_ip = pkt->IP();
|
||||
ip_hdr = &pkt_ip;
|
||||
}
|
||||
|
||||
DoNextPacket(t, pkt, ip_hdr, encapsulation);
|
||||
}
|
||||
}
|
||||
|
||||
else if ( pkt->l3_proto == L3_IPV6 )
|
||||
|
@ -171,8 +132,25 @@ void NetSessions::NextPacket(double t, const Packet* pkt)
|
|||
return;
|
||||
}
|
||||
|
||||
IP_Hdr ip_hdr((const struct ip6_hdr*) (pkt->data + pkt->hdr_size), false, caplen);
|
||||
DoNextPacket(t, pkt, &ip_hdr, nullptr);
|
||||
if ( ! encapsulation )
|
||||
{
|
||||
IP_Hdr ip_hdr((const struct ip6_hdr*) (pkt->data + pkt->hdr_size), false, caplen);
|
||||
DoNextPacket(t, pkt, &ip_hdr, encapsulation);
|
||||
}
|
||||
else
|
||||
{
|
||||
const IP_Hdr* ip_hdr = nullptr;
|
||||
auto it = pkt->key_store.find("encap_inner_ip");
|
||||
if ( it != pkt->key_store.end() )
|
||||
ip_hdr = std::any_cast<IP_Hdr*>(*it);
|
||||
else
|
||||
{
|
||||
IP_Hdr pkt_ip = pkt->IP();
|
||||
ip_hdr = &pkt_ip;
|
||||
}
|
||||
|
||||
DoNextPacket(t, pkt, ip_hdr, encapsulation);
|
||||
}
|
||||
}
|
||||
|
||||
else
|
||||
|
@ -180,182 +158,18 @@ void NetSessions::NextPacket(double t, const Packet* pkt)
|
|||
Weird("unknown_packet_type", pkt);
|
||||
return;
|
||||
}
|
||||
|
||||
// Check whether packet should be recorded based on session analysis
|
||||
if ( pkt->dump_packet && ! dumped_packet )
|
||||
DumpPacket(pkt);
|
||||
}
|
||||
|
||||
static unsigned int gre_header_len(uint16_t flags)
|
||||
{
|
||||
unsigned int len = 4; // Always has 2 byte flags and 2 byte protocol type.
|
||||
|
||||
if ( flags & 0x8000 )
|
||||
// Checksum/Reserved1 present.
|
||||
len += 4;
|
||||
|
||||
// Not considering routing presence bit since it's deprecated ...
|
||||
|
||||
if ( flags & 0x2000 )
|
||||
// Key present.
|
||||
len += 4;
|
||||
|
||||
if ( flags & 0x1000 )
|
||||
// Sequence present.
|
||||
len += 4;
|
||||
|
||||
if ( flags & 0x0080 )
|
||||
// Acknowledgement present.
|
||||
len += 4;
|
||||
|
||||
return len;
|
||||
}
|
||||
|
||||
void NetSessions::DoNextPacket(double t, const Packet* pkt, const IP_Hdr* ip_hdr,
|
||||
const EncapsulationStack* encapsulation)
|
||||
{
|
||||
uint32_t caplen = pkt->cap_len - pkt->hdr_size;
|
||||
const struct ip* ip4 = ip_hdr->IP4_Hdr();
|
||||
|
||||
uint32_t len = ip_hdr->TotalLen();
|
||||
if ( len == 0 )
|
||||
{
|
||||
// TCP segmentation offloading can zero out the ip_len field.
|
||||
Weird("ip_hdr_len_zero", pkt, encapsulation);
|
||||
|
||||
// Cope with the zero'd out ip_len field by using the caplen.
|
||||
len = pkt->cap_len - pkt->hdr_size;
|
||||
}
|
||||
|
||||
if ( pkt->len < len + pkt->hdr_size )
|
||||
{
|
||||
Weird("truncated_IP", pkt, encapsulation);
|
||||
return;
|
||||
}
|
||||
|
||||
// For both of these it is safe to pass ip_hdr because the presence
|
||||
// is guaranteed for the functions that pass data to us.
|
||||
uint16_t ip_hdr_len = ip_hdr->HdrLen();
|
||||
if ( ip_hdr_len > len )
|
||||
{
|
||||
Weird("invalid_IP_header_size", ip_hdr, encapsulation);
|
||||
return;
|
||||
}
|
||||
|
||||
if ( ip_hdr_len > caplen )
|
||||
{
|
||||
Weird("internally_truncated_header", ip_hdr, encapsulation);
|
||||
return;
|
||||
}
|
||||
|
||||
if ( ip_hdr->IP4_Hdr() )
|
||||
{
|
||||
if ( ip_hdr_len < sizeof(struct ip) )
|
||||
{
|
||||
Weird("IPv4_min_header_size", pkt);
|
||||
return;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if ( ip_hdr_len < sizeof(struct ip6_hdr) )
|
||||
{
|
||||
Weird("IPv6_min_header_size", pkt);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
// Ignore if packet matches packet filter.
|
||||
if ( packet_filter && packet_filter->Match(ip_hdr, len, caplen) )
|
||||
return;
|
||||
|
||||
if ( ! pkt->l2_checksummed && ! zeek::detail::ignore_checksums && ip4 &&
|
||||
detail::in_cksum(reinterpret_cast<const uint8_t*>(ip4), ip_hdr_len) != 0xffff )
|
||||
{
|
||||
Weird("bad_IP_checksum", pkt, encapsulation);
|
||||
return;
|
||||
}
|
||||
|
||||
if ( discarder && discarder->NextPacket(ip_hdr, len, caplen) )
|
||||
return;
|
||||
|
||||
detail::FragReassembler* f = nullptr;
|
||||
|
||||
if ( ip_hdr->IsFragment() )
|
||||
{
|
||||
pkt->dump_packet = true; // always record fragments
|
||||
|
||||
if ( caplen < len )
|
||||
{
|
||||
Weird("incompletely_captured_fragment", ip_hdr, encapsulation);
|
||||
|
||||
// Don't try to reassemble, that's doomed.
|
||||
// Discard all except the first fragment (which
|
||||
// is useful in analyzing header-only traces)
|
||||
if ( ip_hdr->FragOffset() != 0 )
|
||||
return;
|
||||
}
|
||||
else
|
||||
{
|
||||
f = NextFragment(t, ip_hdr, pkt->data + pkt->hdr_size);
|
||||
const IP_Hdr* ih = f->ReassembledPkt();
|
||||
if ( ! ih )
|
||||
// It didn't reassemble into anything yet.
|
||||
return;
|
||||
|
||||
ip4 = ih->IP4_Hdr();
|
||||
ip_hdr = ih;
|
||||
|
||||
caplen = len = ip_hdr->TotalLen();
|
||||
ip_hdr_len = ip_hdr->HdrLen();
|
||||
|
||||
if ( ip_hdr_len > len )
|
||||
{
|
||||
Weird("invalid_IP_header_size", ip_hdr, encapsulation);
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
detail::FragReassemblerTracker frt(this, f);
|
||||
|
||||
len -= ip_hdr_len; // remove IP header
|
||||
caplen -= ip_hdr_len;
|
||||
caplen -= ip_hdr_len; // remove IP header
|
||||
|
||||
// We stop building the chain when seeing IPPROTO_ESP so if it's
|
||||
// there, it's always the last.
|
||||
if ( ip_hdr->LastHeader() == IPPROTO_ESP )
|
||||
{
|
||||
pkt->dump_packet = true;
|
||||
if ( esp_packet )
|
||||
event_mgr.Enqueue(esp_packet, ip_hdr->ToPktHdrVal());
|
||||
|
||||
// Can't do more since upper-layer payloads are going to be encrypted.
|
||||
return;
|
||||
}
|
||||
|
||||
#ifdef ENABLE_MOBILE_IPV6
|
||||
// We stop building the chain when seeing IPPROTO_MOBILITY so it's always
|
||||
// last if present.
|
||||
if ( ip_hdr->LastHeader() == IPPROTO_MOBILITY )
|
||||
{
|
||||
pkt->dump_packet = true;
|
||||
|
||||
if ( ! ignore_checksums && mobility_header_checksum(ip_hdr) != 0xffff )
|
||||
{
|
||||
Weird("bad_MH_checksum", pkt, encapsulation);
|
||||
return;
|
||||
}
|
||||
|
||||
if ( mobile_ipv6_message )
|
||||
event_mgr.Enqueue(mobile_ipv6_message, ip_hdr->ToPktHdrVal());
|
||||
|
||||
if ( ip_hdr->NextProto() != IPPROTO_NONE )
|
||||
Weird("mobility_piggyback", pkt, encapsulation);
|
||||
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
int proto = ip_hdr->NextProto();
|
||||
|
||||
if ( CheckHeaderTrunc(proto, len, caplen, pkt, encapsulation) )
|
||||
|
@ -368,8 +182,6 @@ void NetSessions::DoNextPacket(double t, const Packet* pkt, const IP_Hdr* ip_hdr
|
|||
id.dst_addr = ip_hdr->DstAddr();
|
||||
ConnectionMap* d = nullptr;
|
||||
BifEnum::Tunnel::Type tunnel_type = BifEnum::Tunnel::IP;
|
||||
int gre_version = -1;
|
||||
int gre_link_type = DLT_RAW;
|
||||
|
||||
switch ( proto ) {
|
||||
case IPPROTO_TCP:
|
||||
|
@ -424,236 +236,6 @@ void NetSessions::DoNextPacket(double t, const Packet* pkt, const IP_Hdr* ip_hdr
|
|||
break;
|
||||
}
|
||||
|
||||
case IPPROTO_GRE:
|
||||
{
|
||||
if ( ! BifConst::Tunnel::enable_gre )
|
||||
{
|
||||
Weird("GRE_tunnel", ip_hdr, encapsulation);
|
||||
return;
|
||||
}
|
||||
|
||||
uint16_t flags_ver = ntohs(*((uint16_t*)(data + 0)));
|
||||
uint16_t proto_typ = ntohs(*((uint16_t*)(data + 2)));
|
||||
gre_version = flags_ver & 0x0007;
|
||||
|
||||
unsigned int eth_len = 0;
|
||||
unsigned int gre_len = gre_header_len(flags_ver);
|
||||
unsigned int ppp_len = gre_version == 1 ? 4 : 0;
|
||||
unsigned int erspan_len = 0;
|
||||
|
||||
if ( gre_version != 0 && gre_version != 1 )
|
||||
{
|
||||
Weird("unknown_gre_version", ip_hdr, encapsulation,
|
||||
util::fmt("%d", gre_version));
|
||||
return;
|
||||
}
|
||||
|
||||
if ( gre_version == 0 )
|
||||
{
|
||||
if ( proto_typ == 0x6558 )
|
||||
{
|
||||
// transparent ethernet bridging
|
||||
if ( len > gre_len + 14 )
|
||||
{
|
||||
eth_len = 14;
|
||||
gre_link_type = DLT_EN10MB;
|
||||
proto_typ = ntohs(*((uint16_t*)(data + gre_len + eth_len - 2)));
|
||||
}
|
||||
else
|
||||
{
|
||||
Weird("truncated_GRE", ip_hdr, encapsulation);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
else if ( proto_typ == 0x88be )
|
||||
{
|
||||
// ERSPAN type II
|
||||
if ( len > gre_len + 14 + 8 )
|
||||
{
|
||||
erspan_len = 8;
|
||||
eth_len = 14;
|
||||
gre_link_type = DLT_EN10MB;
|
||||
proto_typ = ntohs(*((uint16_t*)(data + gre_len + erspan_len + eth_len - 2)));
|
||||
}
|
||||
else
|
||||
{
|
||||
Weird("truncated_GRE", ip_hdr, encapsulation);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
else if ( proto_typ == 0x22eb )
|
||||
{
|
||||
// ERSPAN type III
|
||||
if ( len > gre_len + 14 + 12 )
|
||||
{
|
||||
erspan_len = 12;
|
||||
eth_len = 14;
|
||||
gre_link_type = DLT_EN10MB;
|
||||
|
||||
auto flags = data + gre_len + erspan_len - 1;
|
||||
bool have_opt_header = ((*flags & 0x01) == 0x01);
|
||||
|
||||
if ( have_opt_header )
|
||||
{
|
||||
if ( len > gre_len + erspan_len + 8 + eth_len )
|
||||
erspan_len += 8;
|
||||
else
|
||||
{
|
||||
Weird("truncated_GRE", ip_hdr, encapsulation);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
proto_typ = ntohs(*((uint16_t*)(data + gre_len + erspan_len + eth_len - 2)));
|
||||
}
|
||||
else
|
||||
{
|
||||
Weird("truncated_GRE", ip_hdr, encapsulation);
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
else // gre_version == 1
|
||||
{
|
||||
if ( proto_typ != 0x880b )
|
||||
{
|
||||
// Enhanced GRE payload must be PPP.
|
||||
Weird("egre_protocol_type", ip_hdr, encapsulation,
|
||||
util::fmt("%d", proto_typ));
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
if ( flags_ver & 0x4000 )
|
||||
{
|
||||
// RFC 2784 deprecates the variable length routing field
|
||||
// specified by RFC 1701. It could be parsed here, but easiest
|
||||
// to just skip for now.
|
||||
Weird("gre_routing", ip_hdr, encapsulation);
|
||||
return;
|
||||
}
|
||||
|
||||
if ( flags_ver & 0x0078 )
|
||||
{
|
||||
// Expect last 4 bits of flags are reserved, undefined.
|
||||
Weird("unknown_gre_flags", ip_hdr, encapsulation);
|
||||
return;
|
||||
}
|
||||
|
||||
if ( len < gre_len + ppp_len + eth_len + erspan_len || caplen < gre_len + ppp_len + eth_len + erspan_len )
|
||||
{
|
||||
Weird("truncated_GRE", ip_hdr, encapsulation);
|
||||
return;
|
||||
}
|
||||
|
||||
if ( gre_version == 1 )
|
||||
{
|
||||
uint16_t ppp_proto = ntohs(*((uint16_t*)(data + gre_len + 2)));
|
||||
|
||||
if ( ppp_proto != 0x0021 && ppp_proto != 0x0057 )
|
||||
{
|
||||
Weird("non_ip_packet_in_encap", ip_hdr, encapsulation);
|
||||
return;
|
||||
}
|
||||
|
||||
proto = (ppp_proto == 0x0021) ? IPPROTO_IPV4 : IPPROTO_IPV6;
|
||||
}
|
||||
|
||||
// If we know there's an Ethernet header here, it's not skipped yet.
|
||||
// The Packet::init() that happens later will process all layer 2
|
||||
// data, including things like vlan tags.
|
||||
data += gre_len + ppp_len + erspan_len;
|
||||
len -= gre_len + ppp_len + erspan_len;
|
||||
caplen -= gre_len + ppp_len + erspan_len;
|
||||
|
||||
// Treat GRE tunnel like IP tunnels, fallthrough to logic below now
|
||||
// that GRE header is stripped and only payload packet remains.
|
||||
// The only thing different is the tunnel type enum value to use.
|
||||
tunnel_type = BifEnum::Tunnel::GRE;
|
||||
}
|
||||
|
||||
case IPPROTO_IPV4:
|
||||
case IPPROTO_IPV6:
|
||||
{
|
||||
if ( ! BifConst::Tunnel::enable_ip )
|
||||
{
|
||||
Weird("IP_tunnel", ip_hdr, encapsulation);
|
||||
return;
|
||||
}
|
||||
|
||||
if ( encapsulation &&
|
||||
encapsulation->Depth() >= BifConst::Tunnel::max_depth )
|
||||
{
|
||||
Weird("exceeded_tunnel_max_depth", ip_hdr, encapsulation);
|
||||
return;
|
||||
}
|
||||
|
||||
IP_Hdr* inner = nullptr;
|
||||
|
||||
if ( gre_version != 0 )
|
||||
{
|
||||
// Check for a valid inner packet first.
|
||||
int result = ParseIPPacket(caplen, data, proto, inner);
|
||||
if ( result == -2 )
|
||||
Weird("invalid_inner_IP_version", ip_hdr, encapsulation);
|
||||
else if ( result < 0 )
|
||||
Weird("truncated_inner_IP", ip_hdr, encapsulation);
|
||||
else if ( result > 0 )
|
||||
Weird("inner_IP_payload_length_mismatch", ip_hdr, encapsulation);
|
||||
|
||||
if ( result != 0 )
|
||||
{
|
||||
delete inner;
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
// 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.
|
||||
IPPair tunnel_idx;
|
||||
if ( ip_hdr->SrcAddr() < ip_hdr->DstAddr() )
|
||||
tunnel_idx = IPPair(ip_hdr->SrcAddr(), ip_hdr->DstAddr());
|
||||
else
|
||||
tunnel_idx = IPPair(ip_hdr->DstAddr(), ip_hdr->SrcAddr());
|
||||
|
||||
IPTunnelMap::iterator it = ip_tunnels.find(tunnel_idx);
|
||||
|
||||
if ( it == ip_tunnels.end() )
|
||||
{
|
||||
EncapsulatingConn ec(ip_hdr->SrcAddr(), ip_hdr->DstAddr(),
|
||||
tunnel_type);
|
||||
ip_tunnels[tunnel_idx] = TunnelActivity(ec, run_state::network_time);
|
||||
detail::timer_mgr->Add(new detail::IPTunnelTimer(run_state::network_time, tunnel_idx));
|
||||
}
|
||||
else
|
||||
it->second.second = zeek::run_state::network_time;
|
||||
|
||||
if ( gre_version == 0 )
|
||||
DoNextInnerPacket(t, pkt, caplen, len, data, gre_link_type,
|
||||
encapsulation, ip_tunnels[tunnel_idx].first);
|
||||
else
|
||||
DoNextInnerPacket(t, pkt, inner, encapsulation,
|
||||
ip_tunnels[tunnel_idx].first);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
case IPPROTO_NONE:
|
||||
{
|
||||
// If the packet is encapsulated in Teredo, then it was a bubble and
|
||||
// the Teredo analyzer may have raised an event for that, else we're
|
||||
// not sure the reason for the No Next header in the packet.
|
||||
if ( ! ( encapsulation &&
|
||||
encapsulation->LastType() == BifEnum::Tunnel::TEREDO ) )
|
||||
Weird("ipv6_no_next", pkt);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
default:
|
||||
Weird("unknown_protocol", pkt, encapsulation, util::fmt("%d", proto));
|
||||
return;
|
||||
|
@ -717,15 +299,11 @@ void NetSessions::DoNextPacket(double t, const Packet* pkt, const IP_Hdr* ip_hdr
|
|||
std::move(pkt_hdr_val) : ip_hdr->ToPktHdrVal());
|
||||
|
||||
conn->NextPacket(t, is_orig, ip_hdr, len, caplen, data,
|
||||
record_packet, record_content, pkt);
|
||||
record_packet, record_content, pkt);
|
||||
|
||||
if ( f )
|
||||
{
|
||||
// Above we already recorded the fragment in its entirety.
|
||||
f->DeleteTimer();
|
||||
}
|
||||
|
||||
else if ( record_packet )
|
||||
// We skip this block for reassembled packets because the pointer
|
||||
// math wouldn't work.
|
||||
if ( ! ip_hdr->reassembled && record_packet )
|
||||
{
|
||||
if ( record_content )
|
||||
pkt->dump_packet = true; // save the whole thing
|
||||
|
@ -738,82 +316,6 @@ void NetSessions::DoNextPacket(double t, const Packet* pkt, const IP_Hdr* ip_hdr
|
|||
}
|
||||
}
|
||||
|
||||
void NetSessions::DoNextInnerPacket(double t, const Packet* pkt,
|
||||
const IP_Hdr* inner, const EncapsulationStack* prev,
|
||||
const EncapsulatingConn& ec)
|
||||
{
|
||||
uint32_t caplen, len;
|
||||
caplen = len = inner->TotalLen();
|
||||
|
||||
pkt_timeval ts;
|
||||
int link_type;
|
||||
|
||||
if ( pkt )
|
||||
ts = pkt->ts;
|
||||
else
|
||||
{
|
||||
ts.tv_sec = (time_t) run_state::network_time;
|
||||
ts.tv_usec = (suseconds_t)
|
||||
((run_state::network_time - (double)ts.tv_sec) * 1000000);
|
||||
}
|
||||
|
||||
const u_char* data = nullptr;
|
||||
|
||||
if ( inner->IP4_Hdr() )
|
||||
data = (const u_char*) inner->IP4_Hdr();
|
||||
else
|
||||
data = (const u_char*) inner->IP6_Hdr();
|
||||
|
||||
EncapsulationStack* outer = prev ?
|
||||
new EncapsulationStack(*prev) : new EncapsulationStack();
|
||||
outer->Add(ec);
|
||||
|
||||
// Construct fake packet for DoNextPacket
|
||||
Packet p;
|
||||
p.Init(DLT_RAW, &ts, caplen, len, data, false, "");
|
||||
packet_mgr->ProcessPacket(&p);
|
||||
|
||||
DoNextPacket(t, &p, inner, outer);
|
||||
|
||||
delete inner;
|
||||
delete outer;
|
||||
}
|
||||
|
||||
void NetSessions::DoNextInnerPacket(double t, const Packet* pkt,
|
||||
uint32_t caplen, uint32_t len,
|
||||
const u_char* data, int link_type,
|
||||
const EncapsulationStack* prev,
|
||||
const EncapsulatingConn& ec)
|
||||
{
|
||||
pkt_timeval ts;
|
||||
|
||||
if ( pkt )
|
||||
ts = pkt->ts;
|
||||
else
|
||||
{
|
||||
ts.tv_sec = (time_t) run_state::network_time;
|
||||
ts.tv_usec = (suseconds_t)
|
||||
((run_state::network_time - (double)ts.tv_sec) * 1000000);
|
||||
}
|
||||
|
||||
EncapsulationStack* outer = prev ?
|
||||
new EncapsulationStack(*prev) : new EncapsulationStack();
|
||||
outer->Add(ec);
|
||||
|
||||
// Construct fake packet for DoNextPacket
|
||||
Packet p;
|
||||
p.Init(link_type, &ts, caplen, len, data, false, "");
|
||||
packet_mgr->ProcessPacket(&p);
|
||||
|
||||
if ( p.l2_valid && (p.l3_proto == L3_IPV4 || p.l3_proto == L3_IPV6) )
|
||||
{
|
||||
auto inner = p.IP();
|
||||
DoNextPacket(t, &p, &inner, outer);
|
||||
}
|
||||
|
||||
delete outer;
|
||||
}
|
||||
|
||||
int NetSessions::ParseIPPacket(int caplen, const u_char* const pkt, int proto,
|
||||
IP_Hdr*& inner)
|
||||
{
|
||||
|
@ -862,18 +364,6 @@ bool NetSessions::CheckHeaderTrunc(int proto, uint32_t len, uint32_t caplen,
|
|||
case IPPROTO_UDP:
|
||||
min_hdr_len = sizeof(struct udphdr);
|
||||
break;
|
||||
case IPPROTO_IPV4:
|
||||
min_hdr_len = sizeof(struct ip);
|
||||
break;
|
||||
case IPPROTO_IPV6:
|
||||
min_hdr_len = sizeof(struct ip6_hdr);
|
||||
break;
|
||||
case IPPROTO_NONE:
|
||||
min_hdr_len = 0;
|
||||
break;
|
||||
case IPPROTO_GRE:
|
||||
min_hdr_len = 4;
|
||||
break;
|
||||
case IPPROTO_ICMP:
|
||||
case IPPROTO_ICMPV6:
|
||||
default:
|
||||
|
@ -897,31 +387,6 @@ bool NetSessions::CheckHeaderTrunc(int proto, uint32_t len, uint32_t caplen,
|
|||
return false;
|
||||
}
|
||||
|
||||
detail::FragReassembler* NetSessions::NextFragment(double t, const IP_Hdr* ip,
|
||||
const u_char* pkt)
|
||||
{
|
||||
uint32_t frag_id = ip->ID();
|
||||
|
||||
detail::FragReassemblerKey key = std::make_tuple(ip->SrcAddr(), ip->DstAddr(), frag_id);
|
||||
|
||||
detail::FragReassembler* f = nullptr;
|
||||
auto it = fragments.find(key);
|
||||
if ( it != fragments.end() )
|
||||
f = it->second;
|
||||
|
||||
if ( ! f )
|
||||
{
|
||||
f = new detail::FragReassembler(this, ip, pkt, key, t);
|
||||
fragments[key] = f;
|
||||
if ( fragments.size() > stats.max_fragments )
|
||||
stats.max_fragments = fragments.size();
|
||||
return f;
|
||||
}
|
||||
|
||||
f->AddFragment(t, ip, pkt);
|
||||
return f;
|
||||
}
|
||||
|
||||
Connection* NetSessions::FindConnection(Val* v)
|
||||
{
|
||||
const auto& vt = v->GetType();
|
||||
|
@ -1048,17 +513,6 @@ void NetSessions::Remove(Connection* c)
|
|||
}
|
||||
}
|
||||
|
||||
void NetSessions::Remove(detail::FragReassembler* f)
|
||||
{
|
||||
if ( ! f )
|
||||
return;
|
||||
|
||||
if ( fragments.erase(f->Key()) == 0 )
|
||||
reporter->InternalWarning("fragment reassembler not in dict");
|
||||
|
||||
Unref(f);
|
||||
}
|
||||
|
||||
void NetSessions::Insert(Connection* c)
|
||||
{
|
||||
assert(c->IsKeyValid());
|
||||
|
@ -1135,13 +589,12 @@ void NetSessions::Clear()
|
|||
Unref(entry.second);
|
||||
for ( const auto& entry : icmp_conns )
|
||||
Unref(entry.second);
|
||||
for ( const auto& entry : fragments )
|
||||
Unref(entry.second);
|
||||
|
||||
tcp_conns.clear();
|
||||
udp_conns.clear();
|
||||
icmp_conns.clear();
|
||||
fragments.clear();
|
||||
|
||||
detail::fragment_mgr->Clear();
|
||||
}
|
||||
|
||||
void NetSessions::GetStats(SessionStats& s) const
|
||||
|
@ -1152,13 +605,13 @@ void NetSessions::GetStats(SessionStats& s) const
|
|||
s.cumulative_UDP_conns = stats.cumulative_UDP_conns;
|
||||
s.num_ICMP_conns = icmp_conns.size();
|
||||
s.cumulative_ICMP_conns = stats.cumulative_ICMP_conns;
|
||||
s.num_fragments = fragments.size();
|
||||
s.num_packets = num_packets_processed;
|
||||
s.num_fragments = detail::fragment_mgr->Size();
|
||||
s.num_packets = packet_mgr->PacketsProcessed();
|
||||
|
||||
s.max_TCP_conns = stats.max_TCP_conns;
|
||||
s.max_UDP_conns = stats.max_UDP_conns;
|
||||
s.max_ICMP_conns = stats.max_ICMP_conns;
|
||||
s.max_fragments = stats.max_fragments;
|
||||
s.max_fragments = detail::fragment_mgr->MaxFragments();
|
||||
}
|
||||
|
||||
Connection* NetSessions::NewConn(const detail::ConnIDKey& k, double t, const ConnID* id,
|
||||
|
@ -1393,7 +846,7 @@ unsigned int NetSessions::MemoryAllocation()
|
|||
+ (tcp_conns.size() * (sizeof(ConnectionMap::key_type) + sizeof(ConnectionMap::value_type)))
|
||||
+ (udp_conns.size() * (sizeof(ConnectionMap::key_type) + sizeof(ConnectionMap::value_type)))
|
||||
+ (icmp_conns.size() * (sizeof(ConnectionMap::key_type) + sizeof(ConnectionMap::value_type)))
|
||||
+ (fragments.size() * (sizeof(FragmentMap::key_type) + sizeof(FragmentMap::value_type)))
|
||||
+ detail::fragment_mgr->MemoryAllocation();
|
||||
// FIXME: MemoryAllocation() not implemented for rest.
|
||||
;
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue