Added skkippedPacket hook to capture skipped packets during analysis

This commit is contained in:
Siavash Tahmureszadeh 2025-07-25 10:04:11 -07:00
parent 6e2a18ce4f
commit 405f419c4b
7 changed files with 125 additions and 2 deletions

View file

@ -191,6 +191,19 @@ void Analyzer::NextPacket(int len, const u_char* data, bool is_orig, uint64_t se
}
}
void Analyzer::NextSkippedPacket(int len, const u_char* data, bool is_orig, uint64_t seq, const IP_Hdr* ip,
int caplen) {
if ( skip )
return;
SupportAnalyzer* next_sibling = FirstSupportAnalyzer(is_orig);
if ( next_sibling )
next_sibling->NextSkippedPacket(len, data, is_orig, seq, ip, caplen);
else
DeliverSkippedPacket(len, data, is_orig, seq, ip, caplen);
}
void Analyzer::NextStream(int len, const u_char* data, bool is_orig) {
if ( skip )
return;
@ -260,6 +273,27 @@ void Analyzer::ForwardPacket(int len, const u_char* data, bool is_orig, uint64_t
AppendNewChildren();
}
void Analyzer::ForwardSkippedPacket(int len, const u_char* data, bool is_orig, uint64_t seq, const IP_Hdr* ip,
int caplen) {
if ( output_handler )
output_handler->DeliverSkippedPacket(len, data, is_orig, seq, ip, caplen);
AppendNewChildren();
for ( auto i = children.begin(); i != children.end(); ) {
Analyzer* current = *i;
if ( ! (current->finished || current->removing) ) {
current->NextSkippedPacket(len, data, is_orig, seq, ip, caplen);
++i;
}
else
i = DeleteChild(i);
}
AppendNewChildren();
}
void Analyzer::ForwardStream(int len, const u_char* data, bool is_orig) {
if ( output_handler )
output_handler->DeliverStream(len, data, is_orig);
@ -587,6 +621,13 @@ void Analyzer::DeliverPacket(int len, const u_char* data, bool is_orig, uint64_t
len > 40 ? "..." : "");
}
void Analyzer::DeliverSkippedPacket(int len, const u_char* data, bool is_orig, uint64_t seq, const IP_Hdr* ip,
int caplen) {
DBG_LOG(DBG_ANALYZER, "%s DeliverSkippedPacket(%d, %s, %" PRIu64 ", %p, %d) [%s%s]", fmt_analyzer(this).c_str(),
len, is_orig ? "T" : "F", seq, ip, caplen, util::fmt_bytes((const char*)data, min(40, len)),
len > 40 ? "..." : "");
}
void Analyzer::DeliverStream(int len, const u_char* data, bool is_orig) {
DBG_LOG(DBG_ANALYZER, "%s DeliverStream(%d, %s) [%s%s]", fmt_analyzer(this).c_str(), len, is_orig ? "T" : "F",
util::fmt_bytes((const char*)data, min(40, len)), len > 40 ? "..." : "");

View file

@ -69,6 +69,13 @@ public:
*/
virtual void DeliverPacket(int len, const u_char* data, bool orig, uint64_t seq, const IP_Hdr* ip, int caplen) {}
/**
* Hook for receiving skipped packet data. Parameters are the same as for
* Analyzer::DeliverSkippedPacket().
*/
virtual void DeliverSkippedPacket(int len, const u_char* data, bool orig, uint64_t seq, const IP_Hdr* ip,
int caplen) {}
/**
* Hook for receiving stream data. Parameters are the same as for
* Analyzer::DeliverStream().
@ -165,6 +172,29 @@ public:
void NextPacket(int len, const u_char* data, bool is_orig, uint64_t seq = -1, const IP_Hdr* ip = nullptr,
int caplen = 0);
/**
* Passes a skipped packet input to the analyzer for processing. The
* analyzer will process the input with any support analyzers first
* and then forward the data to DeliverSkippedPacket(), which derived
* classes can override.
*
* @param len The number of bytes passed in.
*
* @param data Pointer the input to process.
*
* @param is_orig True if this is originator-side input.
*
* @param seq Current sequence number, if available (only supported
* if the data is coming from the TCP analyzer.
*
* @param ip An IP packet header associated with the data, if
* available.
*
* @param caplen The packet's capture length, if available.
*/
void NextSkippedPacket(int len, const u_char* data, bool is_orig, uint64_t seq = -1, const IP_Hdr* ip = nullptr,
int caplen = 0);
/**
* Passes stream input to the analyzer for processing. The analyzer
* will process the input with any support analyzers first and then
@ -216,6 +246,17 @@ public:
*/
virtual void ForwardPacket(int len, const u_char* data, bool orig, uint64_t seq, const IP_Hdr* ip, int caplen);
/**
* Forwards skipped packet input on to all child analyzers. If the
* analyzer has an associated OutputHandlers, that one receives the
* input as well.
*
* Parameters are the same as for NextSkippedPacket().
*/
virtual void ForwardSkippedPacket(int len, const u_char* data, bool orig, uint64_t seq, const IP_Hdr* ip,
int caplen);
/**
* Forwards stream input on to all child analyzers. If the analyzer
* has an associated OutputHandlers, that one receives the input as
@ -246,6 +287,14 @@ public:
*/
virtual void DeliverPacket(int len, const u_char* data, bool orig, uint64_t seq, const IP_Hdr* ip, int caplen);
/**
* Hook for accessing skipped packet during parsing. This is called by
* NextSkippedPacket and can be overridden by derived classes.
* Parameters are the same.
*/
virtual void DeliverSkippedPacket(int len, const u_char* data, bool orig, uint64_t seq, const IP_Hdr* ip,
int caplen);
/**
* Hook for accessing stream input for parsing. This is called by
* NextStream() and can be overridden by derived classes.

View file

@ -80,6 +80,7 @@ void ICMPAnalyzer::DeliverPacket(Connection* c, double t, bool is_orig, int rema
if ( chksum != 0xffff ) {
adapter->Weird("bad_ICMP_checksum");
adapter->ForwardSkippedPacket(len, data, is_orig, -1, ip.get(), pkt->cap_len);
return;
}
}
@ -103,6 +104,7 @@ void ICMPAnalyzer::DeliverPacket(Connection* c, double t, bool is_orig, int rema
NextICMP6(run_state::current_timestamp, icmpp, len, remaining, data, ip.get(), adapter);
else {
reporter->Error("expected ICMP as IP packet's protocol, got %d", ip->NextProto());
adapter->ForwardSkippedPacket(len, data, is_orig, -1, ip.get(), pkt->cap_len);
return;
}

View file

@ -83,8 +83,10 @@ void TCPAnalyzer::DeliverPacket(Connection* c, double t, bool is_orig, int remai
auto* adapter = static_cast<TCPSessionAdapter*>(c->GetSessionAdapter());
const struct tcphdr* tp = ExtractTCP_Header(data, len, remaining, adapter);
if ( ! tp )
if ( ! tp ) {
adapter->DeliverSkippedPacket(len, data, is_orig, adapter->LastRelDataSeq(), pkt->ip_hdr.get(), pkt->cap_len);
return;
}
// We need the min() here because Ethernet frame padding can lead to
// remaining > len.
@ -95,8 +97,10 @@ void TCPAnalyzer::DeliverPacket(Connection* c, double t, bool is_orig, int remai
analyzer::tcp::TCP_Endpoint* peer = endpoint->peer;
const std::shared_ptr<IP_Hdr>& ip = pkt->ip_hdr;
if ( ! ValidateChecksum(ip.get(), tp, endpoint, len, remaining, adapter) )
if ( ! ValidateChecksum(ip.get(), tp, endpoint, len, remaining, adapter) ) {
adapter->DeliverSkippedPacket(len, data, is_orig, adapter->LastRelDataSeq(), ip.get(), pkt->cap_len);
return;
}
adapter->Process(is_orig, tp, len, ip, data, remaining);

View file

@ -1012,6 +1012,30 @@ void TCPSessionAdapter::DeliverPacket(int len, const u_char* data, bool is_orig,
ForwardPacket(len, data, is_orig, seq, ip, caplen);
}
void TCPSessionAdapter::DeliverSkippedPacket(int len, const u_char* data, bool is_orig, uint64_t seq, const IP_Hdr* ip,
int caplen) {
analyzer::analyzer_list::iterator next;
for ( auto i = packet_children.begin(); i != packet_children.end(); /* nop */ ) {
auto child = *i;
if ( child->IsFinished() || child->Removing() ) {
if ( child->Removing() )
child->Done();
DBG_LOG(DBG_ANALYZER, "%s deleted child %s", fmt_analyzer(this).c_str(), fmt_analyzer(child).c_str());
i = packet_children.erase(i);
delete child;
}
else {
child->NextSkippedPacket(len, data, is_orig, seq, ip, caplen);
++i;
}
}
ForwardSkippedPacket(len, data, is_orig, seq, ip, caplen);
}
void TCPSessionAdapter::DeliverStream(int len, const u_char* data, bool orig) {
Analyzer::DeliverStream(len, data, orig);
}

View file

@ -87,6 +87,8 @@ protected:
void Init() override;
void Done() override;
void DeliverPacket(int len, const u_char* data, bool orig, uint64_t seq, const IP_Hdr* ip, int caplen) override;
void DeliverSkippedPacket(int len, const u_char* data, bool orig, uint64_t seq, const IP_Hdr* ip,
int caplen) override;
void DeliverStream(int len, const u_char* data, bool orig) override;
void Undelivered(uint64_t seq, int len, bool orig) override;
void FlipRoles() override;

View file

@ -126,6 +126,7 @@ void UDPAnalyzer::DeliverPacket(Connection* c, double t, bool is_orig, int remai
if ( bad ) {
adapter->HandleBadChecksum(is_orig);
adapter->ForwardSkippedPacket(len, data, is_orig, -1, ip.get(), pkt->cap_len);
return;
}
}