A set of various fixes and smaller API tweaks, plus tests.

Also moving PCAP-related bifs to iosource/pcap.bif.
This commit is contained in:
Robin Sommer 2014-08-22 17:56:16 -07:00
parent ce9f16490c
commit 5f817513d0
34 changed files with 395 additions and 164 deletions

View file

@ -91,7 +91,8 @@ bool BPF_Program::Compile(pcap_t* pcap, const char* filter, uint32 netmask,
}
bool BPF_Program::Compile(int snaplen, int linktype, const char* filter,
uint32 netmask, char* errbuf, bool optimize)
uint32 netmask, char* errbuf, unsigned int errbuf_len,
bool optimize)
{
FreeCode();
@ -99,13 +100,18 @@ bool BPF_Program::Compile(int snaplen, int linktype, const char* filter,
char my_error[PCAP_ERRBUF_SIZE];
int err = pcap_compile_nopcap(snaplen, linktype, &m_program,
(char *) filter, optimize, netmask, error);
(char *) filter, optimize, netmask, my_error);
if ( err < 0 && errbuf )
safe_strncpy(errbuf, my_errbuf, PCAP_ERRBUF_SIZE);
safe_strncpy(errbuf, my_error, errbuf_len);
*errbuf = '\0';
#else
int err = pcap_compile_nopcap(snaplen, linktype, &m_program,
(char*) filter, optimize, netmask);
if ( err < 0 && errbuf && errbuf_len )
*errbuf = '\0';
#endif
if ( err == 0 )
m_compiled = true;

View file

@ -30,7 +30,8 @@ public:
// similarly to pcap_compile_nopcap(). Parameters are
// similar. Returns true on success.
bool Compile(int snaplen, int linktype, const char* filter,
uint32 netmask, char* errbuf = 0, bool optimize = true);
uint32 netmask, char* errbuf = 0, unsigned int errbuf_len = 0,
bool optimize = true);
// Returns true if this program currently contains compiled
// code, false otherwise.

View file

