Bugfixes and test updates.

This commit is contained in:
Robin Sommer 2014-09-05 18:20:23 -07:00
parent c1c4e6eb63
commit 4a66a8e341
19 changed files with 212 additions and 771 deletions

View file

@ -1,4 +0,0 @@
- Tests
- pktsrc plugin
- pktdump plugin

View file

@ -405,7 +405,7 @@ DNS_Mgr::~DNS_Mgr()
delete [] dir; delete [] dir;
} }
void DNS_Mgr::Init() void DNS_Mgr::InitPostScript()
{ {
if ( did_init ) if ( did_init )
return; return;

View file

@ -45,7 +45,7 @@ public:
DNS_Mgr(DNS_MgrMode mode); DNS_Mgr(DNS_MgrMode mode);
virtual ~DNS_Mgr(); virtual ~DNS_Mgr();
void Init(); void InitPostScript();
void Flush(); void Flush();
// Looks up the address or addresses of the given host, and returns // Looks up the address or addresses of the given host, and returns

View file

@ -1,709 +0,0 @@
// See the file "COPYING" in the main distribution directory for copyright.
#include <errno.h>
#include <sys/stat.h>
#include "config.h"
#include "util.h"
#include "PktSrc.h"
#include "Hash.h"
#include "Net.h"
#include "Sessions.h"
// ### This needs auto-confing.
#ifdef HAVE_PCAP_INT_H
#include <pcap-int.h>
#endif
PktSrc::PktSrc()
{
interface = readfile = 0;
data = last_data = 0;
memset(&hdr, 0, sizeof(hdr));
hdr_size = 0;
datalink = 0;
netmask = 0xffffff00;
pd = 0;
idle = false;
next_sync_point = 0;
first_timestamp = current_timestamp = next_timestamp = 0.0;
first_wallclock = current_wallclock = 0;
stats.received = stats.dropped = stats.link = 0;
}
PktSrc::~PktSrc()
{
Close();
loop_over_list(program_list, i)
delete program_list[i];
BPF_Program* code;
IterCookie* cookie = filters.InitForIteration();
while ( (code = filters.NextEntry(cookie)) )
delete code;
delete [] interface;
delete [] readfile;
}
void PktSrc::GetFds(int* read, int* write, int* except)
{
if ( pseudo_realtime )
{
// Select would give erroneous results. But we simulate it
// by setting idle accordingly.
idle = CheckPseudoTime() == 0;
return;
}
if ( selectable_fd >= 0 )
*read = selectable_fd;
}
int PktSrc::ExtractNextPacket()
{
// Don't return any packets if processing is suspended (except for the
// very first packet which we need to set up times).
if ( net_is_processing_suspended() && first_timestamp )
{
idle = true;
return 0;
}
data = last_data = pcap_next(pd, &hdr);
if ( data && (hdr.len == 0 || hdr.caplen == 0) )
{
sessions->Weird("empty_pcap_header", &hdr, data);
return 0;
}
if ( data )
next_timestamp = hdr.ts.tv_sec + double(hdr.ts.tv_usec) / 1e6;
if ( pseudo_realtime )
current_wallclock = current_time(true);
if ( ! first_timestamp )
first_timestamp = next_timestamp;
idle = (data == 0);
if ( data )
++stats.received;
// Source has gone dry. If it's a network interface, this just means
// it's timed out. If it's a file, though, then the file has been
// exhausted.
if ( ! data && ! IsLive() )
{
closed = true;
if ( pseudo_realtime && using_communication )
{
if ( remote_trace_sync_interval )
remote_serializer->SendFinalSyncPoint();
else
remote_serializer->Terminate();
}
}
return data != 0;
}
double PktSrc::NextTimestamp(double* local_network_time)
{
if ( ! data && ! ExtractNextPacket() )
return -1.0;
if ( pseudo_realtime )
{
// Delay packet if necessary.
double packet_time = CheckPseudoTime();
if ( packet_time )
return packet_time;
idle = true;
return -1.0;
}
return next_timestamp;
}
void PktSrc::ContinueAfterSuspend()
{
current_wallclock = current_time(true);
}
double PktSrc::CurrentPacketWallClock()
{
// We stop time when we are suspended.
if ( net_is_processing_suspended() )
current_wallclock = current_time(true);
return current_wallclock;
}
double PktSrc::CheckPseudoTime()
{
if ( ! data && ! ExtractNextPacket() )
return 0;
if ( ! current_timestamp )
return bro_start_time;
if ( remote_trace_sync_interval )
{
if ( next_sync_point == 0 || next_timestamp >= next_sync_point )
{
int n = remote_serializer->SendSyncPoint();
next_sync_point = first_timestamp +
n * remote_trace_sync_interval;
remote_serializer->Log(RemoteSerializer::LogInfo,
fmt("stopping at packet %.6f, next sync-point at %.6f",
current_timestamp, next_sync_point));
return 0;
}
}
double pseudo_time = next_timestamp - first_timestamp;
double ct = (current_time(true) - first_wallclock) * pseudo_realtime;
return pseudo_time <= ct ? bro_start_time + pseudo_time : 0;
}
void PktSrc::Process()
{
if ( ! data && ! ExtractNextPacket() )
return;
current_timestamp = next_timestamp;
int pkt_hdr_size = hdr_size;
// Unfortunately some packets on the link might have MPLS labels
// while others don't. That means we need to ask the link-layer if
// labels are in place.
bool have_mpls = false;
int protocol = 0;
switch ( datalink ) {
case DLT_NULL:
{
protocol = (data[3] << 24) + (data[2] << 16) + (data[1] << 8) + data[0];
// From the Wireshark Wiki: "AF_INET6, unfortunately, has
// different values in {NetBSD,OpenBSD,BSD/OS},
// {FreeBSD,DragonFlyBSD}, and {Darwin/Mac OS X}, so an IPv6
// packet might have a link-layer header with 24, 28, or 30
// as the AF_ value." As we may be reading traces captured on
// platforms other than what we're running on, we accept them
// all here.
if ( protocol != AF_INET
&& protocol != AF_INET6
&& protocol != 24
&& protocol != 28
&& protocol != 30 )
{
sessions->Weird("non_ip_packet_in_null_transport", &hdr, data);
data = 0;
return;
}
break;
}
case DLT_EN10MB:
{
// Get protocol being carried from the ethernet frame.
protocol = (data[12] << 8) + data[13];
switch ( protocol )
{
// MPLS carried over the ethernet frame.
case 0x8847:
// Remove the data link layer and denote a
// header size of zero before the IP header.
have_mpls = true;
data += get_link_header_size(datalink);
pkt_hdr_size = 0;
break;
// VLAN carried over the ethernet frame.
case 0x8100:
data += get_link_header_size(datalink);
// Check for MPLS in VLAN.
if ( ((data[2] << 8) + data[3]) == 0x8847 )
have_mpls = true;
data += 4; // Skip the vlan header
pkt_hdr_size = 0;
// Check for 802.1ah (Q-in-Q) containing IP.
// Only do a second layer of vlan tag
// stripping because there is no
// specification that allows for deeper
// nesting.
if ( ((data[2] << 8) + data[3]) == 0x0800 )
data += 4;
break;
// PPPoE carried over the ethernet frame.
case 0x8864:
data += get_link_header_size(datalink);
protocol = (data[6] << 8) + data[7];
data += 8; // Skip the PPPoE session and PPP header
pkt_hdr_size = 0;
if ( protocol != 0x0021 && protocol != 0x0057 )
{
// Neither IPv4 nor IPv6.
sessions->Weird("non_ip_packet_in_pppoe_encapsulation", &hdr, data);
data = 0;
return;
}
break;
}
break;
}
case DLT_PPP_SERIAL:
{
// Get PPP protocol.
protocol = (data[2] << 8) + data[3];
if ( protocol == 0x0281 )
{
// MPLS Unicast. Remove the data link layer and
// denote a header size of zero before the IP header.
have_mpls = true;
data += get_link_header_size(datalink);
pkt_hdr_size = 0;
}
else if ( protocol != 0x0021 && protocol != 0x0057 )
{
// Neither IPv4 nor IPv6.
sessions->Weird("non_ip_packet_in_ppp_encapsulation", &hdr, data);
data = 0;
return;
}
break;
}
}
if ( have_mpls )
{
// Skip the MPLS label stack.
bool end_of_stack = false;
while ( ! end_of_stack )
{
end_of_stack = *(data + 2) & 0x01;
data += 4;
}
}
if ( pseudo_realtime )
{
current_pseudo = CheckPseudoTime();
net_packet_dispatch(current_pseudo, &hdr, data, pkt_hdr_size, this);
if ( ! first_wallclock )
first_wallclock = current_time(true);
}
else
net_packet_dispatch(current_timestamp, &hdr, data, pkt_hdr_size, this);
data = 0;
}
bool PktSrc::GetCurrentPacket(const struct pcap_pkthdr** arg_hdr,
const u_char** arg_pkt)
{
if ( ! last_data )
return false;
*arg_hdr = &hdr;
*arg_pkt = last_data;
return true;
}
int PktSrc::PrecompileFilter(int index, const char* filter)
{
// Compile filter.
BPF_Program* code = new BPF_Program();
if ( ! code->Compile(pd, filter, netmask, errbuf, sizeof(errbuf)) )
{
delete code;
return 0;
}
// Store it in hash.
HashKey* hash = new HashKey(HashKey(bro_int_t(index)));
BPF_Program* oldcode = filters.Lookup(hash);
if ( oldcode )
delete oldcode;
filters.Insert(hash, code);
delete hash;
return 1;
}
int PktSrc::SetFilter(int index)
{
HashKey* hash = new HashKey(HashKey(bro_int_t(index)));
BPF_Program* code = filters.Lookup(hash);
delete hash;
if ( ! code )
{
safe_snprintf(errbuf, sizeof(errbuf),
"No precompiled pcap filter for index %d",
index);
return 0;
}
if ( pcap_setfilter(pd, code->GetProgram()) < 0 )
{
safe_snprintf(errbuf, sizeof(errbuf),
"pcap_setfilter(%d): %s",
index, pcap_geterr(pd));
return 0;
}
#ifndef HAVE_LINUX
// Linux doesn't clear counters when resetting filter.
stats.received = stats.dropped = stats.link = 0;
#endif
return 1;
}
void PktSrc::SetHdrSize()
{
int dl = pcap_datalink(pd);
hdr_size = get_link_header_size(dl);
if ( hdr_size < 0 )
{
safe_snprintf(errbuf, sizeof(errbuf),
"unknown data link type 0x%x", dl);
Close();
}
datalink = dl;
}
void PktSrc::Close()
{
if ( pd )
{
pcap_close(pd);
pd = 0;
closed = true;
}
}
void PktSrc::Statistics(Stats* s)
{
if ( reading_traces )
s->received = s->dropped = s->link = 0;
else
{
struct pcap_stat pstat;
if ( pcap_stats(pd, &pstat) < 0 )
{
reporter->Error("problem getting packet filter statistics: %s",
ErrorMsg());
s->received = s->dropped = s->link = 0;
}
else
{
s->dropped = pstat.ps_drop;
s->link = pstat.ps_recv;
}
}
s->received = stats.received;
if ( pseudo_realtime )
s->dropped = 0;
stats.dropped = s->dropped;
}
PktInterfaceSrc::PktInterfaceSrc(const char* arg_interface, const char* filter,
PktSrc_Filter_Type ft)
: PktSrc()
{
char tmp_errbuf[PCAP_ERRBUF_SIZE];
filter_type = ft;
// Determine interface if not specified.
if ( ! arg_interface && ! (arg_interface = pcap_lookupdev(tmp_errbuf)) )
{
safe_snprintf(errbuf, sizeof(errbuf),
"pcap_lookupdev: %s", tmp_errbuf);
return;
}
interface = copy_string(arg_interface);
// Determine network and netmask.
uint32 net;
if ( pcap_lookupnet(interface, &net, &netmask, tmp_errbuf) < 0 )
{
// ### The lookup can fail if no address is assigned to
// the interface; and libpcap doesn't have any useful notion
// of error codes, just error strings - how bogus - so we
// just kludge around the error :-(.
// sprintf(errbuf, "pcap_lookupnet %s", tmp_errbuf);
// return;
net = 0;
netmask = 0xffffff00;
}
// We use the smallest time-out possible to return almost immediately if
// no packets are available. (We can't use set_nonblocking() as it's
// broken on FreeBSD: even when select() indicates that we can read
// something, we may get nothing if the store buffer hasn't filled up
// yet.)
pd = pcap_open_live(interface, snaplen, 1, 1, tmp_errbuf);
if ( ! pd )
{
safe_snprintf(errbuf, sizeof(errbuf),
"pcap_open_live: %s", tmp_errbuf);
closed = true;
return;
}
// ### This needs autoconf'ing.
#ifdef HAVE_PCAP_INT_H
reporter->Info("pcap bufsize = %d\n", ((struct pcap *) pd)->bufsize);
#endif
#ifdef HAVE_LINUX
if ( pcap_setnonblock(pd, 1, tmp_errbuf) < 0 )
{
safe_snprintf(errbuf, sizeof(errbuf),
"pcap_setnonblock: %s", tmp_errbuf);
pcap_close(pd);
closed = true;
return;
}
#endif
selectable_fd = pcap_fileno(pd);
if ( PrecompileFilter(0, filter) && SetFilter(0) )
{
SetHdrSize();
if ( closed )
// Couldn't get header size.
return;
reporter->Info("listening on %s, capture length %d bytes\n", interface, snaplen);
}
else
closed = true;
}
PktFileSrc::PktFileSrc(const char* arg_readfile, const char* filter,
PktSrc_Filter_Type ft)
: PktSrc()
{
readfile = copy_string(arg_readfile);
filter_type = ft;
pd = pcap_open_offline((char*) readfile, errbuf);
if ( pd && PrecompileFilter(0, filter) && SetFilter(0) )
{
SetHdrSize();
if ( closed )
// Unknown link layer type.
return;
// We don't put file sources into non-blocking mode as
// otherwise we would not be able to identify the EOF.
selectable_fd = fileno(pcap_file(pd));
if ( selectable_fd < 0 )
reporter->InternalError("OS does not support selectable pcap fd");
}
else
closed = true;
}
PktDumper::PktDumper(const char* arg_filename, bool arg_append)
{
filename[0] = '\0';
is_error = false;
append = arg_append;
dumper = 0;
open_time = 0.0;
// We need a pcap_t with a reasonable link-layer type. We try to get it
// from the packet sources. If not available, we fall back to Ethernet.
// FIXME: Perhaps we should make this configurable?
int linktype = -1;
if ( pkt_srcs.length() )
linktype = pkt_srcs[0]->LinkType();
if ( linktype < 0 )
linktype = DLT_EN10MB;
pd = pcap_open_dead(linktype, snaplen);
if ( ! pd )
{
Error("error for pcap_open_dead");
return;
}
if ( arg_filename )
Open(arg_filename);
}
bool PktDumper::Open(const char* arg_filename)
{
if ( ! arg_filename && ! *filename )
{
Error("no filename given");
return false;
}
if ( arg_filename )
{
if ( dumper && streq(arg_filename, filename) )
// Already open.
return true;
safe_strncpy(filename, arg_filename, FNBUF_LEN);
}
if ( dumper )
Close();
struct stat s;
int exists = 0;
if ( append )
{
// See if output file already exists (and is non-empty).
exists = stat(filename, &s); ;
if ( exists < 0 && errno != ENOENT )
{
Error(fmt("can't stat file %s: %s", filename, strerror(errno)));
return false;
}
}
if ( ! append || exists < 0 || s.st_size == 0 )
{
// Open new file.
dumper = pcap_dump_open(pd, filename);
if ( ! dumper )
{
Error(pcap_geterr(pd));
return false;
}
}
else
{
// Old file and we need to append, which, unfortunately,
// is not supported by libpcap. So, we have to hack a
// little bit, knowing that pcap_dumpter_t is, in fact,
// a FILE ... :-(
dumper = (pcap_dumper_t*) fopen(filename, "a");
if ( ! dumper )
{
Error(fmt("can't open dump %s: %s", filename, strerror(errno)));
return false;
}
}
open_time = network_time;
is_error = false;
return true;
}
bool PktDumper::Close()
{
if ( dumper )
{
pcap_dump_close(dumper);
dumper = 0;
is_error = false;
}
return true;
}
bool PktDumper::Dump(const struct pcap_pkthdr* hdr, const u_char* pkt)
{
if ( ! dumper )
return false;
if ( ! open_time )
open_time = network_time;
pcap_dump((u_char*) dumper, hdr, pkt);
return true;
}
void PktDumper::Error(const char* errstr)
{
safe_strncpy(errbuf, errstr, sizeof(errbuf));
is_error = true;
}
int get_link_header_size(int dl)
{
switch ( dl ) {
case DLT_NULL:
return 4;
case DLT_EN10MB:
return 14;
case DLT_FDDI:
return 13 + 8; // fddi_header + LLC
#ifdef DLT_LINUX_SLL
case DLT_LINUX_SLL:
return 16;
#endif
case DLT_PPP_SERIAL: // PPP_SERIAL
return 4;
case DLT_RAW:
return 0;
}
return -1;
}

View file

@ -558,7 +558,7 @@ RemoteSerializer::~RemoteSerializer()
delete io; delete io;
} }
void RemoteSerializer::Init() void RemoteSerializer::Enable()
{ {
if ( initialized ) if ( initialized )
return; return;

View file

@ -28,7 +28,7 @@ public:
virtual ~RemoteSerializer(); virtual ~RemoteSerializer();
// Initialize the remote serializer (calling this will fork). // Initialize the remote serializer (calling this will fork).
void Init(); void Enable();
// FIXME: Use SourceID directly (or rename everything to Peer*). // FIXME: Use SourceID directly (or rename everything to Peer*).
typedef SourceID PeerID; typedef SourceID PeerID;

View file

@ -4459,7 +4459,7 @@ function enable_communication%(%): any
return 0; return 0;
using_communication = 1; using_communication = 1;
remote_serializer->Init(); remote_serializer->Enable();
return 0; return 0;
%} %}

