mirror of
https://github.com/zeek/zeek.git
synced 2025-10-08 17:48:21 +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
|
@ -69,14 +69,16 @@ public:
|
|||
* in the header. In this case, derived classes may use ForwardPacket() to
|
||||
* forward the payload to the corresponding analyzer.
|
||||
*
|
||||
* @param len The number of bytes passed in.
|
||||
* @param len The number of bytes passed in. As we move along the chain of
|
||||
* analyzers, this is the number of bytes we have left of the packet to
|
||||
* process.
|
||||
* @param data Pointer to the input to process.
|
||||
* @param packet Object that maintains the packet's meta data.
|
||||
*
|
||||
* @return false if the analysis failed, else true.
|
||||
*/
|
||||
virtual bool AnalyzePacket(size_t len, const uint8_t* data,
|
||||
Packet* packet) = 0;
|
||||
Packet* packet) = 0;
|
||||
|
||||
/**
|
||||
* Dumps out debug information to the \c analyzer debug stream.
|
||||
|
@ -124,7 +126,7 @@ protected:
|
|||
* @return false if the analysis failed, else true.
|
||||
*/
|
||||
bool ForwardPacket(size_t len, const uint8_t* data, Packet* packet,
|
||||
uint32_t identifier) const;
|
||||
uint32_t identifier) const;
|
||||
|
||||
/**
|
||||
* Triggers default analysis of the encapsulated packet if the default analyzer
|
||||
|
|
|
@ -4,6 +4,10 @@
|
|||
|
||||
#include "Analyzer.h"
|
||||
#include "Dispatcher.h"
|
||||
#include "zeek-bif.h"
|
||||
#include "Stats.h"
|
||||
#include "zeek/Sessions.h"
|
||||
#include "zeek/RunState.h"
|
||||
|
||||
using namespace zeek::packet_analysis;
|
||||
|
||||
|
@ -12,6 +16,11 @@ Manager::Manager()
|
|||
{
|
||||
}
|
||||
|
||||
Manager::~Manager()
|
||||
{
|
||||
delete pkt_profiler;
|
||||
}
|
||||
|
||||
void Manager::InitPostScript()
|
||||
{
|
||||
// Instantiate objects for all available analyzers
|
||||
|
@ -26,6 +35,13 @@ void Manager::InitPostScript()
|
|||
analyzer->Initialize();
|
||||
|
||||
root_analyzer = analyzers["Root"];
|
||||
|
||||
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());
|
||||
}
|
||||
|
||||
void Manager::Done()
|
||||
|
@ -69,9 +85,37 @@ void Manager::ProcessPacket(Packet* packet)
|
|||
static size_t counter = 0;
|
||||
DBG_LOG(DBG_PACKET_ANALYSIS, "Analyzing packet %ld, ts=%.3f...", ++counter, packet->time);
|
||||
#endif
|
||||
|
||||
zeek::detail::SegmentProfiler prof(detail::segment_logger, "dispatching-packet");
|
||||
if ( pkt_profiler )
|
||||
pkt_profiler->ProfilePkt(zeek::run_state::processing_start_time, packet->cap_len);
|
||||
|
||||
++num_packets_processed;
|
||||
|
||||
bool dumped_packet = false;
|
||||
if ( packet->dump_packet || zeek::detail::record_all_packets )
|
||||
{
|
||||
// TODO: should this stay in Session?
|
||||
sessions->DumpPacket(packet);
|
||||
dumped_packet = true;
|
||||
}
|
||||
|
||||
// Start packet analysis
|
||||
packet->l2_valid = root_analyzer->ForwardPacket(packet->cap_len, packet->data,
|
||||
packet, packet->link_type);
|
||||
|
||||
if ( raw_packet )
|
||||
event_mgr.Enqueue(raw_packet, packet->ToRawPktHdrVal());
|
||||
|
||||
// Check whether packet should be recorded based on session analysis
|
||||
if ( packet->dump_packet && ! dumped_packet )
|
||||
// TODO: should this stay in Session?
|
||||
sessions->DumpPacket(packet);
|
||||
}
|
||||
|
||||
bool Manager::ProcessInnerPacket(Packet* packet)
|
||||
{
|
||||
return root_analyzer->ForwardPacket(packet->cap_len, packet->data, packet, packet->link_type);
|
||||
}
|
||||
|
||||
AnalyzerPtr Manager::InstantiateAnalyzer(const Tag& tag)
|
||||
|
|
|
@ -8,6 +8,8 @@
|
|||
#include "iosource/Packet.h"
|
||||
#include "Dispatcher.h"
|
||||
|
||||
ZEEK_FORWARD_DECLARE_NAMESPACED(PacketProfiler, zeek::detail);
|
||||
|
||||
namespace zeek {
|
||||
namespace packet_analysis {
|
||||
|
||||
|
@ -24,7 +26,7 @@ public:
|
|||
/**
|
||||
* Destructor.
|
||||
*/
|
||||
~Manager() = default;
|
||||
~Manager();
|
||||
|
||||
/**
|
||||
* Second-stage initialization of the manager. This is called late
|
||||
|
@ -69,6 +71,18 @@ public:
|
|||
*/
|
||||
void ProcessPacket(Packet* packet);
|
||||
|
||||
/**
|
||||
* Process the inner packet of an encapsulation. This can be used by tunnel
|
||||
* analyzers to process a inner packet from the "beginning" directly through
|
||||
* the root analyzer. This short-circuits some of the additional processing
|
||||
* that happens in ProcessPacket().
|
||||
*
|
||||
* @param packet The packet to process.
|
||||
*/
|
||||
bool ProcessInnerPacket(Packet* packet);
|
||||
|
||||
uint64_t PacketsProcessed() const { return num_packets_processed; }
|
||||
|
||||
private:
|
||||
/**
|
||||
* Instantiates a new analyzer instance.
|
||||
|
@ -92,6 +106,9 @@ private:
|
|||
|
||||
std::map<std::string, AnalyzerPtr> analyzers;
|
||||
AnalyzerPtr root_analyzer = nullptr;
|
||||
|
||||
uint64_t num_packets_processed = 0;
|
||||
detail::PacketProfiler* pkt_profiler = nullptr;
|
||||
};
|
||||
|
||||
} // namespace packet_analysis
|
||||
|
|
|
@ -15,5 +15,5 @@ add_subdirectory(linux_sll)
|
|||
|
||||
add_subdirectory(arp)
|
||||
add_subdirectory(ip)
|
||||
add_subdirectory(ipv4)
|
||||
add_subdirectory(ipv6)
|
||||
add_subdirectory(gre)
|
||||
add_subdirectory(iptunnel)
|
||||
|
|
|
@ -3,6 +3,6 @@ include(ZeekPlugin)
|
|||
|
||||
include_directories(BEFORE ${CMAKE_CURRENT_SOURCE_DIR} ${CMAKE_CURRENT_BINARY_DIR})
|
||||
|
||||
zeek_plugin_begin(PacketAnalyzer IPv4)
|
||||
zeek_plugin_cc(IPv4.cc Plugin.cc)
|
||||
zeek_plugin_begin(PacketAnalyzer GRE)
|
||||
zeek_plugin_cc(GRE.cc Plugin.cc)
|
||||
zeek_plugin_end()
|
218
src/packet_analysis/protocol/gre/GRE.cc
Normal file
218
src/packet_analysis/protocol/gre/GRE.cc
Normal file
|
@ -0,0 +1,218 @@
|
|||
// See the file "COPYING" in the main distribution directory for copyright.
|
||||
|
||||
#include "GRE.h"
|
||||
#include "zeek/Sessions.h"
|
||||
#include "zeek/RunState.h"
|
||||
#include "zeek/IP.h"
|
||||
#include "zeek/Reporter.h"
|
||||
|
||||
#include "pcap.h" // For DLT_ constants
|
||||
|
||||
using namespace zeek::packet_analysis::GRE;
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
GREAnalyzer::GREAnalyzer()
|
||||
: zeek::packet_analysis::Analyzer("GRE")
|
||||
{
|
||||
}
|
||||
|
||||
bool GREAnalyzer::AnalyzePacket(size_t len, const uint8_t* data, Packet* packet)
|
||||
{
|
||||
EncapsulationStack* encapsulation = nullptr;
|
||||
auto it = packet->key_store.find("encap");
|
||||
if ( it != packet->key_store.end() )
|
||||
encapsulation = std::any_cast<EncapsulationStack*>(it->second);
|
||||
|
||||
it = packet->key_store.find("ip_hdr");
|
||||
if ( it == packet->key_store.end() )
|
||||
{
|
||||
reporter->InternalError("GREAnalyzer: ip_hdr not found in packet keystore");
|
||||
return false;
|
||||
}
|
||||
|
||||
IP_Hdr* ip_hdr = std::any_cast<IP_Hdr*>(it->second);
|
||||
|
||||
int proto = -1;
|
||||
it = packet->key_store.find("proto");
|
||||
if ( it != packet->key_store.end() )
|
||||
proto = std::any_cast<int>(proto);
|
||||
|
||||
if ( ! BifConst::Tunnel::enable_gre )
|
||||
{
|
||||
sessions->Weird("GRE_tunnel", ip_hdr, encapsulation);
|
||||
return false;
|
||||
}
|
||||
|
||||
int gre_link_type = DLT_RAW;
|
||||
|
||||
uint16_t flags_ver = ntohs(*((uint16_t*)(data + 0)));
|
||||
uint16_t proto_typ = ntohs(*((uint16_t*)(data + 2)));
|
||||
int 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 )
|
||||
{
|
||||
sessions->Weird("unknown_gre_version", ip_hdr, encapsulation,
|
||||
util::fmt("%d", gre_version));
|
||||
return false;
|
||||
}
|
||||
|
||||
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
|
||||
{
|
||||
sessions->Weird("truncated_GRE", ip_hdr, encapsulation);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
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
|
||||
{
|
||||
sessions->Weird("truncated_GRE", ip_hdr, encapsulation);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
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
|
||||
{
|
||||
sessions->Weird("truncated_GRE", ip_hdr, encapsulation);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
proto_typ = ntohs(*((uint16_t*)(data + gre_len + erspan_len + eth_len - 2)));
|
||||
}
|
||||
else
|
||||
{
|
||||
sessions->Weird("truncated_GRE", ip_hdr, encapsulation);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
else // gre_version == 1
|
||||
{
|
||||
if ( proto_typ != 0x880b )
|
||||
{
|
||||
// Enhanced GRE payload must be PPP.
|
||||
sessions->Weird("egre_protocol_type", ip_hdr, encapsulation,
|
||||
util::fmt("%d", proto_typ));
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
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.
|
||||
sessions->Weird("gre_routing", ip_hdr, encapsulation);
|
||||
return false;
|
||||
}
|
||||
|
||||
if ( flags_ver & 0x0078 )
|
||||
{
|
||||
// Expect last 4 bits of flags are reserved, undefined.
|
||||
sessions->Weird("unknown_gre_flags", ip_hdr, encapsulation);
|
||||
return false;
|
||||
}
|
||||
|
||||
if ( len < gre_len + ppp_len + eth_len + erspan_len )
|
||||
{
|
||||
sessions->Weird("truncated_GRE", ip_hdr, encapsulation);
|
||||
return false;
|
||||
}
|
||||
|
||||
if ( gre_version == 1 )
|
||||
{
|
||||
uint16_t ppp_proto = ntohs(*((uint16_t*)(data + gre_len + 2)));
|
||||
|
||||
if ( ppp_proto != 0x0021 && ppp_proto != 0x0057 )
|
||||
{
|
||||
sessions->Weird("non_ip_packet_in_encap", ip_hdr, encapsulation);
|
||||
return false;
|
||||
}
|
||||
|
||||
proto = (ppp_proto == 0x0021) ? IPPROTO_IPV4 : IPPROTO_IPV6;
|
||||
}
|
||||
|
||||
data += gre_len + ppp_len + erspan_len;
|
||||
len -= 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.
|
||||
BifEnum::Tunnel::Type tunnel_type = BifEnum::Tunnel::GRE;
|
||||
|
||||
packet->key_store["tunnel_type"] = tunnel_type;
|
||||
packet->key_store["gre_version"] = gre_version;
|
||||
packet->key_store["gre_link_type"] = gre_link_type;
|
||||
packet->key_store["proto"] = proto;
|
||||
|
||||
ForwardPacket(len, data, packet);
|
||||
|
||||
return true;
|
||||
}
|
|
@ -5,18 +5,18 @@
|
|||
#include <packet_analysis/Analyzer.h>
|
||||
#include <packet_analysis/Component.h>
|
||||
|
||||
namespace zeek::packet_analysis::IPv4 {
|
||||
namespace zeek::packet_analysis::GRE {
|
||||
|
||||
class IPv4Analyzer : public Analyzer {
|
||||
class GREAnalyzer : public Analyzer {
|
||||
public:
|
||||
IPv4Analyzer();
|
||||
~IPv4Analyzer() override = default;
|
||||
GREAnalyzer();
|
||||
~GREAnalyzer() override = default;
|
||||
|
||||
bool AnalyzePacket(size_t len, const uint8_t* data, Packet* packet) override;
|
||||
|
||||
static zeek::packet_analysis::AnalyzerPtr Instantiate()
|
||||
{
|
||||
return std::make_shared<IPv4Analyzer>();
|
||||
return std::make_shared<GREAnalyzer>();
|
||||
}
|
||||
};
|
||||
|
|
@ -1,23 +1,24 @@
|
|||
// See the file "COPYING" in the main distribution directory for copyright.
|
||||
|
||||
#include "GRE.h"
|
||||
#include "plugin/Plugin.h"
|
||||
#include "IPv6.h"
|
||||
#include "packet_analysis/Component.h"
|
||||
|
||||
namespace zeek::plugin::Zeek_IPv6 {
|
||||
namespace zeek::plugin::Zeek_GRE {
|
||||
|
||||
class Plugin : public zeek::plugin::Plugin {
|
||||
public:
|
||||
zeek::plugin::Configuration Configure()
|
||||
{
|
||||
AddComponent(new zeek::packet_analysis::Component("IPv6",
|
||||
zeek::packet_analysis::IPv6::IPv6Analyzer::Instantiate));
|
||||
AddComponent(new zeek::packet_analysis::Component("GRE",
|
||||
zeek::packet_analysis::GRE::GREAnalyzer::Instantiate));
|
||||
|
||||
zeek::plugin::Configuration config;
|
||||
config.name = "Zeek::IPv6";
|
||||
config.description = "IPv6 packet analyzer";
|
||||
config.name = "Zeek::GRE";
|
||||
config.description = "GRE packet analyzer";
|
||||
return config;
|
||||
}
|
||||
|
||||
} plugin;
|
||||
|
||||
}
|
|
@ -1,37 +1,274 @@
|
|||
// See the file "COPYING" in the main distribution directory for copyright.
|
||||
|
||||
#include "IP.h"
|
||||
#include "NetVar.h"
|
||||
#include "zeek/NetVar.h"
|
||||
#include "zeek/IP.h"
|
||||
#include "zeek/Discard.h"
|
||||
#include "zeek/PacketFilter.h"
|
||||
#include "zeek/Sessions.h"
|
||||
#include "zeek/RunState.h"
|
||||
#include "zeek/Frag.h"
|
||||
#include "zeek/Event.h"
|
||||
#include "zeek/TunnelEncapsulation.h"
|
||||
|
||||
using namespace zeek::packet_analysis::IP;
|
||||
|
||||
IPAnalyzer::IPAnalyzer()
|
||||
: zeek::packet_analysis::Analyzer("IP")
|
||||
{
|
||||
discarder = new detail::Discarder();
|
||||
if ( ! discarder->IsActive() )
|
||||
{
|
||||
delete discarder;
|
||||
discarder = nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
IPAnalyzer::~IPAnalyzer()
|
||||
{
|
||||
}
|
||||
|
||||
bool IPAnalyzer::AnalyzePacket(size_t len, const uint8_t* data, Packet* packet)
|
||||
{
|
||||
// Assume we're pointing at IP. Just figure out which version.
|
||||
if ( sizeof(struct ip) >= len )
|
||||
EncapsulationStack* encapsulation = nullptr;
|
||||
auto it = packet->key_store.find("encap");
|
||||
if ( it != packet->key_store.end() )
|
||||
encapsulation = std::any_cast<EncapsulationStack*>(it->second);
|
||||
|
||||
// Check to make sure we have enough data left for an IP header to be here. Note we only
|
||||
// check ipv4 here. We'll check ipv6 later once we determine we have an ipv6 header.
|
||||
if ( len < sizeof(struct ip) )
|
||||
{
|
||||
packet->Weird("packet_analyzer_truncated_header");
|
||||
packet->Weird("truncated_IP");
|
||||
return false;
|
||||
}
|
||||
|
||||
// TODO: i feel like this could be generated as we move along the header hierarchy.
|
||||
// TODO: the sessions code expects that the header size does not include the ip header. Should
|
||||
// this change?
|
||||
packet->hdr_size = static_cast<int32_t>(data - packet->data);
|
||||
|
||||
// Cast the current data pointer to an IP header pointer so we can use it to get some
|
||||
// data about the header.
|
||||
auto ip = (const struct ip *)data;
|
||||
uint32_t protocol = ip->ip_v;
|
||||
|
||||
auto inner_analyzer = Lookup(protocol);
|
||||
if ( inner_analyzer == nullptr )
|
||||
std::unique_ptr<IP_Hdr> ip_hdr = nullptr;
|
||||
if ( protocol == 4 )
|
||||
{
|
||||
DBG_LOG(DBG_PACKET_ANALYSIS, "Analysis in %s failed, could not find analyzer for identifier %#x.",
|
||||
GetAnalyzerName(), protocol);
|
||||
packet->Weird("no_suitable_analyzer_found");
|
||||
ip_hdr = std::make_unique<IP_Hdr>(ip, false);
|
||||
packet->l3_proto = L3_IPV4;
|
||||
}
|
||||
else if ( protocol == 6 )
|
||||
{
|
||||
if ( len < sizeof(struct ip6_hdr) )
|
||||
{
|
||||
packet->Weird("truncated_IP");
|
||||
return false;
|
||||
}
|
||||
|
||||
ip_hdr = std::make_unique<IP_Hdr>((const struct ip6_hdr*) data, false, len);
|
||||
packet->l3_proto = L3_IPV6;
|
||||
}
|
||||
else
|
||||
{
|
||||
packet->Weird("unknown_ip_version");
|
||||
return false;
|
||||
}
|
||||
|
||||
DBG_LOG(DBG_PACKET_ANALYSIS, "Analysis in %s succeeded, next layer identifier is %#x.",
|
||||
GetAnalyzerName(), protocol);
|
||||
return inner_analyzer->AnalyzePacket(len, data, packet);
|
||||
}
|
||||
const struct ip* ip4 = ip_hdr->IP4_Hdr();
|
||||
|
||||
// total_len is the length of the packet minus all of the headers so far, including IP
|
||||
uint32_t total_len = ip_hdr->TotalLen();
|
||||
if ( total_len == 0 )
|
||||
{
|
||||
// TCP segmentation offloading can zero out the ip_len field.
|
||||
packet->Weird("ip_hdr_len_zero", encapsulation);
|
||||
|
||||
// Cope with the zero'd out ip_len field by using the caplen.
|
||||
total_len = packet->cap_len - packet->hdr_size;
|
||||
}
|
||||
|
||||
if ( packet->len < total_len + packet->hdr_size )
|
||||
{
|
||||
packet->Weird("truncated_IP", encapsulation);
|
||||
return false;
|
||||
}
|
||||
|
||||
// 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 > total_len )
|
||||
{
|
||||
sessions->Weird("invalid_IP_header_size", ip_hdr.get(), encapsulation);
|
||||
return false;
|
||||
}
|
||||
|
||||
if ( ip_hdr_len > len )
|
||||
{
|
||||
sessions->Weird("internally_truncated_header", ip_hdr.get(), encapsulation);
|
||||
return false;
|
||||
}
|
||||
|
||||
if ( ip_hdr->IP4_Hdr() )
|
||||
{
|
||||
if ( ip_hdr_len < sizeof(struct ip) )
|
||||
{
|
||||
packet->Weird("IPv4_min_header_size");
|
||||
return false;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if ( ip_hdr_len < sizeof(struct ip6_hdr) )
|
||||
{
|
||||
packet->Weird("IPv6_min_header_size");
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
// Ignore if packet matches packet filter.
|
||||
detail::PacketFilter* packet_filter = sessions->GetPacketFilter(false);
|
||||
if ( packet_filter && packet_filter->Match(ip_hdr.get(), total_len, len) )
|
||||
return false;
|
||||
|
||||
if ( ! packet->l2_checksummed && ! detail::ignore_checksums && ip4 &&
|
||||
detail::in_cksum(reinterpret_cast<const uint8_t*>(ip4), ip_hdr_len) != 0xffff )
|
||||
{
|
||||
sessions->Weird("bad_IP_checksum", packet, encapsulation);
|
||||
return false;
|
||||
}
|
||||
|
||||
if ( discarder && discarder->NextPacket(ip_hdr.get(), total_len, len) )
|
||||
return false;
|
||||
|
||||
detail::FragReassembler* f = nullptr;
|
||||
|
||||
if ( ip_hdr->IsFragment() )
|
||||
{
|
||||
packet->dump_packet = true; // always record fragments
|
||||
|
||||
if ( len < total_len )
|
||||
{
|
||||
sessions->Weird("incompletely_captured_fragment", ip_hdr.get(), 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 false;
|
||||
}
|
||||
else
|
||||
{
|
||||
f = detail::fragment_mgr->NextFragment(run_state::processing_start_time, ip_hdr.get(), packet->data + packet->hdr_size);
|
||||
IP_Hdr* ih = f->ReassembledPkt();
|
||||
if ( ! ih )
|
||||
// It didn't reassemble into anything yet.
|
||||
return true;
|
||||
|
||||
ip4 = ih->IP4_Hdr();
|
||||
|
||||
// Delete the old ip_hdr and replace it with this one.
|
||||
ip_hdr.reset(ih);
|
||||
|
||||
len = total_len = ip_hdr->TotalLen();
|
||||
ip_hdr_len = ip_hdr->HdrLen();
|
||||
packet->cap_len = total_len + packet->hdr_size;
|
||||
|
||||
// TODO: in the old code, the data pointer is updated to point at the IP header's
|
||||
// payload, so it contains all of the data when it's processed. This isn't a big
|
||||
// deal for when we pass it down into the session analyzers, since that does the
|
||||
// same itself. should it be updated here for the case where a fragmented packet
|
||||
// is actually tunneled? is that a thing that can happen? Does updating the data
|
||||
// pointer without also updating the one in packet cause any problems?
|
||||
|
||||
if ( ip_hdr_len > total_len )
|
||||
{
|
||||
sessions->Weird("invalid_IP_header_size", ip_hdr.get(), encapsulation);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
detail::FragReassemblerTracker frt(f);
|
||||
|
||||
// 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 )
|
||||
{
|
||||
packet->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 true;
|
||||
}
|
||||
|
||||
#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 )
|
||||
{
|
||||
dump_this_packet = true;
|
||||
|
||||
if ( ! ignore_checksums && mobility_header_checksum(ip_hdr) != 0xffff )
|
||||
{
|
||||
sessions->Weird("bad_MH_checksum", packet, encapsulation);
|
||||
return false;
|
||||
}
|
||||
|
||||
if ( mobile_ipv6_message )
|
||||
event_mgr.Enqueue(mobile_ipv6_message, ip_hdr->ToPktHdrVal());
|
||||
|
||||
if ( ip_hdr->NextProto() != IPPROTO_NONE )
|
||||
sessions->Weird("mobility_piggyback", packet, encapsulation);
|
||||
|
||||
return true;
|
||||
}
|
||||
#endif
|
||||
|
||||
// Advance the data pointer past the IP header based on the header length
|
||||
data += ip_hdr_len;
|
||||
len -= ip_hdr_len;
|
||||
|
||||
bool return_val = true;
|
||||
int proto = ip_hdr->NextProto();
|
||||
|
||||
packet->key_store["ip_hdr"] = ip_hdr.get();
|
||||
packet->key_store["proto"] = proto;
|
||||
|
||||
switch ( proto ) {
|
||||
case IPPROTO_TCP:
|
||||
case IPPROTO_UDP:
|
||||
case IPPROTO_ICMP:
|
||||
case IPPROTO_ICMPV6:
|
||||
sessions->DoNextPacket(run_state::processing_start_time, packet, ip_hdr.get(), encapsulation);
|
||||
break;
|
||||
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 ) )
|
||||
{
|
||||
sessions->Weird("ipv6_no_next", packet);
|
||||
return_val = false;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
// For everything else, pass it on to another analyzer. If there's no one to handle that,
|
||||
// it'll report a Weird.
|
||||
return_val = ForwardPacket(len, data, packet, proto);
|
||||
break;
|
||||
}
|
||||
|
||||
if ( f )
|
||||
{
|
||||
// If this was a fragment, we need to release the pointer here so that it doesn't get
|
||||
// deleted. Deleting this one will be the responsibility of the fragment tracker.
|
||||
ip_hdr.release();
|
||||
f->DeleteTimer();
|
||||
}
|
||||
|
||||
return return_val;
|
||||
}
|
||||
|
|
|
@ -2,15 +2,18 @@
|
|||
|
||||
#pragma once
|
||||
|
||||
#include <packet_analysis/Analyzer.h>
|
||||
#include <packet_analysis/Component.h>
|
||||
#include "zeek/packet_analysis/Analyzer.h"
|
||||
#include "zeek/packet_analysis/Component.h"
|
||||
#include "zeek/Frag.h"
|
||||
|
||||
ZEEK_FORWARD_DECLARE_NAMESPACED(Discarder, zeek::detail);
|
||||
|
||||
namespace zeek::packet_analysis::IP {
|
||||
|
||||
class IPAnalyzer : public Analyzer {
|
||||
public:
|
||||
IPAnalyzer();
|
||||
~IPAnalyzer() override = default;
|
||||
~IPAnalyzer() override;
|
||||
|
||||
bool AnalyzePacket(size_t len, const uint8_t* data, Packet* packet) override;
|
||||
|
||||
|
@ -18,6 +21,15 @@ public:
|
|||
{
|
||||
return std::make_shared<IPAnalyzer>();
|
||||
}
|
||||
|
||||
private:
|
||||
|
||||
// Returns a reassembled packet, or nil if there are still
|
||||
// some missing fragments.
|
||||
zeek::detail::FragReassembler* NextFragment(double t, const IP_Hdr* ip,
|
||||
const u_char* pkt);
|
||||
|
||||
zeek::detail::Discarder* discarder = nullptr;
|
||||
};
|
||||
|
||||
}
|
||||
|
|
|
@ -3,6 +3,6 @@ include(ZeekPlugin)
|
|||
|
||||
include_directories(BEFORE ${CMAKE_CURRENT_SOURCE_DIR} ${CMAKE_CURRENT_BINARY_DIR})
|
||||
|
||||
zeek_plugin_begin(PacketAnalyzer IPv6)
|
||||
zeek_plugin_cc(IPv6.cc Plugin.cc)
|
||||
zeek_plugin_begin(PacketAnalyzer IPTunnel)
|
||||
zeek_plugin_cc(IPTunnel.cc Plugin.cc)
|
||||
zeek_plugin_end()
|
238
src/packet_analysis/protocol/iptunnel/IPTunnel.cc
Normal file
238
src/packet_analysis/protocol/iptunnel/IPTunnel.cc
Normal file
|
@ -0,0 +1,238 @@
|
|||
// See the file "COPYING" in the main distribution directory for copyright.
|
||||
|
||||
#include "IPTunnel.h"
|
||||
#include "zeek/Sessions.h"
|
||||
#include "zeek/RunState.h"
|
||||
#include "zeek/IP.h"
|
||||
#include "zeek/TunnelEncapsulation.h"
|
||||
|
||||
#include "pcap.h" // For DLT_ constants
|
||||
|
||||
namespace zeek::packet_analysis::IPTunnel {
|
||||
|
||||
IPTunnelAnalyzer* ip_tunnel_analyzer;
|
||||
|
||||
IPTunnelAnalyzer::IPTunnelAnalyzer()
|
||||
: zeek::packet_analysis::Analyzer("IPTunnel")
|
||||
{
|
||||
ip_tunnel_analyzer = this;
|
||||
}
|
||||
|
||||
bool IPTunnelAnalyzer::AnalyzePacket(size_t len, const uint8_t* data, Packet* packet)
|
||||
{
|
||||
EncapsulationStack* encapsulation = nullptr;
|
||||
auto it = packet->key_store.find("encap");
|
||||
if ( it != packet->key_store.end() )
|
||||
encapsulation = std::any_cast<EncapsulationStack*>(it->second);
|
||||
|
||||
it = packet->key_store.find("ip_hdr");
|
||||
if ( it == packet->key_store.end() )
|
||||
{
|
||||
reporter->InternalError("IPTunnelAnalyzer: ip_hdr not found in packet keystore");
|
||||
return false;
|
||||
}
|
||||
|
||||
IP_Hdr* ip_hdr = std::any_cast<IP_Hdr*>(it->second);
|
||||
|
||||
int proto = -1;
|
||||
it = packet->key_store.find("proto");
|
||||
if ( it != packet->key_store.end() )
|
||||
proto = std::any_cast<int>(it->second);
|
||||
|
||||
int gre_version = -1;
|
||||
it = packet->key_store.find("gre_version");
|
||||
if ( it != packet->key_store.end() )
|
||||
gre_version = std::any_cast<int>(it->second);
|
||||
|
||||
BifEnum::Tunnel::Type tunnel_type = BifEnum::Tunnel::IP;
|
||||
it = packet->key_store.find("tunnel_type");
|
||||
if ( it != packet->key_store.end() )
|
||||
tunnel_type = std::any_cast<BifEnum::Tunnel::Type>(it->second);
|
||||
|
||||
int gre_link_type = DLT_RAW;
|
||||
it = packet->key_store.find("gre_link_type");
|
||||
if ( it != packet->key_store.end() )
|
||||
gre_link_type = std::any_cast<int>(it->second);
|
||||
|
||||
if ( ! BifConst::Tunnel::enable_ip )
|
||||
{
|
||||
sessions->Weird("IP_tunnel", ip_hdr, encapsulation);
|
||||
return false;
|
||||
}
|
||||
|
||||
if ( encapsulation &&
|
||||
encapsulation->Depth() >= BifConst::Tunnel::max_depth )
|
||||
{
|
||||
sessions->Weird("exceeded_tunnel_max_depth", ip_hdr, encapsulation);
|
||||
return false;
|
||||
}
|
||||
|
||||
IP_Hdr* inner = nullptr;
|
||||
|
||||
if ( gre_version != 0 )
|
||||
{
|
||||
// Check for a valid inner packet first.
|
||||
int result = sessions->ParseIPPacket(len, data, proto, inner);
|
||||
if ( result == -2 )
|
||||
sessions->Weird("invalid_inner_IP_version", ip_hdr, encapsulation);
|
||||
else if ( result < 0 )
|
||||
sessions->Weird("truncated_inner_IP", ip_hdr, encapsulation);
|
||||
else if ( result > 0 )
|
||||
sessions->Weird("inner_IP_payload_length_mismatch", ip_hdr, encapsulation);
|
||||
|
||||
if ( result != 0 )
|
||||
{
|
||||
delete inner;
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
// 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 tunnel_it = ip_tunnels.find(tunnel_idx);
|
||||
|
||||
if ( tunnel_it == ip_tunnels.end() )
|
||||
{
|
||||
EncapsulatingConn ec(ip_hdr->SrcAddr(), ip_hdr->DstAddr(),
|
||||
tunnel_type);
|
||||
ip_tunnels[tunnel_idx] = TunnelActivity(ec, run_state::network_time);
|
||||
zeek::detail::timer_mgr->Add(new detail::IPTunnelTimer(run_state::network_time, tunnel_idx, this));
|
||||
}
|
||||
else
|
||||
tunnel_it->second.second = zeek::run_state::network_time;
|
||||
|
||||
if ( gre_version == 0 )
|
||||
ProcessEncapsulatedPacket(run_state::processing_start_time, packet, len, len, data, gre_link_type,
|
||||
encapsulation, ip_tunnels[tunnel_idx].first);
|
||||
else
|
||||
ProcessEncapsulatedPacket(run_state::processing_start_time, packet, inner, encapsulation,
|
||||
ip_tunnels[tunnel_idx].first);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Handles a packet that contains an IP header directly after the tunnel header.
|
||||
*/
|
||||
bool IPTunnelAnalyzer::ProcessEncapsulatedPacket(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, "");
|
||||
p.key_store["encap"] = outer;
|
||||
p.key_store["encap_inner_ip"] = inner;
|
||||
|
||||
// Forward the packet back to the IP analyzer.
|
||||
bool return_val = ForwardPacket(len, data, &p);
|
||||
|
||||
delete inner;
|
||||
delete outer;
|
||||
|
||||
return return_val;
|
||||
}
|
||||
|
||||
/**
|
||||
* Handles a packet that contains a physical-layer header after the tunnel header.
|
||||
*/
|
||||
bool IPTunnelAnalyzer::ProcessEncapsulatedPacket(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, "");
|
||||
p.key_store["encap"] = outer;
|
||||
|
||||
// Process the packet as if it was a brand new packet by passing it back
|
||||
// to the packet manager.
|
||||
bool return_val = packet_mgr->ProcessInnerPacket(&p);
|
||||
|
||||
delete outer;
|
||||
|
||||
return return_val;
|
||||
}
|
||||
|
||||
namespace detail {
|
||||
|
||||
IPTunnelTimer::IPTunnelTimer(double t, IPTunnelAnalyzer::IPPair p, IPTunnelAnalyzer* analyzer)
|
||||
: Timer(t + BifConst::Tunnel::ip_tunnel_timeout,
|
||||
zeek::detail::TIMER_IP_TUNNEL_INACTIVITY),
|
||||
tunnel_idx(p), analyzer(analyzer)
|
||||
{
|
||||
}
|
||||
|
||||
void IPTunnelTimer::Dispatch(double t, bool is_expire)
|
||||
{
|
||||
IPTunnelAnalyzer::IPTunnelMap::const_iterator it =
|
||||
analyzer->ip_tunnels.find(tunnel_idx);
|
||||
|
||||
if ( it == analyzer->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
|
||||
analyzer->ip_tunnels.erase(tunnel_idx);
|
||||
|
||||
else if ( ! is_expire )
|
||||
// tunnel activity didn't timeout, schedule another timer
|
||||
zeek::detail::timer_mgr->Add(new IPTunnelTimer(t, tunnel_idx, analyzer));
|
||||
}
|
||||
|
||||
} // namespace detail
|
||||
|
||||
} // namespace zeek::packet_analysis::IPTunnel
|
98
src/packet_analysis/protocol/iptunnel/IPTunnel.h
Normal file
98
src/packet_analysis/protocol/iptunnel/IPTunnel.h
Normal file
|
@ -0,0 +1,98 @@
|
|||
// See the file "COPYING" in the main distribution directory for copyright.
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <packet_analysis/Analyzer.h>
|
||||
#include <packet_analysis/Component.h>
|
||||
#include "zeek/IPAddr.h"
|
||||
#include "zeek/TunnelEncapsulation.h"
|
||||
|
||||
namespace zeek::packet_analysis::IPTunnel {
|
||||
|
||||
namespace detail { class IPTunnelTimer; }
|
||||
|
||||
class IPTunnelAnalyzer : public Analyzer {
|
||||
public:
|
||||
|
||||
IPTunnelAnalyzer();
|
||||
~IPTunnelAnalyzer() override = default;
|
||||
|
||||
bool AnalyzePacket(size_t len, const uint8_t* data, Packet* packet) override;
|
||||
|
||||
static zeek::packet_analysis::AnalyzerPtr Instantiate()
|
||||
{
|
||||
return std::make_shared<IPTunnelAnalyzer>();
|
||||
}
|
||||
|
||||
/**
|
||||
* Wrapper that handles encapsulated IP packets and passes them back into
|
||||
* packet analysis.
|
||||
*
|
||||
* @param t Network time.
|
||||
* @param pkt If the outer pcap header is available, this pointer can be set
|
||||
* 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 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.
|
||||
*/
|
||||
bool ProcessEncapsulatedPacket(double t, const Packet *pkt,
|
||||
const IP_Hdr* inner, const EncapsulationStack* prev,
|
||||
const EncapsulatingConn& ec);
|
||||
|
||||
/**
|
||||
* Wrapper that handles encapsulated Ethernet/IP packets and passes them back into
|
||||
* packet analysis.
|
||||
*
|
||||
* @param t Network time.
|
||||
* @param pkt If the outer pcap header is available, this pointer can be
|
||||
* set so that the fake pcap header passed to DoNextPacket will use
|
||||
* the same timeval.
|
||||
* @param caplen number of captured bytes remaining
|
||||
* @param len number of bytes remaining as claimed by outer framing
|
||||
* @param data the remaining packet data
|
||||
* @param link_type layer 2 link type used for initializing inner packet
|
||||
* @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.
|
||||
*/
|
||||
bool ProcessEncapsulatedPacket(double t, const Packet* pkt,
|
||||
uint32_t caplen, uint32_t len,
|
||||
const u_char* data, int link_type,
|
||||
const EncapsulationStack* prev,
|
||||
const EncapsulatingConn& ec);
|
||||
|
||||
protected:
|
||||
|
||||
friend class detail::IPTunnelTimer;
|
||||
|
||||
using IPPair = std::pair<IPAddr, IPAddr>;
|
||||
using TunnelActivity = std::pair<EncapsulatingConn, double>;
|
||||
using IPTunnelMap = std::map<IPPair, TunnelActivity>;
|
||||
IPTunnelMap ip_tunnels;
|
||||
|
||||
};
|
||||
|
||||
namespace detail {
|
||||
|
||||
class IPTunnelTimer final : public zeek::detail::Timer {
|
||||
public:
|
||||
IPTunnelTimer(double t, IPTunnelAnalyzer::IPPair p, IPTunnelAnalyzer* analyzer);
|
||||
~IPTunnelTimer() override = default;
|
||||
|
||||
void Dispatch(double t, bool is_expire) override;
|
||||
|
||||
protected:
|
||||
IPTunnelAnalyzer::IPPair tunnel_idx;
|
||||
IPTunnelAnalyzer* analyzer;
|
||||
};
|
||||
|
||||
} // namespace detail
|
||||
|
||||
// This is temporary until the TCP and UDP analyzers are moved to be packet analyzers.
|
||||
extern IPTunnelAnalyzer* ip_tunnel_analyzer;
|
||||
|
||||
}
|
|
@ -1,21 +1,21 @@
|
|||
// See the file "COPYING" in the main distribution directory for copyright.
|
||||
|
||||
#include "IPv4.h"
|
||||
#include "IPTunnel.h"
|
||||
#include "plugin/Plugin.h"
|
||||
#include "packet_analysis/Component.h"
|
||||
|
||||
namespace zeek::plugin::Zeek_IPv4 {
|
||||
namespace zeek::plugin::Zeek_IPTunnel {
|
||||
|
||||
class Plugin : public zeek::plugin::Plugin {
|
||||
public:
|
||||
zeek::plugin::Configuration Configure()
|
||||
{
|
||||
AddComponent(new zeek::packet_analysis::Component("IPv4",
|
||||
zeek::packet_analysis::IPv4::IPv4Analyzer::Instantiate));
|
||||
AddComponent(new zeek::packet_analysis::Component("IPTunnel",
|
||||
zeek::packet_analysis::IPTunnel::IPTunnelAnalyzer::Instantiate));
|
||||
|
||||
zeek::plugin::Configuration config;
|
||||
config.name = "Zeek::IPv4";
|
||||
config.description = "IPv4 packet analyzer";
|
||||
config.name = "Zeek::IPTunnel";
|
||||
config.description = "IPTunnel packet analyzer";
|
||||
return config;
|
||||
}
|
||||
|
|
@ -1,20 +0,0 @@
|
|||
// See the file "COPYING" in the main distribution directory for copyright.
|
||||
|
||||
#include "IPv4.h"
|
||||
|
||||
using namespace zeek::packet_analysis::IPv4;
|
||||
|
||||
IPv4Analyzer::IPv4Analyzer()
|
||||
: zeek::packet_analysis::Analyzer("IPv4")
|
||||
{
|
||||
}
|
||||
|
||||
bool IPv4Analyzer::AnalyzePacket(size_t len, const uint8_t* data, Packet* packet)
|
||||
{
|
||||
packet->l3_proto = L3_IPV4;
|
||||
packet->hdr_size = static_cast<uint32_t>(data - packet->data);
|
||||
packet->session_analysis = true;
|
||||
|
||||
// Leave packet analyzer land
|
||||
return true;
|
||||
}
|
|
@ -1,20 +0,0 @@
|
|||
// See the file "COPYING" in the main distribution directory for copyright.
|
||||
|
||||
#include "IPv6.h"
|
||||
|
||||
using namespace zeek::packet_analysis::IPv6;
|
||||
|
||||
IPv6Analyzer::IPv6Analyzer()
|
||||
: zeek::packet_analysis::Analyzer("IPv6")
|
||||
{
|
||||
}
|
||||
|
||||
bool IPv6Analyzer::AnalyzePacket(size_t len, const uint8_t* data, Packet* packet)
|
||||
{
|
||||
packet->l3_proto = L3_IPV6;
|
||||
packet->hdr_size = static_cast<uint32_t>(data - packet->data);
|
||||
packet->session_analysis = true;
|
||||
|
||||
// Leave packet analyzer land
|
||||
return true;
|
||||
}
|
|
@ -1,23 +0,0 @@
|
|||
// See the file "COPYING" in the main distribution directory for copyright.
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <packet_analysis/Analyzer.h>
|
||||
#include <packet_analysis/Component.h>
|
||||
|
||||
namespace zeek::packet_analysis::IPv6 {
|
||||
|
||||
class IPv6Analyzer : public Analyzer {
|
||||
public:
|
||||
IPv6Analyzer();
|
||||
~IPv6Analyzer() override = default;
|
||||
|
||||
bool AnalyzePacket(size_t len, const uint8_t* data, Packet* packet) override;
|
||||
|
||||
static AnalyzerPtr Instantiate()
|
||||
{
|
||||
return std::make_shared<IPv6Analyzer>();
|
||||
}
|
||||
};
|
||||
|
||||
}
|
Loading…
Add table
Add a link
Reference in a new issue