Add an option to ignore packets sourced from particular subnets.

It's implemented with a new set[subnet] option named ignore_checksums_nets.

If you populate this set with subnets, any packet with a src address within
that set of subnets will not have it's checksum validated.
This commit is contained in:
Seth Hall 2020-10-14 16:51:30 -04:00
parent e4df60c51d
commit 552a24e07c
12 changed files with 63 additions and 9 deletions

View file

@ -1991,6 +1991,11 @@ ValPtr TableVal::FindOrDefault(const ValPtr& index)
return Default(index);
}
bool TableVal::Contains(const IPAddr& addr)
{
return subnets ? subnets->Lookup(addr, true) : false;
}
Val* TableVal::Lookup(Val* index, bool use_default_val)
{
static ValPtr last_default;

View file

@ -906,6 +906,10 @@ public:
[[deprecated("Remove in v4.1. Use Find() or FindOrDefault().")]]
Val* Lookup(Val* index, bool use_default_val = true);
// Returns true if this is a table[subnet]/set[subnet] and the
// given address was found in the table. Otherwise returns false.
bool Contains(const IPAddr& addr);
// For a table[subnet]/set[subnet], return all subnets that cover
// the given subnet.
// Causes an internal error if called for any other kind of table.

View file

@ -49,7 +49,9 @@ void ICMP_Analyzer::DeliverPacket(int len, const u_char* data,
const struct icmp* icmpp = (const struct icmp*) data;
if ( ! zeek::detail::ignore_checksums && caplen >= len )
if ( ! zeek::detail::ignore_checksums &&
! zeek::id::find_val<TableVal>("ignore_checksums_nets")->Contains(ip->IPHeaderSrcAddr()) &&
!caplen >= len )
{
int chksum = 0;

View file

@ -272,11 +272,13 @@ const struct tcphdr* TCP_Analyzer::ExtractTCP_Header(const u_char*& data,
return tp;
}
bool TCP_Analyzer::ValidateChecksum(const struct tcphdr* tp,
TCP_Endpoint* endpoint, int len, int caplen, bool ipv4)
bool TCP_Analyzer::ValidateChecksum(const IP_Hdr* ip, const struct tcphdr* tp,
TCP_Endpoint* endpoint, int len, int caplen)
{
if ( ! run_state::current_pkt->l3_checksummed && ! detail::ignore_checksums && caplen >= len &&
! endpoint->ValidChecksum(tp, len, ipv4) )
if ( ! run_state::current_pkt->l3_checksummed &&
! detail::ignore_checksums &&
! zeek::id::find_val<TableVal>("ignore_checksums_nets")->Contains(ip->IPHeaderSrcAddr()) &&
caplen >= len && ! endpoint->ValidChecksum(tp, len, ip->IP4_Hdr()) )
{
Weird("bad_TCP_checksum");
endpoint->ChecksumError();
@ -1060,7 +1062,7 @@ void TCP_Analyzer::DeliverPacket(int len, const u_char* data, bool is_orig,
TCP_Endpoint* endpoint = is_orig ? orig : resp;
TCP_Endpoint* peer = endpoint->peer;
if ( ! ValidateChecksum(tp, endpoint, len, caplen, ip->IP4_Hdr()) )
if ( ! ValidateChecksum(ip, tp, endpoint, len, caplen) )
return;
uint32_t tcp_hdr_len = data - (const u_char*) tp;

View file

@ -94,8 +94,8 @@ protected:
// Returns true if the checksum is valid, false if not (and in which
// case also updates the status history of the endpoint).
bool ValidateChecksum(const struct tcphdr* tp, TCP_Endpoint* endpoint,
int len, int caplen, bool ipv4);
bool ValidateChecksum(const IP_Hdr* ip, const struct tcphdr* tp, TCP_Endpoint* endpoint,
int len, int caplen);
void SetPartialStatus(TCP_Flags flags, bool is_orig);

View file

@ -62,7 +62,12 @@ void UDP_Analyzer::DeliverPacket(int len, const u_char* data, bool is_orig,
int chksum = up->uh_sum;
auto validate_checksum = ! run_state::current_pkt->l3_checksummed && ! zeek::detail::ignore_checksums && caplen >=len;
auto validate_checksum =
! run_state::current_pkt->l3_checksummed &&
! zeek::detail::ignore_checksums &&
! zeek::id::find_val<TableVal>("ignore_checksums_nets")->Contains(ip->IPHeaderSrcAddr()) &&
caplen >=len;
constexpr auto vxlan_len = 8;
constexpr auto eth_len = 14;

View file

@ -129,6 +129,7 @@ bool IPAnalyzer::AnalyzePacket(size_t len, const uint8_t* data, Packet* packet)
return false;
if ( ! packet->l2_checksummed && ! detail::ignore_checksums && ip4 &&
! zeek::id::find_val<TableVal>("ignore_checksums_nets")->Contains(packet->ip_hdr->IPHeaderSrcAddr()) &&
detail::in_cksum(reinterpret_cast<const uint8_t*>(ip4), ip_hdr_len) != 0xffff )
{
sessions->Weird("bad_IP_checksum", packet);