@ -6,6 +6,8 @@ include_directories(BEFORE
${CMAKE_CURRENT_BINARY_DIR}
)
add_subdirectory(pcap)
set(iosource_SRCS
BPF_Program.cc
Component.cc
@ -14,6 +16,8 @@ set(iosource_SRCS
PktSrc.cc
)
bif_target(pcap.bif)
bro_add_subdir_library(iosource ${iosource_SRCS})
add_dependencies(bro_iosource generate_outputs)

View file

@ -14,7 +14,7 @@ namespace iosource {
*/
class IOSource {
public:
IOSource() { idle = closed = false; }
IOSource() { idle = false; closed = false; }
virtual ~IOSource() {}
// Returns true if source has nothing ready to process.
@ -57,7 +57,6 @@ protected:
// Derived classed are to set this to true if they have gone dry
// temporarily.
void SetIdle(bool is_idle) { idle = is_idle; }
// Derived classed are to set this to true if they have gone dry
// temporarily.

View file

@ -22,11 +22,19 @@ Manager::~Manager()
{
for ( SourceList::iterator i = sources.begin(); i != sources.end(); ++i )
{
(*i)->src->Done();
// ??? (*i)->src->Done();
delete *i;
}
sources.clear();
for ( PktDumperList::iterator i = pkt_dumpers.begin(); i != pkt_dumpers.end(); ++i )
{
(*i)->Done();
delete *i;
}
pkt_dumpers.clear();
}
void Manager::RemoveAll()
@ -43,6 +51,7 @@ IOSource* Manager::FindSoonest(double* ts)
i != sources.end(); ++i )
if ( ! (*i)->src->IsOpen() )
{
(*i)->src->Done();
delete *i;
sources.erase(i);
break;
@ -246,15 +255,11 @@ PktSrc* Manager::OpenPktSrc(const std::string& path, const std::string& filter,
// Instantiate packet source.
PktSrc* ps = (*component->Factory())(npath, filter, is_live);
assert(ps);
if ( ! (ps && ps->IsOpen()) )
{
string type = (is_live ? "interface" : "trace file");
string pserr = ps->ErrorMsg() ? (string(" - ") + ps->ErrorMsg()) : "";
reporter->FatalError("%s: problem with %s %s%s",
prog, npath.c_str(), type.c_str(), pserr.c_str());
}
if ( ! ps->IsOpen() && ps->ErrorMsg() )
// Set an error message if it didn't open successfully.
ps->Error("could not open");
DBG_LOG(DBG_PKTIO, "Created packet source of type %s for %s", component->Name().c_str(), npath.c_str());
@ -291,16 +296,16 @@ PktDumper* Manager::OpenPktDumper(const string& path, bool append)
// Instantiate packet dumper.
PktDumper* pd = (*component->Factory())(npath, append);
assert(pd);
if ( ! (pd && pd->IsOpen()) )
{
string pderr = pd->ErrorMsg().size() ? (string(" - ") + pd->ErrorMsg()) : "";
reporter->FatalError("%s: can't open write file \"%s\"%s",
prog, npath.c_str(), pderr.c_str());
}
if ( ! pd->IsOpen() && pd->ErrorMsg() )
// Set an error message if it didn't open successfully.
pd->Error("could not open");
DBG_LOG(DBG_PKTIO, "Created packer dumper of type %s for %s", component->Name().c_str(), npath.c_str());
pd->Init();
pkt_dumpers.push_back(pd);
return pd;
}

View file

@ -64,7 +64,10 @@ protected:
typedef std::list<Source*> SourceList;
SourceList sources;
typedef std::list<PktDumper *> PktDumperList;
PktSrcList pkt_srcs;
PktDumperList pkt_dumpers;
};
}

View file

@ -20,6 +20,16 @@ PktDumper::~PktDumper()
{
}
void PktDumper::Init()
{
Open();
}
void PktDumper::Done()
{
Close();
}
const std::string& PktDumper::Path() const
{
return props.path;
@ -40,9 +50,9 @@ bool PktDumper::IsError() const
return errmsg.size();
}
const std::string& PktDumper::ErrorMsg() const
const char* PktDumper::ErrorMsg() const
{
return errmsg;
return errmsg.size() ? errmsg.c_str() : 0;
}
int PktDumper::HdrSize() const
@ -60,8 +70,8 @@ void PktDumper::Opened(const Properties& arg_props)
void PktDumper::Closed()
{
is_open = false;
props.path = "";
DBG_LOG(DBG_PKTIO, "Closed dumper %s", props.path.c_str());
props.path = "";
}
void PktDumper::Error(const std::string& msg)

View file

@ -21,16 +21,18 @@ public:
bool IsOpen() const;
double OpenTime() const;
bool IsError() const;
const std::string& ErrorMsg() const;
const char* ErrorMsg() const;
int HdrSize() const;
bool Record(const Packet* pkt);
// PktSrc interface for derived classes to implement.
// PktDumper interface for derived classes to implement.
virtual void Close() = 0;
virtual void Open() = 0;
virtual bool Dump(const Packet* pkt) = 0;
protected:
friend class Manager;
// Methods to use by derived classed.
//
struct Properties {
@ -39,6 +41,9 @@ protected:
double open_time;
};
void Init();
void Done();
void Opened(const Properties& props);
void Closed();
void Error(const std::string& msg);

View file

@ -17,6 +17,7 @@ PktSrc::PktSrc()
{
have_packet = false;
errbuf = "";
SetClosed(true);
next_sync_point = 0;
first_timestamp = 0.0;
@ -195,7 +196,8 @@ void PktSrc::Init()
void PktSrc::Done()
{
Close();
if ( IsOpen() )
Close();
}
void PktSrc::GetFds(int* read, int* write, int* except)
@ -433,8 +435,13 @@ int PktSrc::PrecompileBPFFilter(int index, const std::string& filter)
if ( ! code->Compile(SnapLen(), LinkType(), filter.c_str(), Netmask(), errbuf, sizeof(errbuf)) )
{
Error(fmt("cannot compile BPF filter \"%s\": %s", filter.c_str(), errbuf));
Close();
string msg = fmt("cannot compile BPF filter \"%s\"", filter.c_str());
if ( *errbuf )
msg += ": " + string(errbuf);
Error(msg);
delete code;
return 0;
}

View file

@ -83,6 +83,8 @@ public:
static int GetLinkHeaderSize(int link_type);
protected:
friend class Manager;
// Methods to use by derived classes.
struct Properties {

104
src/iosource/pcap.bif Normal file
View file

@ -0,0 +1,104 @@
## Precompiles a PCAP filter and binds it to a given identifier.
##
## id: The PCAP identifier to reference the filter *s* later on.
##
## s: The PCAP filter. See ``man tcpdump`` for valid expressions.
##
## Returns: True if *s* is valid and precompiles successfully.
##
## .. bro:see:: install_pcap_filter
## install_src_addr_filter
## install_src_net_filter
## uninstall_src_addr_filter
## uninstall_src_net_filter
## install_dst_addr_filter
## install_dst_net_filter
## uninstall_dst_addr_filter
## uninstall_dst_net_filter
## pcap_error
function precompile_pcap_filter%(id: PcapFilterID, s: string%): bool
%{
bool success = true;
const iosource::Manager::PktSrcList& pkt_srcs(iosource_mgr->GetPktSrcs());
for ( iosource::Manager::PktSrcList::const_iterator i = pkt_srcs.begin();
i != pkt_srcs.end(); i++ )
{
iosource::PktSrc* ps = *i;
if ( ! ps->PrecompileFilter(id->ForceAsInt(),
s->CheckString()) )
success = false;
}
return new Val(success, TYPE_BOOL);
%}
## Installs a PCAP filter that has been precompiled with
## :bro:id:`precompile_pcap_filter`.
##
## id: The PCAP filter id of a precompiled filter.
##
## Returns: True if the filter associated with *id* has been installed
## successfully.
##
## .. bro:see:: precompile_pcap_filter
## install_src_addr_filter
## install_src_net_filter
## uninstall_src_addr_filter
## uninstall_src_net_filter
## install_dst_addr_filter
## install_dst_net_filter
## uninstall_dst_addr_filter
## uninstall_dst_net_filter
## pcap_error
function install_pcap_filter%(id: PcapFilterID%): bool
%{
bool success = true;
const iosource::Manager::PktSrcList& pkt_srcs(iosource_mgr->GetPktSrcs());
for ( iosource::Manager::PktSrcList::const_iterator i = pkt_srcs.begin();
i != pkt_srcs.end(); i++ )
{
iosource::PktSrc* ps = *i;
if ( ! ps->SetFilter(id->ForceAsInt()) )
success = false;
}
return new Val(success, TYPE_BOOL);
%}
## Returns a string representation of the last PCAP error.
##
## Returns: A descriptive error message of the PCAP function that failed.
##
## .. bro:see:: precompile_pcap_filter
## install_pcap_filter
## install_src_addr_filter
## install_src_net_filter
## uninstall_src_addr_filter
## uninstall_src_net_filter
## install_dst_addr_filter
## install_dst_net_filter
## uninstall_dst_addr_filter
## uninstall_dst_net_filter
function pcap_error%(%): string
%{
const iosource::Manager::PktSrcList& pkt_srcs(iosource_mgr->GetPktSrcs());
for ( iosource::Manager::PktSrcList::const_iterator i = pkt_srcs.begin();
i != pkt_srcs.end(); i++ )
{
iosource::PktSrc* ps = *i;
const char* err = ps->ErrorMsg();
if ( *err )
return new StringVal(err);
}
return new StringVal("no error");
%}

View file

@ -5,9 +5,9 @@
#include "Dumper.h"
#include "../PktSrc.h"
#include "../../../Net.h"
#include "../../Net.h"
using namespace iosource::pktsrc;
using namespace iosource::pcap;
PcapDumper::PcapDumper(const std::string& path, bool arg_append)
{

View file

@ -9,7 +9,7 @@ extern "C" {
#include "../PktDumper.h"
namespace iosource {
namespace pktsrc {
namespace pcap {
class PcapDumper : public PktDumper {
public:

View file

@ -12,8 +12,8 @@ class Plugin : public plugin::Plugin {
public:
plugin::Configuration Configure()
{
AddComponent(new ::iosource::pktsrc::SourceComponent("PcapReader", "pcap", ::iosource::pktsrc::SourceComponent::BOTH, ::iosource::pktsrc::PcapSource::Instantiate));
AddComponent(new ::iosource::pktsrc::DumperComponent("PcapWriter", "pcap", ::iosource::pktsrc::PcapDumper::Instantiate));
AddComponent(new ::iosource::PktSrcComponent("PcapReader", "pcap", ::iosource::PktSrcComponent::BOTH, ::iosource::pcap::PcapSource::Instantiate));
AddComponent(new ::iosource::PktDumperComponent("PcapWriter", "pcap", ::iosource::pcap::PcapDumper::Instantiate));
plugin::Configuration config;
config.name = "Bro::Pcap";

View file

@ -9,7 +9,7 @@
#include <pcap-int.h>
#endif
using namespace iosource::pktsrc;
using namespace iosource::pcap;
PcapSource::~PcapSource()
{
@ -182,7 +182,7 @@ void PcapSource::DoneWithPacket(Packet* pkt)
int PcapSource::PrecompileFilter(int index, const std::string& filter)
{
return PktSrc::PrecompileBPFFilter(index, filter).
return PktSrc::PrecompileBPFFilter(index, filter);
}
int PcapSource::SetFilter(int index)
@ -192,7 +192,7 @@ int PcapSource::SetFilter(int index)
char errbuf[PCAP_ERRBUF_SIZE];
BPF_Program* code = GetFilter(index);
BPF_Program* code = GetBPFFilter(index);
if ( ! code )
{

View file

@ -6,7 +6,7 @@
#include "../PktSrc.h"
namespace iosource {
namespace pktsrc {
namespace pcap {
class PcapSource : public iosource::PktSrc {
public: