diff --git a/src/iosource/BPF_Program.cc b/src/iosource/BPF_Program.cc index a712a8745b..c0d07cf6ee 100644 --- a/src/iosource/BPF_Program.cc +++ b/src/iosource/BPF_Program.cc @@ -6,6 +6,8 @@ #include +#include "zeek/util.h" + #ifdef DONT_HAVE_LIBPCAP_PCAP_FREECODE extern "C" { @@ -76,8 +78,8 @@ BPF_Program::~BPF_Program() FreeCode(); } -bool BPF_Program::Compile(pcap_t* pcap, const char* filter, uint32_t netmask, char* errbuf, - unsigned int errbuf_len, bool optimize) +bool BPF_Program::Compile(pcap_t* pcap, const char* filter, uint32_t netmask, std::string& errbuf, + bool optimize) { if ( ! pcap ) 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 ( errbuf ) - snprintf(errbuf, errbuf_len, "pcap_compile(%s): %s", filter, pcap_geterr(pcap)); - + errbuf = util::fmt("pcap_compile(%s): %s", filter, pcap_geterr(pcap)); 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, - char* errbuf, unsigned int errbuf_len, bool optimize) + std::string& errbuf, bool optimize) { 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, my_error); - if ( err < 0 && errbuf ) - safe_strncpy(errbuf, my_error, errbuf_len); - *errbuf = '\0'; + if ( err < 0 ) + errbuf = std::string(my_error); #else int err = pcap_compile_nopcap(snaplen, linktype, &m_program, (char*)filter, optimize, netmask); - if ( err < 0 && errbuf && errbuf_len ) - *errbuf = '\0'; + if ( err < 0 ) + errbuf.clear(); #endif if ( err == 0 ) diff --git a/src/iosource/BPF_Program.h b/src/iosource/BPF_Program.h index b3025a4c9d..220e67b4f1 100644 --- a/src/iosource/BPF_Program.h +++ b/src/iosource/BPF_Program.h @@ -2,7 +2,8 @@ #pragma once -#include +#include +#include extern "C" { @@ -26,14 +27,14 @@ public: // Creates a BPF program for the given pcap handle. // Parameters are like in pcap_compile(). Returns true // for successful compilation, false otherwise. - bool Compile(pcap_t* pcap, const char* filter, uint32_t netmask, char* errbuf = nullptr, - unsigned int errbuf_len = 0, bool optimize = true); + bool Compile(pcap_t* pcap, const char* filter, uint32_t netmask, std::string& errbuf, + bool optimize = true); // Creates a BPF program when no pcap handle is around, // similarly to pcap_compile_nopcap(). Parameters are // similar. Returns true on success. 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 // code, false otherwise. diff --git a/src/iosource/PktSrc.cc b/src/iosource/PktSrc.cc index a265bd6f74..d1876f3cb1 100644 --- a/src/iosource/PktSrc.cc +++ b/src/iosource/PktSrc.cc @@ -201,35 +201,40 @@ bool PktSrc::ExtractNextPacketInternal() return false; } +detail::BPF_Program* PktSrc::CompileFilter(const std::string& filter) + { + std::string errbuf; + auto code = std::make_unique(); + + 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) { if ( index < 0 ) return false; - char errbuf[PCAP_ERRBUF_SIZE]; - // Compile filter. - auto* code = new detail::BPF_Program(); - - 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; + auto code = CompileFilter(filter); + if ( ! code ) return false; - } // Store it in vector. if ( index >= static_cast(filters.size()) ) filters.resize(index + 1); - if ( auto old = filters[index] ) + if ( auto* old = filters[index] ) delete old; filters[index] = code; diff --git a/src/iosource/PktSrc.h b/src/iosource/PktSrc.h index 6cb8333874..70229ec243 100644 --- a/src/iosource/PktSrc.h +++ b/src/iosource/PktSrc.h @@ -111,7 +111,7 @@ public: * * @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, @@ -336,6 +336,8 @@ protected: */ virtual void DoneWithPacket() = 0; + virtual detail::BPF_Program* CompileFilter(const std::string& filter); + private: // Internal helper for ExtractNextPacket(). bool ExtractNextPacketInternal(); diff --git a/src/iosource/pcap/Source.cc b/src/iosource/pcap/Source.cc index 8afe55638a..093a5f8eed 100644 --- a/src/iosource/pcap/Source.cc +++ b/src/iosource/pcap/Source.cc @@ -268,6 +268,25 @@ bool PcapSource::PrecompileFilter(int index, const std::string& filter) return PktSrc::PrecompileBPFFilter(index, filter); } +detail::BPF_Program* PcapSource::CompileFilter(const std::string& filter) + { + std::string errbuf; + auto code = std::make_unique(); + + 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) { if ( ! pd ) diff --git a/src/iosource/pcap/Source.h b/src/iosource/pcap/Source.h index af64076671..8c1c88992b 100644 --- a/src/iosource/pcap/Source.h +++ b/src/iosource/pcap/Source.h @@ -31,6 +31,7 @@ protected: bool PrecompileFilter(int index, const std::string& filter) override; bool SetFilter(int index) override; void Statistics(Stats* stats) override; + detail::BPF_Program* CompileFilter(const std::string& filter) override; private: void OpenLive();