zeek/src/Discard.cc
Jon Siwek 8bc65f09ec Cleanup/improve PList usage and Event API
Majority of PLists are now created as automatic/stack objects,
rather than on heap and initialized either with the known-capacity
reserved upfront or directly from an initializer_list (so there's no
wasted slack in the memory that gets allocated for lists containing
a fixed/known number of elements).

Added versions of the ConnectionEvent/QueueEvent methods that take
a val_list by value.

Added a move ctor/assign-operator to Plists to allow passing them
around without having to copy the underlying array of pointers.
2019-04-11 20:30:25 -07:00

161 lines
3.1 KiB
C++

// See the file "COPYING" in the main distribution directory for copyright.
#include <algorithm>
#include "bro-config.h"
#include "Net.h"
#include "Var.h"
#include "Discard.h"
Discarder::Discarder()
{
check_ip = internal_func("discarder_check_ip");
check_tcp = internal_func("discarder_check_tcp");
check_udp = internal_func("discarder_check_udp");
check_icmp = internal_func("discarder_check_icmp");
discarder_maxlen = static_cast<int>(opt_internal_int("discarder_maxlen"));
}
Discarder::~Discarder()
{
}
int Discarder::IsActive()
{
return check_ip || check_tcp || check_udp || check_icmp;
}
int Discarder::NextPacket(const IP_Hdr* ip, int len, int caplen)
{
int discard_packet = 0;
if ( check_ip )
{
val_list args{ip->BuildPktHdrVal()};
try
{
discard_packet = check_ip->Call(&args)->AsBool();
}
catch ( InterpreterException& e )
{
discard_packet = false;
}
if ( discard_packet )
return discard_packet;
}
int proto = ip->NextProto();
if ( proto != IPPROTO_TCP && proto != IPPROTO_UDP &&
proto != IPPROTO_ICMP )
// This is not a protocol we understand.
return 0;
// XXX shall we only check the first packet???
if ( ip->IsFragment() )
// Never check any fragment.
return 0;
int ip_hdr_len = ip->HdrLen();
len -= ip_hdr_len; // remove IP header
caplen -= ip_hdr_len;
int is_tcp = (proto == IPPROTO_TCP);
int is_udp = (proto == IPPROTO_UDP);
int min_hdr_len = is_tcp ?
sizeof(struct tcphdr) :
(is_udp ? sizeof(struct udphdr) : sizeof(struct icmp));
if ( len < min_hdr_len || caplen < min_hdr_len )
// we don't have a complete protocol header
return 0;
// Where the data starts - if this is a protocol we know about,
// this gets advanced past the transport header.
const u_char* data = ip->Payload();
if ( is_tcp )
{
if ( check_tcp )
{
const struct tcphdr* tp = (const struct tcphdr*) data;
int th_len = tp->th_off * 4;
val_list args{
ip->BuildPktHdrVal(),
BuildData(data, th_len, len, caplen),
};
try
{
discard_packet = check_tcp->Call(&args)->AsBool();
}
catch ( InterpreterException& e )
{
discard_packet = false;
}
}
}
else if ( is_udp )
{
if ( check_udp )
{
const struct udphdr* up = (const struct udphdr*) data;
int uh_len = sizeof (struct udphdr);
val_list args{
ip->BuildPktHdrVal(),
BuildData(data, uh_len, len, caplen),
};
try
{
discard_packet = check_udp->Call(&args)->AsBool();
}
catch ( InterpreterException& e )
{
discard_packet = false;
}
}
}
else
{
if ( check_icmp )
{
const struct icmp* ih = (const struct icmp*) data;
val_list args{ip->BuildPktHdrVal()};
try
{
discard_packet = check_icmp->Call(&args)->AsBool();
}
catch ( InterpreterException& e )
{
discard_packet = false;
}
}
}
return discard_packet;
}
Val* Discarder::BuildData(const u_char* data, int hdrlen, int len, int caplen)
{
len -= hdrlen;
caplen -= hdrlen;
data += hdrlen;
len = max(min(min(len, caplen), discarder_maxlen), 0);
return new StringVal(new BroString(data, len, 1));
}