View file

@ -1,3 +1,4 @@
// See the file "COPYING" in the main distribution directory for copyright.
#include "Component.h" #include "Component.h"

View file

@ -22,7 +22,10 @@ public:
typedef IOSource* (*factory_callback)(); typedef IOSource* (*factory_callback)();
/** /**
* XXX * Constructor.
*
* @param name A descriptive name for the component. This name must
* be unique across all components of this type.
*/ */
Component(const std::string& name); Component(const std::string& name);
@ -38,7 +41,12 @@ public:
protected: protected:
/** /**
* XXXX * Constructor to use by derived classes.
*
* @param type The type of the componnent.
*
* @param name A descriptive name for the component. This name must
* be unique across all components of this type.
*/ */
Component(plugin::component::Type type, const std::string& name); Component(plugin::component::Type type, const std::string& name);
}; };
@ -48,12 +56,29 @@ protected:
*/ */
class PktSrcComponent : public iosource::Component { class PktSrcComponent : public iosource::Component {
public: public:
enum InputType { LIVE, TRACE, BOTH }; /**
* Type of input a packet source supports.
*/
enum InputType {
LIVE, ///< Live input.
TRACE, ///< Offline input from trace file.
BOTH ///< Live input as well as offline.
};
typedef PktSrc* (*factory_callback)(const std::string& path, bool is_live); typedef PktSrc* (*factory_callback)(const std::string& path, bool is_live);
/** /**
* XXX * Constructor.
*
* @param name A descriptive name for the component. This name must
* be unique across all components of this type.
*
* @param prefixes The list of interface/file prefixes associated
* with this component.
*
* @param type Type of input the component supports.
*
* @param factor Factory function to instantiate component.
*/ */
PktSrcComponent(const std::string& name, const std::string& prefixes, InputType type, factory_callback factory); PktSrcComponent(const std::string& name, const std::string& prefixes, InputType type, factory_callback factory);

View file

@ -14,56 +14,120 @@ extern "C" {
namespace iosource { namespace iosource {
/** /**
* Interface class for components providing/consuming data inside Bro's main loop. * Interface class for components providing/consuming data inside Bro's main
* loop.
*/ */
class IOSource { class IOSource {
public: public:
/**
* Constructor.
*/
IOSource() { idle = false; closed = false; } IOSource() { idle = false; closed = false; }
/**
* Destructor.
*/
virtual ~IOSource() {} virtual ~IOSource() {}
// Returns true if source has nothing ready to process. /**
* Returns true if source has nothing ready to process.
*/
bool IsIdle() const { return idle; } bool IsIdle() const { return idle; }
// Returns true if more data is to be expected in the future. /**
// Otherwise, source may be removed. * Returns true if more data is to be expected in the future.
* Otherwise, source may be removed.
*/
bool IsOpen() const { return ! closed; } bool IsOpen() const { return ! closed; }
// XXX /**
* Initializes the source. Can be overwritten by derived classes.
*/
virtual void Init() { } virtual void Init() { }
// XXX /**
* Finalizes the source when it's being closed. Can be overwritten by
* derived classes.
*/
virtual void Done() { } virtual void Done() { }
// Returns select'able fds (leaves args untouched if we don't have /**
// selectable fds). * Returns select'able file descriptors for this source. Leaves the
* passed values untouched if not available.
*
* @param read Pointer to where to store a read descriptor.
*
* @param write Pointer to where to store a write descriptor.
*
* @param except Pointer to where to store a except descriptor.
*/
virtual void GetFds(int* read, int* write, int* except) = 0; virtual void GetFds(int* read, int* write, int* except) = 0;
// The following two methods are only called when either IsIdle() /**
// returns false or select() on one of the fds indicates that there's * Returns the timestamp (in \a global network time) associated with
// data to process. * next data item from this source. If the source wants the data
* item to be processed with a local network time, it sets the
// Returns timestamp (in global network time) associated with next * argument accordingly.
// data item. If the source wants the data item to be processed *
// with a local network time, it sets the argument accordingly. * This method will be called only when either IsIdle() returns
* false, or select() on one of the fds returned by GetFDs()
* indicates that there's data to process.
*
* Must be overridden by derived classes.
*
* @param network_time A pointer to store the \a local network time
* associated with the next item (as opposed to global network time).
*
* @return The global network time of the next entry, or a value
* smaller than zero if none is available currently.
*/
virtual double NextTimestamp(double* network_time) = 0; virtual double NextTimestamp(double* network_time) = 0;
// Processes and consumes next data item. /**
* Processes and consumes next data item.
*
* This method will be called only when either IsIdle() returns
* false, or select() on one of the fds returned by GetFDs()
* indicates that there's data to process.
*
* Must be overridden by derived classes.
*/
virtual void Process() = 0; virtual void Process() = 0;
// Returns tag of timer manager associated with last processed /**
// data item, nil for global timer manager. * Returns the tag of the timer manafger associated with the last
* procesees data item.
*
* Can be overridden by derived classes.
*
* @return The tag, or null for the global timer manager.
*
*/
virtual TimerMgr::Tag* GetCurrentTag() { return 0; } virtual TimerMgr::Tag* GetCurrentTag() { return 0; }
// Returns a descriptual tag for debugging. /**
* Returns a descriptual tag representing the source for debugging.
*
* Can be overridden by derived classes.
*
* @return The debugging name.
*/
virtual const char* Tag() = 0; virtual const char* Tag() = 0;
protected: protected:
// Derived classed are to set this to true if they have gone dry /*
// temporarily. * Callback for derived classes to call when they have gone dry
* temporarily.
*
* @param is_idle True if the source is idle currently.
*/
void SetIdle(bool is_idle) { idle = is_idle; } void SetIdle(bool is_idle) { idle = is_idle; }
// Derived classed are to set this to true if they have gone dry /*
// temporarily. * Callback for derived class to call when they have shutdown.
*
* @param is_closed True if the source is now closed.
*/
void SetClosed(bool is_closed) { closed = is_closed; } void SetClosed(bool is_closed) { closed = is_closed; }
private: private:

View file

@ -1,3 +1,4 @@
// See the file "COPYING" in the main distribution directory for copyright.
#include <sys/types.h> #include <sys/types.h>
#include <sys/time.h> #include <sys/time.h>
@ -22,7 +23,7 @@ Manager::~Manager()
{ {
for ( SourceList::iterator i = sources.begin(); i != sources.end(); ++i ) for ( SourceList::iterator i = sources.begin(); i != sources.end(); ++i )
{ {
// ??? (*i)->src->Done(); (*i)->src->Done();
delete *i; delete *i;
} }

View file

@ -12,43 +12,100 @@ class IOSource;
class PktSrc; class PktSrc;
class PktDumper; class PktDumper;
/**
* Singleton class managing all IOSources.
*/
class Manager { class Manager {
public: public:
/**
* Constructor.
*/
Manager() { call_count = 0; dont_counts = 0; } Manager() { call_count = 0; dont_counts = 0; }
/**
* Destructor.
*/
~Manager(); ~Manager();
// If dont_count is true, this source does not contribute to the /**
// number of IOSources returned by Size(). The effect is that * Registers an IOSource with the manager.
// if all sources but the non-counting ones have gone dry, *
// processing will shut down. * @param src The source. The manager takes ownership.
*
* @param dont_count If true, this source does not contribute to the
* number of IOSources returned by Size(). The effect is that if all
* sources except for the non-counting ones have gone dry, processing
* will shut down.
*/
void Register(IOSource* src, bool dont_count = false); void Register(IOSource* src, bool dont_count = false);
// This may block for some time. /**
* Returns the packet source with the soonest available input. This
* may block for a little while if all are dry.
*
* @param ts A pointer where to store the timestamp of the input that
* the soonest source has available next.
*
* @return The source, or null if no source has input.
*/
IOSource* FindSoonest(double* ts); IOSource* FindSoonest(double* ts);
/**
* Returns the number of registered and still active sources,
* excluding those that are registered as \a dont_cont.
*/
int Size() const { return sources.size() - dont_counts; } int Size() const { return sources.size() - dont_counts; }
typedef std::list<PktSrc *> PktSrcList; typedef std::list<PktSrc *> PktSrcList;
/**
* Returns a list of all registered PktSrc instances. This is a
* subset of all registered IOSource instances.
*/
const PktSrcList& GetPktSrcs() const { return pkt_srcs; } const PktSrcList& GetPktSrcs() const { return pkt_srcs; }
// Terminate IOSource processing immediately by removing all /**
// sources (and therefore returning a Size() of zero). * Terminate all processing immediately by removing all sources (and
* therefore now returning a Size() of zero).
*/
void Terminate() { RemoveAll(); } void Terminate() { RemoveAll(); }
/**
* Opens a new packet source.
*
* @param path The interface or file name, as one would give to Bro \c -i.
*
* @param is_live True if \a path represents a live interface, false
* for a file.
*
* @return The new packet source, or null if an error occured.
*/
PktSrc* OpenPktSrc(const std::string& path, bool is_live); PktSrc* OpenPktSrc(const std::string& path, bool is_live);
/**
* Opens a new packet dumper.
*
* @param path The file name to dump into.
*
* @param append True to append if \a path already exists.
*
* @return The new packet dumper, or null if an error occured.
*/
PktDumper* OpenPktDumper(const std::string& path, bool append); PktDumper* OpenPktDumper(const std::string& path, bool append);
protected: private:
void Register(PktSrc* src); /**
* When looking for a source with something to process, every
// When looking for a source with something to process, * SELECT_FREQUENCY calls we will go ahead and block on a select().
// every SELECT_FREQUENCY calls we will go ahead and */
// block on a select().
static const int SELECT_FREQUENCY = 25; static const int SELECT_FREQUENCY = 25;
// Microseconds to wait in an empty select if no source is ready. /**
* Microseconds to wait in an empty select if no source is ready.
*/
static const int SELECT_TIMEOUT = 50; static const int SELECT_TIMEOUT = 50;
void Register(PktSrc* src);
void RemoveAll(); void RemoveAll();
unsigned int call_count; unsigned int call_count;

View file

@ -7,6 +7,9 @@
namespace iosource { namespace iosource {
/**
* Base class for packet dumpers.
*/
class PktDumper { class PktDumper {
public: public:
/** /**

View file

@ -387,13 +387,13 @@ void PktSrc::Process()
if ( pseudo_realtime ) if ( pseudo_realtime )
{ {
current_pseudo = CheckPseudoTime(); current_pseudo = CheckPseudoTime();
net_packet_dispatch(current_pseudo, current_packet.hdr, current_packet.data, pkt_hdr_size, this); net_packet_dispatch(current_pseudo, current_packet.hdr, data, pkt_hdr_size, this);
if ( ! first_wallclock ) if ( ! first_wallclock )
first_wallclock = current_time(true); first_wallclock = current_time(true);
} }
else else
net_packet_dispatch(current_packet.ts, current_packet.hdr, current_packet.data, pkt_hdr_size, this); net_packet_dispatch(current_packet.ts, current_packet.hdr, data, pkt_hdr_size, this);
have_packet = 0; have_packet = 0;
DoneWithPacket(); DoneWithPacket();

View file

@ -11,6 +11,9 @@ declare(PDict,BPF_Program);
namespace iosource { namespace iosource {
/**
* Base class for packet sources.
*/
class PktSrc : public IOSource { class PktSrc : public IOSource {
public: public:
/** /**

View file

@ -1,3 +1,4 @@
// See the file in the main distribution directory for copyright.
#ifndef IOSOURCE_PKTSRC_PCAP_DUMPER_H #ifndef IOSOURCE_PKTSRC_PCAP_DUMPER_H
#define IOSOURCE_PKTSRC_PCAP_DUMPER_H #define IOSOURCE_PKTSRC_PCAP_DUMPER_H

View file

@ -1,3 +1,4 @@
// See the file in the main distribution directory for copyright.
#include <assert.h> #include <assert.h>

View file

@ -377,18 +377,14 @@ void terminate_bro()
delete broxygen_mgr; delete broxygen_mgr;
delete timer_mgr; delete timer_mgr;
delete dns_mgr;
delete persistence_serializer; delete persistence_serializer;
delete event_player;
delete event_serializer; delete event_serializer;
delete state_serializer; delete state_serializer;
delete event_registry; delete event_registry;
delete remote_serializer;
delete analyzer_mgr; delete analyzer_mgr;
delete file_mgr; delete file_mgr;
delete log_mgr; delete log_mgr;
delete plugin_mgr; delete plugin_mgr;
delete thread_mgr;
delete reporter; delete reporter;
delete iosource_mgr; delete iosource_mgr;
@ -841,6 +837,7 @@ int main(int argc, char** argv)
// policy, but we can't parse policy without DNS resolution. // policy, but we can't parse policy without DNS resolution.
dns_mgr->SetDir(".state"); dns_mgr->SetDir(".state");
iosource_mgr = new iosource::Manager();
persistence_serializer = new PersistenceSerializer(); persistence_serializer = new PersistenceSerializer();
remote_serializer = new RemoteSerializer(); remote_serializer = new RemoteSerializer();
event_registry = new EventRegistry(); event_registry = new EventRegistry();
@ -848,7 +845,6 @@ int main(int argc, char** argv)
log_mgr = new logging::Manager(); log_mgr = new logging::Manager();
input_mgr = new input::Manager(); input_mgr = new input::Manager();
file_mgr = new file_analysis::Manager(); file_mgr = new file_analysis::Manager();
iosource_mgr = new iosource::Manager();
plugin_mgr->InitPreScript(); plugin_mgr->InitPreScript();
analyzer_mgr->InitPreScript(); analyzer_mgr->InitPreScript();
@ -908,6 +904,7 @@ int main(int argc, char** argv)
analyzer_mgr->InitPostScript(); analyzer_mgr->InitPostScript();
file_mgr->InitPostScript(); file_mgr->InitPostScript();
dns_mgr->InitPostScript();
if ( parse_only ) if ( parse_only )
{ {

View file

@ -3,7 +3,7 @@
#empty_field (empty) #empty_field (empty)
#unset_field - #unset_field -
#path loaded_scripts #path loaded_scripts
#open 2014-08-14-04-31-10 #open 2014-09-06-01-19-42
#fields name #fields name
#types string #types string
scripts/base/init-bare.bro scripts/base/init-bare.bro
@ -43,6 +43,7 @@ scripts/base/init-bare.bro
scripts/base/frameworks/files/magic/__load__.bro scripts/base/frameworks/files/magic/__load__.bro
build/scripts/base/bif/__load__.bro build/scripts/base/bif/__load__.bro
build/scripts/base/bif/broxygen.bif.bro build/scripts/base/bif/broxygen.bif.bro
build/scripts/base/bif/pcap.bif.bro
build/scripts/base/bif/bloom-filter.bif.bro build/scripts/base/bif/bloom-filter.bif.bro
build/scripts/base/bif/cardinality-counter.bif.bro build/scripts/base/bif/cardinality-counter.bif.bro
build/scripts/base/bif/top-k.bif.bro build/scripts/base/bif/top-k.bif.bro
@ -113,4 +114,4 @@ scripts/base/init-bare.bro
build/scripts/base/bif/plugins/Bro_SQLiteWriter.sqlite.bif.bro build/scripts/base/bif/plugins/Bro_SQLiteWriter.sqlite.bif.bro
scripts/policy/misc/loaded-scripts.bro scripts/policy/misc/loaded-scripts.bro
scripts/base/utils/paths.bro scripts/base/utils/paths.bro
#close 2014-08-14-04-31-10 #close 2014-09-06-01-19-42