Allow pcap pktsrc to use other BPF_Program::Compile method

This commit is contained in:
Tim Wojtulewicz 2022-05-23 17:36:09 -07:00
parent 515e5bf8a3
commit b30d5702f6
6 changed files with 60 additions and 33 deletions

View file

@ -6,6 +6,8 @@
#include <string.h> #include <string.h>
#include "zeek/util.h"
#ifdef DONT_HAVE_LIBPCAP_PCAP_FREECODE #ifdef DONT_HAVE_LIBPCAP_PCAP_FREECODE
extern "C" extern "C"
{ {
@ -76,8 +78,8 @@ BPF_Program::~BPF_Program()
FreeCode(); FreeCode();
} }
bool BPF_Program::Compile(pcap_t* pcap, const char* filter, uint32_t netmask, char* errbuf, bool BPF_Program::Compile(pcap_t* pcap, const char* filter, uint32_t netmask, std::string& errbuf,
unsigned int errbuf_len, bool optimize) bool optimize)
{ {
if ( ! pcap ) if ( ! pcap )
return false; return false;
@ -86,9 +88,7 @@ bool BPF_Program::Compile(pcap_t* pcap, const char* filter, uint32_t netmask, ch
if ( pcap_compile(pcap, &m_program, (char*)filter, optimize, netmask) < 0 ) if ( pcap_compile(pcap, &m_program, (char*)filter, optimize, netmask) < 0 )
{ {
if ( errbuf ) errbuf = util::fmt("pcap_compile(%s): %s", filter, pcap_geterr(pcap));
snprintf(errbuf, errbuf_len, "pcap_compile(%s): %s", filter, pcap_geterr(pcap));
return false; return false;
} }
@ -99,7 +99,7 @@ bool BPF_Program::Compile(pcap_t* pcap, const char* filter, uint32_t netmask, ch
} }
bool BPF_Program::Compile(int snaplen, int linktype, const char* filter, uint32_t netmask, bool BPF_Program::Compile(int snaplen, int linktype, const char* filter, uint32_t netmask,
char* errbuf, unsigned int errbuf_len, bool optimize) std::string& errbuf, bool optimize)
{ {
FreeCode(); FreeCode();
@ -119,14 +119,13 @@ bool BPF_Program::Compile(int snaplen, int linktype, const char* filter, uint32_
int err = pcap_compile_nopcap(snaplen, linktype, &m_program, (char*)filter, optimize, netmask, int err = pcap_compile_nopcap(snaplen, linktype, &m_program, (char*)filter, optimize, netmask,
my_error); my_error);
if ( err < 0 && errbuf ) if ( err < 0 )
safe_strncpy(errbuf, my_error, errbuf_len); errbuf = std::string(my_error);
*errbuf = '\0';
#else #else
int err = pcap_compile_nopcap(snaplen, linktype, &m_program, (char*)filter, optimize, netmask); int err = pcap_compile_nopcap(snaplen, linktype, &m_program, (char*)filter, optimize, netmask);
if ( err < 0 && errbuf && errbuf_len ) if ( err < 0 )
*errbuf = '\0'; errbuf.clear();
#endif #endif
if ( err == 0 ) if ( err == 0 )

View file

@ -2,7 +2,8 @@
#pragma once #pragma once
#include <stdint.h> #include <cstdint>
#include <string>
extern "C" extern "C"
{ {
@ -26,14 +27,14 @@ public:
// Creates a BPF program for the given pcap handle. // Creates a BPF program for the given pcap handle.
// Parameters are like in pcap_compile(). Returns true // Parameters are like in pcap_compile(). Returns true
// for successful compilation, false otherwise. // for successful compilation, false otherwise.
bool Compile(pcap_t* pcap, const char* filter, uint32_t netmask, char* errbuf = nullptr, bool Compile(pcap_t* pcap, const char* filter, uint32_t netmask, std::string& errbuf,
unsigned int errbuf_len = 0, bool optimize = true); bool optimize = true);
// Creates a BPF program when no pcap handle is around, // Creates a BPF program when no pcap handle is around,
// similarly to pcap_compile_nopcap(). Parameters are // similarly to pcap_compile_nopcap(). Parameters are
// similar. Returns true on success. // similar. Returns true on success.
bool Compile(int snaplen, int linktype, const char* filter, uint32_t netmask, bool Compile(int snaplen, int linktype, const char* filter, uint32_t netmask,
char* errbuf = nullptr, unsigned int errbuf_len = 0, bool optimize = true); std::string& errbuf, bool optimize = true);
// Returns true if this program currently contains compiled // Returns true if this program currently contains compiled
// code, false otherwise. // code, false otherwise.

View file

@ -201,35 +201,40 @@ bool PktSrc::ExtractNextPacketInternal()
return false; return false;
} }
detail::BPF_Program* PktSrc::CompileFilter(const std::string& filter)
{
std::string errbuf;
auto code = std::make_unique<detail::BPF_Program>();
if ( ! code->Compile(BifConst::Pcap::snaplen, LinkType(), filter.c_str(), Netmask(), errbuf) )
{
std::string msg = util::fmt("cannot compile BPF filter \"%s\"", filter.c_str());
if ( ! errbuf.empty() )
msg += ": " + errbuf;
Error(msg);
return nullptr;
}
return code.release();
}
bool PktSrc::PrecompileBPFFilter(int index, const std::string& filter) bool PktSrc::PrecompileBPFFilter(int index, const std::string& filter)
{ {
if ( index < 0 ) if ( index < 0 )
return false; return false;
char errbuf[PCAP_ERRBUF_SIZE];
// Compile filter. // Compile filter.
auto* code = new detail::BPF_Program(); auto code = CompileFilter(filter);
if ( ! code )
if ( ! code->Compile(BifConst::Pcap::snaplen, LinkType(), filter.c_str(), Netmask(), errbuf,
sizeof(errbuf)) )
{
std::string msg = util::fmt("cannot compile BPF filter \"%s\"", filter.c_str());
if ( *errbuf )
msg += ": " + std::string(errbuf);
Error(msg);
delete code;
return false; return false;
}
// Store it in vector. // Store it in vector.
if ( index >= static_cast<int>(filters.size()) ) if ( index >= static_cast<int>(filters.size()) )
filters.resize(index + 1); filters.resize(index + 1);
if ( auto old = filters[index] ) if ( auto* old = filters[index] )
delete old; delete old;
filters[index] = code; filters[index] = code;

View file

@ -111,7 +111,7 @@ public:
* *
* @return True on success, false if a problem occurred. * @return True on success, false if a problem occurred.
*/ */
bool PrecompileBPFFilter(int index, const std::string& filter); virtual bool PrecompileBPFFilter(int index, const std::string& filter);
/** /**
* Returns the precompiled BPF filter associated with a given index, * Returns the precompiled BPF filter associated with a given index,
@ -336,6 +336,8 @@ protected:
*/ */
virtual void DoneWithPacket() = 0; virtual void DoneWithPacket() = 0;
virtual detail::BPF_Program* CompileFilter(const std::string& filter);
private: private:
// Internal helper for ExtractNextPacket(). // Internal helper for ExtractNextPacket().
bool ExtractNextPacketInternal(); bool ExtractNextPacketInternal();

View file

@ -268,6 +268,25 @@ bool PcapSource::PrecompileFilter(int index, const std::string& filter)
return PktSrc::PrecompileBPFFilter(index, filter); return PktSrc::PrecompileBPFFilter(index, filter);
} }
detail::BPF_Program* PcapSource::CompileFilter(const std::string& filter)
{
std::string errbuf;
auto code = std::make_unique<detail::BPF_Program>();
if ( ! code->Compile(pd, filter.c_str(), Netmask(), errbuf) )
{
std::string msg = util::fmt("cannot compile BPF filter \"%s\"", filter.c_str());
if ( ! errbuf.empty() )
msg += ": " + errbuf;
Error(msg);
return nullptr;
}
return code.release();
}
bool PcapSource::SetFilter(int index) bool PcapSource::SetFilter(int index)
{ {
if ( ! pd ) if ( ! pd )

View file

@ -31,6 +31,7 @@ protected:
bool PrecompileFilter(int index, const std::string& filter) override; bool PrecompileFilter(int index, const std::string& filter) override;
bool SetFilter(int index) override; bool SetFilter(int index) override;
void Statistics(Stats* stats) override; void Statistics(Stats* stats) override;
detail::BPF_Program* CompileFilter(const std::string& filter) override;
private: private:
void OpenLive(); void OpenLive();