diff --git a/TODO.iosources b/TODO.iosources index e61e858087..ee19dea169 100644 --- a/TODO.iosources +++ b/TODO.iosources @@ -1,3 +1,4 @@ -- Wrap BPF_Program into namespace and clean up -- Add an interface for derived pkt source to run a BPF filter. -- Tests, in particular the packet dumping needs testing. +- Tests + - pktsrc plugin + - pktdump plugin + diff --git a/src/Net.cc b/src/Net.cc index 38ec7c3b06..554aa890ba 100644 --- a/src/Net.cc +++ b/src/Net.cc @@ -116,8 +116,7 @@ RETSIGTYPE watchdog(int /* signo */) pkt_dumper = iosource_mgr->OpenPktDumper("watchdog-pkt.pcap", false); if ( ! pkt_dumper || pkt_dumper->IsError() ) { - reporter->Error("watchdog: can't open watchdog-pkt.pcap for writing\n"); - delete pkt_dumper; + reporter->Error("watchdog: can't open watchdog-pkt.pcap for writing"); pkt_dumper = 0; } } @@ -167,9 +166,9 @@ void net_init(name_list& interfaces, name_list& readfiles, iosource::PktSrc* ps = iosource_mgr->OpenPktSrc(readfiles[i], filter, false); assert(ps); - if ( ps->ErrorMsg() ) - reporter->FatalError("%s: problem with trace file %s - %s\n", - prog, readfiles[i], + if ( ! ps->IsOpen() ) + reporter->FatalError("problem with trace file %s (%s)", + readfiles[i], ps->ErrorMsg()); } } @@ -184,9 +183,9 @@ void net_init(name_list& interfaces, name_list& readfiles, iosource::PktSrc* ps = iosource_mgr->OpenPktSrc(interfaces[i], filter, true); assert(ps); - if ( ps->ErrorMsg() ) - reporter->FatalError("%s: problem with interface %s - %s\n", - prog, interfaces[i], + if ( ! ps->IsOpen() ) + reporter->FatalError("problem with interface %s (%s)", + interfaces[i], ps->ErrorMsg()); } } @@ -203,9 +202,9 @@ void net_init(name_list& interfaces, name_list& readfiles, pkt_dumper = iosource_mgr->OpenPktDumper(writefile, false); assert(pkt_dumper); - if ( pkt_dumper->ErrorMsg().size() ) - reporter->FatalError("problem opening dump file %s - %s\n", - writefile, pkt_dumper->ErrorMsg().c_str()); + if ( ! pkt_dumper->IsOpen() ) + reporter->FatalError("problem opening dump file %s (%s)", + writefile, pkt_dumper->ErrorMsg()); ID* id = global_scope()->Lookup("trace_output_file"); if ( ! id ) @@ -409,7 +408,7 @@ void net_get_final_stats() { iosource::PktSrc::Stats s; ps->Statistics(&s); - reporter->Info("%d packets received on interface %s, %d dropped\n", + reporter->Info("%d packets received on interface %s, %d dropped", s.received, ps->Path().c_str(), s.dropped); } } @@ -430,8 +429,6 @@ void net_finish(int drain_events) sessions->Done(); } - delete pkt_dumper; - #ifdef DEBUG extern int reassem_seen_bytes, reassem_copied_bytes; // DEBUG_MSG("Reassembly (TCP and IP/Frag): %d bytes seen, %d bytes copied\n", diff --git a/src/bro.bif b/src/bro.bif index adf5e3d6f0..1255f05f50 100644 --- a/src/bro.bif +++ b/src/bro.bif @@ -4228,114 +4228,6 @@ function enable_raw_output%(f: file%): any # # =========================================================================== -## 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()) ) - { - reporter->Error("precompile_pcap_filter: %s", - ps->ErrorMsg()); - 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"); - %} - ## Installs a filter to drop packets from a given IP source address with ## a certain probability if none of a given set of TCP flags are set. ## Note that for IPv6 packets with a Destination options header that has diff --git a/src/iosource/BPF_Program.cc b/src/iosource/BPF_Program.cc index 5260429eb0..8df7729ad1 100644 --- a/src/iosource/BPF_Program.cc +++ b/src/iosource/BPF_Program.cc @@ -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; diff --git a/src/iosource/BPF_Program.h b/src/iosource/BPF_Program.h index 88ed669da2..3efa212bbc 100644 --- a/src/iosource/BPF_Program.h +++ b/src/iosource/BPF_Program.h @@ -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. diff --git a/src/iosource/CMakeLists.txt b/src/iosource/CMakeLists.txt index 272ced7740..a36667aee7 100644 --- a/src/iosource/CMakeLists.txt +++ b/src/iosource/CMakeLists.txt @@ -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) diff --git a/src/iosource/IOSource.h b/src/iosource/IOSource.h index 3419152a9a..9083e8f4f1 100644 --- a/src/iosource/IOSource.h +++ b/src/iosource/IOSource.h @@ -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. diff --git a/src/iosource/Manager.cc b/src/iosource/Manager.cc index e2be297a77..63b6888801 100644 --- a/src/iosource/Manager.cc +++ b/src/iosource/Manager.cc @@ -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; } diff --git a/src/iosource/Manager.h b/src/iosource/Manager.h index 5a3a58d798..4198c73680 100644 --- a/src/iosource/Manager.h +++ b/src/iosource/Manager.h @@ -64,7 +64,10 @@ protected: typedef std::list SourceList; SourceList sources; + typedef std::list PktDumperList; + PktSrcList pkt_srcs; + PktDumperList pkt_dumpers; }; } diff --git a/src/iosource/PktDumper.cc b/src/iosource/PktDumper.cc index 3c8595e11c..a4bc3a82f8 100644 --- a/src/iosource/PktDumper.cc +++ b/src/iosource/PktDumper.cc @@ -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) diff --git a/src/iosource/PktDumper.h b/src/iosource/PktDumper.h index 85c64ffd1d..d8201f977c 100644 --- a/src/iosource/PktDumper.h +++ b/src/iosource/PktDumper.h @@ -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); diff --git a/src/iosource/PktSrc.cc b/src/iosource/PktSrc.cc index 2e056a10ba..30f58a5b3f 100644 --- a/src/iosource/PktSrc.cc +++ b/src/iosource/PktSrc.cc @@ -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; } diff --git a/src/iosource/PktSrc.h b/src/iosource/PktSrc.h index 5dd51ab5f2..72e1a0da8c 100644 --- a/src/iosource/PktSrc.h +++ b/src/iosource/PktSrc.h @@ -83,6 +83,8 @@ public: static int GetLinkHeaderSize(int link_type); protected: + friend class Manager; + // Methods to use by derived classes. struct Properties { diff --git a/src/iosource/pcap.bif b/src/iosource/pcap.bif new file mode 100644 index 0000000000..ee4e1e6c06 --- /dev/null +++ b/src/iosource/pcap.bif @@ -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"); + %} diff --git a/src/iosource/pcap/Dumper.cc b/src/iosource/pcap/Dumper.cc index 2210e08e64..5d0b5e599b 100644 --- a/src/iosource/pcap/Dumper.cc +++ b/src/iosource/pcap/Dumper.cc @@ -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) { diff --git a/src/iosource/pcap/Dumper.h b/src/iosource/pcap/Dumper.h index c2762a2b04..8013afcb8e 100644 --- a/src/iosource/pcap/Dumper.h +++ b/src/iosource/pcap/Dumper.h @@ -9,7 +9,7 @@ extern "C" { #include "../PktDumper.h" namespace iosource { -namespace pktsrc { +namespace pcap { class PcapDumper : public PktDumper { public: diff --git a/src/iosource/pcap/Plugin.cc b/src/iosource/pcap/Plugin.cc index a412e4f650..f0490e6e3d 100644 --- a/src/iosource/pcap/Plugin.cc +++ b/src/iosource/pcap/Plugin.cc @@ -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"; diff --git a/src/iosource/pcap/Source.cc b/src/iosource/pcap/Source.cc index 67a73fbd8a..79ded790bd 100644 --- a/src/iosource/pcap/Source.cc +++ b/src/iosource/pcap/Source.cc @@ -9,7 +9,7 @@ #include #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 ) { diff --git a/src/iosource/pcap/Source.h b/src/iosource/pcap/Source.h index b9b61ac618..039bdec81a 100644 --- a/src/iosource/pcap/Source.h +++ b/src/iosource/pcap/Source.h @@ -6,7 +6,7 @@ #include "../PktSrc.h" namespace iosource { -namespace pktsrc { +namespace pcap { class PcapSource : public iosource::PktSrc { public: diff --git a/src/main.cc b/src/main.cc index 5066ef85ee..295fa79ee7 100644 --- a/src/main.cc +++ b/src/main.cc @@ -390,6 +390,7 @@ void terminate_bro() delete plugin_mgr; delete thread_mgr; delete reporter; + delete iosource_mgr; reporter = 0; } diff --git a/testing/btest/Baseline/core.pcap.dumper/output b/testing/btest/Baseline/core.pcap.dumper/output new file mode 100644 index 0000000000..1055e73ebe --- /dev/null +++ b/testing/btest/Baseline/core.pcap.dumper/output @@ -0,0 +1 @@ +00000010 ff ff 00 00 01 00 00 00 1d a2 b2 4e 73 00 07 00 | | 00000010 00 20 00 00 01 00 00 00 1d a2 b2 4e 73 00 07 00 | diff --git a/testing/btest/Baseline/core.pcap.dynamic-filter/conn.log b/testing/btest/Baseline/core.pcap.dynamic-filter/conn.log new file mode 100644 index 0000000000..f42999c4fa --- /dev/null +++ b/testing/btest/Baseline/core.pcap.dynamic-filter/conn.log @@ -0,0 +1,25 @@ +#separator \x09 +#set_separator , +#empty_field (empty) +#unset_field - +#path conn +#open 2014-08-24-15-51-55 +#fields ts uid id.orig_h id.orig_p id.resp_h id.resp_p proto service duration orig_bytes resp_bytes conn_state local_orig missed_bytes history orig_pkts orig_ip_bytes resp_pkts resp_ip_bytes tunnel_parents +#types time string addr port addr port enum string interval count count string bool count string count count count count set[string] +1300475167.096535 CXWv6p3arKYeMETxOg 141.142.220.202 5353 224.0.0.251 5353 udp dns - - - S0 - 0 D 1 73 0 0 (empty) +1300475168.853899 CCvvfg3TEfuqmmG4bh 141.142.220.118 43927 141.142.2.2 53 udp dns 0.000435 38 89 SF - 0 Dd 1 66 1 117 (empty) +1300475168.854378 CsRx2w45OKnoww6xl4 141.142.220.118 37676 141.142.2.2 53 udp dns 0.000420 52 99 SF - 0 Dd 1 80 1 127 (empty) +1300475168.854837 CRJuHdVW0XPVINV8a 141.142.220.118 40526 141.142.2.2 53 udp dns 0.000392 38 183 SF - 0 Dd 1 66 1 211 (empty) +1300475168.857956 CPbrpk1qSsw6ESzHV4 141.142.220.118 32902 141.142.2.2 53 udp dns 0.000317 38 89 SF - 0 Dd 1 66 1 117 (empty) +1300475168.858306 C6pKV8GSxOnSLghOa 141.142.220.118 59816 141.142.2.2 53 udp dns 0.000343 52 99 SF - 0 Dd 1 80 1 127 (empty) +1300475168.858713 CIPOse170MGiRM1Qf4 141.142.220.118 59714 141.142.2.2 53 udp dns 0.000375 38 183 SF - 0 Dd 1 66 1 211 (empty) +1300475168.891644 C7XEbhP654jzLoe3a 141.142.220.118 58206 141.142.2.2 53 udp dns 0.000339 38 89 SF - 0 Dd 1 66 1 117 (empty) +1300475168.892037 CJ3xTn1c4Zw9TmAE05 141.142.220.118 38911 141.142.2.2 53 udp dns 0.000335 52 99 SF - 0 Dd 1 80 1 127 (empty) +1300475168.892414 CMXxB5GvmoxJFXdTa 141.142.220.118 59746 141.142.2.2 53 udp dns 0.000421 38 183 SF - 0 Dd 1 66 1 211 (empty) +1300475168.893988 Caby8b1slFea8xwSmb 141.142.220.118 45000 141.142.2.2 53 udp dns 0.000384 38 89 SF - 0 Dd 1 66 1 117 (empty) +1300475168.894422 Che1bq3i2rO3KD1Syg 141.142.220.118 48479 141.142.2.2 53 udp dns 0.000317 52 99 SF - 0 Dd 1 80 1 127 (empty) +1300475168.894787 C3SfNE4BWaU4aSuwkc 141.142.220.118 48128 141.142.2.2 53 udp dns 0.000423 38 183 SF - 0 Dd 1 66 1 211 (empty) +1300475168.901749 CEle3f3zno26fFZkrh 141.142.220.118 56056 141.142.2.2 53 udp dns 0.000402 36 131 SF - 0 Dd 1 64 1 159 (empty) +1300475168.902195 CwSkQu4eWZCH7OONC1 141.142.220.118 55092 141.142.2.2 53 udp dns 0.000374 36 198 SF - 0 Dd 1 64 1 226 (empty) +1300475168.652003 CjhGID4nQcgTWjvg4c 141.142.220.118 35634 208.80.152.2 80 tcp - - - - OTH - 0 D 1 515 0 0 (empty) +#close 2014-08-24-15-51-55 diff --git a/testing/btest/Baseline/core.pcap.dynamic-filter/output b/testing/btest/Baseline/core.pcap.dynamic-filter/output new file mode 100644 index 0000000000..e8be0b0195 --- /dev/null +++ b/testing/btest/Baseline/core.pcap.dynamic-filter/output @@ -0,0 +1,30 @@ +1, [orig_h=141.142.220.202, orig_p=5353/udp, resp_h=224.0.0.251, resp_p=5353/udp] +2, [orig_h=141.142.220.118, orig_p=35634/tcp, resp_h=208.80.152.2, resp_p=80/tcp] +3, [orig_h=141.142.220.118, orig_p=43927/udp, resp_h=141.142.2.2, resp_p=53/udp] +4, [orig_h=141.142.220.118, orig_p=43927/udp, resp_h=141.142.2.2, resp_p=53/udp] +5, [orig_h=141.142.220.118, orig_p=37676/udp, resp_h=141.142.2.2, resp_p=53/udp] +6, [orig_h=141.142.220.118, orig_p=37676/udp, resp_h=141.142.2.2, resp_p=53/udp] +7, [orig_h=141.142.220.118, orig_p=40526/udp, resp_h=141.142.2.2, resp_p=53/udp] +8, [orig_h=141.142.220.118, orig_p=40526/udp, resp_h=141.142.2.2, resp_p=53/udp] +9, [orig_h=141.142.220.118, orig_p=32902/udp, resp_h=141.142.2.2, resp_p=53/udp] +10, [orig_h=141.142.220.118, orig_p=32902/udp, resp_h=141.142.2.2, resp_p=53/udp] +11, [orig_h=141.142.220.118, orig_p=59816/udp, resp_h=141.142.2.2, resp_p=53/udp] +12, [orig_h=141.142.220.118, orig_p=59816/udp, resp_h=141.142.2.2, resp_p=53/udp] +13, [orig_h=141.142.220.118, orig_p=59714/udp, resp_h=141.142.2.2, resp_p=53/udp] +14, [orig_h=141.142.220.118, orig_p=59714/udp, resp_h=141.142.2.2, resp_p=53/udp] +15, [orig_h=141.142.220.118, orig_p=58206/udp, resp_h=141.142.2.2, resp_p=53/udp] +16, [orig_h=141.142.220.118, orig_p=58206/udp, resp_h=141.142.2.2, resp_p=53/udp] +17, [orig_h=141.142.220.118, orig_p=38911/udp, resp_h=141.142.2.2, resp_p=53/udp] +18, [orig_h=141.142.220.118, orig_p=38911/udp, resp_h=141.142.2.2, resp_p=53/udp] +19, [orig_h=141.142.220.118, orig_p=59746/udp, resp_h=141.142.2.2, resp_p=53/udp] +20, [orig_h=141.142.220.118, orig_p=59746/udp, resp_h=141.142.2.2, resp_p=53/udp] +21, [orig_h=141.142.220.118, orig_p=45000/udp, resp_h=141.142.2.2, resp_p=53/udp] +22, [orig_h=141.142.220.118, orig_p=45000/udp, resp_h=141.142.2.2, resp_p=53/udp] +23, [orig_h=141.142.220.118, orig_p=48479/udp, resp_h=141.142.2.2, resp_p=53/udp] +24, [orig_h=141.142.220.118, orig_p=48479/udp, resp_h=141.142.2.2, resp_p=53/udp] +25, [orig_h=141.142.220.118, orig_p=48128/udp, resp_h=141.142.2.2, resp_p=53/udp] +26, [orig_h=141.142.220.118, orig_p=48128/udp, resp_h=141.142.2.2, resp_p=53/udp] +27, [orig_h=141.142.220.118, orig_p=56056/udp, resp_h=141.142.2.2, resp_p=53/udp] +28, [orig_h=141.142.220.118, orig_p=56056/udp, resp_h=141.142.2.2, resp_p=53/udp] +29, [orig_h=141.142.220.118, orig_p=55092/udp, resp_h=141.142.2.2, resp_p=53/udp] +30, [orig_h=141.142.220.118, orig_p=55092/udp, resp_h=141.142.2.2, resp_p=53/udp] diff --git a/testing/btest/Baseline/core.pcap.filter-error/output b/testing/btest/Baseline/core.pcap.filter-error/output new file mode 100644 index 0000000000..82804bb483 --- /dev/null +++ b/testing/btest/Baseline/core.pcap.filter-error/output @@ -0,0 +1,3 @@ +fatal error in /home/robin/bro/master/scripts/base/frameworks/packet-filter/./main.bro, line 282: Bad pcap filter 'kaputt' +---- +error, cannot compile BPF filter "kaputt, too" diff --git a/testing/btest/Baseline/core.pcap.input-error/output2 b/testing/btest/Baseline/core.pcap.input-error/output2 new file mode 100644 index 0000000000..74666797b9 --- /dev/null +++ b/testing/btest/Baseline/core.pcap.input-error/output2 @@ -0,0 +1,2 @@ +fatal error: problem with interface NO_SUCH_INTERFACE +fatal error: problem with trace file NO_SUCH_TRACE (NO_SUCH_TRACE: No such file or directory) diff --git a/testing/btest/Baseline/core.pcap.pseudo-realtime/output b/testing/btest/Baseline/core.pcap.pseudo-realtime/output new file mode 100644 index 0000000000..d708959ce9 --- /dev/null +++ b/testing/btest/Baseline/core.pcap.pseudo-realtime/output @@ -0,0 +1 @@ +real time matches trace time diff --git a/testing/btest/Baseline/core.pcap.read-trace-with-filter/conn.log b/testing/btest/Baseline/core.pcap.read-trace-with-filter/conn.log new file mode 100644 index 0000000000..8522d69ae6 --- /dev/null +++ b/testing/btest/Baseline/core.pcap.read-trace-with-filter/conn.log @@ -0,0 +1,10 @@ +#separator \x09 +#set_separator , +#empty_field (empty) +#unset_field - +#path conn +#open 2014-08-23-18-29-48 +#fields ts uid id.orig_h id.orig_p id.resp_h id.resp_p proto service duration orig_bytes resp_bytes conn_state local_orig missed_bytes history orig_pkts orig_ip_bytes resp_pkts resp_ip_bytes tunnel_parents +#types time string addr port addr port enum string interval count count string bool count string count count count count set[string] +1300475168.892936 CXWv6p3arKYeMETxOg 141.142.220.118 50000 208.80.152.3 80 tcp http 0.229603 1148 734 S1 - 0 ShADad 6 1468 4 950 (empty) +#close 2014-08-23-18-29-48 diff --git a/testing/btest/Baseline/core.pcap.read-trace-with-filter/packet_filter.log b/testing/btest/Baseline/core.pcap.read-trace-with-filter/packet_filter.log new file mode 100644 index 0000000000..75b09c608a --- /dev/null +++ b/testing/btest/Baseline/core.pcap.read-trace-with-filter/packet_filter.log @@ -0,0 +1,10 @@ +#separator \x09 +#set_separator , +#empty_field (empty) +#unset_field - +#path packet_filter +#open 2014-08-23-18-29-48 +#fields ts node filter init success +#types time string string bool bool +1408818588.510297 bro port 50000 T T +#close 2014-08-23-18-29-48 diff --git a/testing/btest/core/pcap/dumper.bro b/testing/btest/core/pcap/dumper.bro new file mode 100644 index 0000000000..9cf5cbe71c --- /dev/null +++ b/testing/btest/core/pcap/dumper.bro @@ -0,0 +1,5 @@ +# @TEST-EXEC: bro -r $TRACES/workshop_2011_browse.trace -w dump +# @TEST-EXEC: hexdump -C $TRACES/workshop_2011_browse.trace >1 +# @TEST-EXEC: hexdump -C dump >2 +# @TEST-EXEC: sdiff -s 1 2 >output || true +# @TEST-EXEC: btest-diff output diff --git a/testing/btest/core/pcap/dynamic-filter.bro b/testing/btest/core/pcap/dynamic-filter.bro new file mode 100644 index 0000000000..012858fa65 --- /dev/null +++ b/testing/btest/core/pcap/dynamic-filter.bro @@ -0,0 +1,32 @@ +# @TEST-EXEC: bro -C -r $TRACES/wikipedia.trace %INPUT >output +# @TEST-EXEC: btest-diff output +# @TEST-EXEC: btest-diff conn.log + +redef enum PcapFilterID += { A, B }; + +global cnt = 0; + +event new_packet(c: connection, p: pkt_hdr) + { + ++cnt; + + print cnt, c$id; + + if ( cnt == 1 ) + if ( ! install_pcap_filter(A) ) + print "error 3"; + + if ( cnt == 2 ) + if ( ! install_pcap_filter(B) ) + print "error 4"; + } + +event bro_init() + { + if ( ! precompile_pcap_filter(A, "port 80") ) + print "error 1"; + + if ( ! precompile_pcap_filter(B, "port 53") ) + print "error 2"; + } + diff --git a/testing/btest/core/pcap/filter-error.bro b/testing/btest/core/pcap/filter-error.bro new file mode 100644 index 0000000000..1f8ad7a464 --- /dev/null +++ b/testing/btest/core/pcap/filter-error.bro @@ -0,0 +1,16 @@ +# @TEST-EXEC-FAIL: bro -r $TRACES/workshop_2011_browse.trace -f "kaputt" >>output 2>&1 +# @TEST-EXEC-FAIL: test -e conn.log +# @TEST-EXEC: echo ---- >>output +# @TEST-EXEC: bro -r $TRACES/workshop_2011_browse.trace %INPUT >>output 2>&1 +# @TEST-EXEC: test -e conn.log +# @TEST-EXEC: btest-diff output + +redef enum PcapFilterID += { A }; + +event bro_init() + { + if ( ! precompile_pcap_filter(A, "kaputt, too") ) + print "error", pcap_error(); + } + + diff --git a/testing/btest/core/pcap/input-error.bro b/testing/btest/core/pcap/input-error.bro new file mode 100644 index 0000000000..2a0787c832 --- /dev/null +++ b/testing/btest/core/pcap/input-error.bro @@ -0,0 +1,14 @@ +# @TEST-EXEC-FAIL: bro -i NO_SUCH_INTERFACE 2>&1 >>output 2>&1 +# @TEST-EXEC: cat output | sed 's/(.*)//g' >output2 +# @TEST-EXEC-FAIL: bro -r NO_SUCH_TRACE 2>&1 >>output2 2>&1 +# @TEST-EXEC: btest-diff output2 + +redef enum PcapFilterID += { A }; + +event bro_init() + { + if ( ! precompile_pcap_filter(A, "kaputt, too") ) + print "error", pcap_error(); + } + + diff --git a/testing/btest/core/pcap/pseudo-realtime.bro b/testing/btest/core/pcap/pseudo-realtime.bro new file mode 100644 index 0000000000..625706f321 --- /dev/null +++ b/testing/btest/core/pcap/pseudo-realtime.bro @@ -0,0 +1,42 @@ +# @TEST-EXEC: bro -C -r $TRACES/wikipedia.trace %INPUT --pseudo-realtime >output +# @TEST-EXEC: btest-diff output + +global init = F; +global last_network = network_time(); +global last_current = current_time(); +global cnt = 0; +global an = 0secs; +global ac = 0secs; + +event new_packet(c: connection, p: pkt_hdr) + { + local tn = network_time(); + local tc = current_time(); + local dn = tn - last_network; + local dc = tc - last_current; + + last_network = tn; + last_current = tc; + ++cnt; + + if ( ! init ) + { + init = T; + return; + } + + an += dn; + ac += dc; + + # print fmt("num=%d agg_delta_network=%.1f agg_delta_real=%.1f", cnt, an, ac); + } + +event bro_done() + { + local d = (an - ac); + if ( d < 0 secs) + d = -d; + + print fmt("real time %s trace time", d < 1.0secs ? "matches" : "does NOT match"); + } + diff --git a/testing/btest/core/pcap/read-trace-with-filter.bro b/testing/btest/core/pcap/read-trace-with-filter.bro new file mode 100644 index 0000000000..5878bada64 --- /dev/null +++ b/testing/btest/core/pcap/read-trace-with-filter.bro @@ -0,0 +1,3 @@ +# @TEST-EXEC: bro -C -r $TRACES/wikipedia.trace -f "port 50000" +# @TEST-EXEC: btest-diff conn.log +# @TEST-EXEC: btest-diff packet_filter.log