mirror of
https://github.com/zeek/zeek.git
synced 2025-10-02 14:48:21 +00:00
Interface tweaks for PktSrc, plus docs for PktSrc and PktDumper.
This commit is contained in:
parent
5f817513d0
commit
3e669daa05
15 changed files with 464 additions and 101 deletions
|
@ -1 +0,0 @@
|
||||||
Subproject commit 6de518922e5f89d52d831ea6fb6adb7fff94437e
|
|
|
@ -153,8 +153,7 @@ void net_update_time(double new_network_time)
|
||||||
}
|
}
|
||||||
|
|
||||||
void net_init(name_list& interfaces, name_list& readfiles,
|
void net_init(name_list& interfaces, name_list& readfiles,
|
||||||
const char* writefile, const char* filter,
|
const char* writefile, int do_watchdog)
|
||||||
int do_watchdog)
|
|
||||||
{
|
{
|
||||||
if ( readfiles.length() > 0 )
|
if ( readfiles.length() > 0 )
|
||||||
{
|
{
|
||||||
|
@ -163,7 +162,7 @@ void net_init(name_list& interfaces, name_list& readfiles,
|
||||||
|
|
||||||
for ( int i = 0; i < readfiles.length(); ++i )
|
for ( int i = 0; i < readfiles.length(); ++i )
|
||||||
{
|
{
|
||||||
iosource::PktSrc* ps = iosource_mgr->OpenPktSrc(readfiles[i], filter, false);
|
iosource::PktSrc* ps = iosource_mgr->OpenPktSrc(readfiles[i], false);
|
||||||
assert(ps);
|
assert(ps);
|
||||||
|
|
||||||
if ( ! ps->IsOpen() )
|
if ( ! ps->IsOpen() )
|
||||||
|
@ -180,7 +179,7 @@ void net_init(name_list& interfaces, name_list& readfiles,
|
||||||
|
|
||||||
for ( int i = 0; i < interfaces.length(); ++i )
|
for ( int i = 0; i < interfaces.length(); ++i )
|
||||||
{
|
{
|
||||||
iosource::PktSrc* ps = iosource_mgr->OpenPktSrc(interfaces[i], filter, true);
|
iosource::PktSrc* ps = iosource_mgr->OpenPktSrc(interfaces[i], true);
|
||||||
assert(ps);
|
assert(ps);
|
||||||
|
|
||||||
if ( ! ps->IsOpen() )
|
if ( ! ps->IsOpen() )
|
||||||
|
|
|
@ -13,8 +13,7 @@
|
||||||
#include "iosource/PktDumper.h"
|
#include "iosource/PktDumper.h"
|
||||||
|
|
||||||
extern void net_init(name_list& interfaces, name_list& readfiles,
|
extern void net_init(name_list& interfaces, name_list& readfiles,
|
||||||
const char* writefile, const char* filter,
|
const char* writefile, int do_watchdog);
|
||||||
int do_watchdog);
|
|
||||||
extern void net_run();
|
extern void net_run();
|
||||||
extern void net_get_final_stats();
|
extern void net_get_final_stats();
|
||||||
extern void net_finish(int drain_events);
|
extern void net_finish(int drain_events);
|
||||||
|
|
|
@ -86,6 +86,7 @@ bool BPF_Program::Compile(pcap_t* pcap, const char* filter, uint32 netmask,
|
||||||
}
|
}
|
||||||
|
|
||||||
m_compiled = true;
|
m_compiled = true;
|
||||||
|
m_matches_anything = (strlen(filter) == 0 || strcmp(filter, "ip or not ip") == 0);
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
|
@ -37,6 +37,10 @@ public:
|
||||||
// code, false otherwise.
|
// code, false otherwise.
|
||||||
bool IsCompiled() { return m_compiled; }
|
bool IsCompiled() { return m_compiled; }
|
||||||
|
|
||||||
|
// Returns true if this program matches any packets. This is not
|
||||||
|
// comprehensive, but can identify a few cases where it does.
|
||||||
|
bool MatchesAnything() { return m_matches_anything; }
|
||||||
|
|
||||||
// Accessor to the compiled program. Returns nil when
|
// Accessor to the compiled program. Returns nil when
|
||||||
// no program is currently compiled.
|
// no program is currently compiled.
|
||||||
bpf_program* GetProgram();
|
bpf_program* GetProgram();
|
||||||
|
@ -47,6 +51,7 @@ protected:
|
||||||
// (I like to prefix member variables with m_, makes it clear
|
// (I like to prefix member variables with m_, makes it clear
|
||||||
// in the implementation whether it's a global or not. --ck)
|
// in the implementation whether it's a global or not. --ck)
|
||||||
bool m_compiled;
|
bool m_compiled;
|
||||||
|
bool m_matches_anything;
|
||||||
struct bpf_program m_program;
|
struct bpf_program m_program;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -50,7 +50,7 @@ class PktSrcComponent : public iosource::Component {
|
||||||
public:
|
public:
|
||||||
enum InputType { LIVE, TRACE, BOTH };
|
enum InputType { LIVE, TRACE, BOTH };
|
||||||
|
|
||||||
typedef PktSrc* (*factory_callback)(const std::string& path, const std::string& filter, bool is_live);
|
typedef PktSrc* (*factory_callback)(const std::string& path, bool is_live);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* XXX
|
* XXX
|
||||||
|
|
|
@ -222,7 +222,7 @@ static std::pair<std::string, std::string> split_prefix(std::string path)
|
||||||
return std::make_pair(prefix, path);
|
return std::make_pair(prefix, path);
|
||||||
}
|
}
|
||||||
|
|
||||||
PktSrc* Manager::OpenPktSrc(const std::string& path, const std::string& filter, bool is_live)
|
PktSrc* Manager::OpenPktSrc(const std::string& path, bool is_live)
|
||||||
{
|
{
|
||||||
std::pair<std::string, std::string> t = split_prefix(path);
|
std::pair<std::string, std::string> t = split_prefix(path);
|
||||||
std::string prefix = t.first;
|
std::string prefix = t.first;
|
||||||
|
@ -254,10 +254,10 @@ PktSrc* Manager::OpenPktSrc(const std::string& path, const std::string& filter,
|
||||||
|
|
||||||
// Instantiate packet source.
|
// Instantiate packet source.
|
||||||
|
|
||||||
PktSrc* ps = (*component->Factory())(npath, filter, is_live);
|
PktSrc* ps = (*component->Factory())(npath, is_live);
|
||||||
assert(ps);
|
assert(ps);
|
||||||
|
|
||||||
if ( ! ps->IsOpen() && ps->ErrorMsg() )
|
if ( ! ps->IsOpen() && ps->IsError() )
|
||||||
// Set an error message if it didn't open successfully.
|
// Set an error message if it didn't open successfully.
|
||||||
ps->Error("could not open");
|
ps->Error("could not open");
|
||||||
|
|
||||||
|
@ -298,7 +298,7 @@ PktDumper* Manager::OpenPktDumper(const string& path, bool append)
|
||||||
PktDumper* pd = (*component->Factory())(npath, append);
|
PktDumper* pd = (*component->Factory())(npath, append);
|
||||||
assert(pd);
|
assert(pd);
|
||||||
|
|
||||||
if ( ! pd->IsOpen() && pd->ErrorMsg() )
|
if ( ! pd->IsOpen() && pd->IsError() )
|
||||||
// Set an error message if it didn't open successfully.
|
// Set an error message if it didn't open successfully.
|
||||||
pd->Error("could not open");
|
pd->Error("could not open");
|
||||||
|
|
||||||
|
|
|
@ -35,7 +35,7 @@ public:
|
||||||
// sources (and therefore returning a Size() of zero).
|
// sources (and therefore returning a Size() of zero).
|
||||||
void Terminate() { RemoveAll(); }
|
void Terminate() { RemoveAll(); }
|
||||||
|
|
||||||
PktSrc* OpenPktSrc(const std::string& path, const std::string& filter, bool is_live);
|
PktSrc* OpenPktSrc(const std::string& path, bool is_live);
|
||||||
PktDumper* OpenPktDumper(const std::string& path, bool append);
|
PktDumper* OpenPktDumper(const std::string& path, bool append);
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
|
|
|
@ -9,45 +9,145 @@ namespace iosource {
|
||||||
|
|
||||||
class PktDumper {
|
class PktDumper {
|
||||||
public:
|
public:
|
||||||
|
/**
|
||||||
|
* Structure describing a packet.
|
||||||
|
*/
|
||||||
struct Packet {
|
struct Packet {
|
||||||
|
/**
|
||||||
|
* The pcap header associated with the packet.
|
||||||
|
*/
|
||||||
const struct pcap_pkthdr* hdr;
|
const struct pcap_pkthdr* hdr;
|
||||||
const u_char* data;
|
|
||||||
|
/**
|
||||||
|
* The full content of the packet.
|
||||||
|
*/
|
||||||
|
const unsigned char* data;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Constructor.
|
||||||
|
*/
|
||||||
PktDumper();
|
PktDumper();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Destructor.
|
||||||
|
*/
|
||||||
virtual ~PktDumper();
|
virtual ~PktDumper();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the path associated with the dumper.
|
||||||
|
*/
|
||||||
const std::string& Path() const;
|
const std::string& Path() const;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns true if the dumper is open for writing.
|
||||||
|
*/
|
||||||
bool IsOpen() const;
|
bool IsOpen() const;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the time when the dumper was opened for writing.
|
||||||
|
*/
|
||||||
double OpenTime() const;
|
double OpenTime() const;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns returns true if the dumper has encountered an error.
|
||||||
|
*/
|
||||||
bool IsError() const;
|
bool IsError() const;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns if the dumper has encountered an error, returns a
|
||||||
|
* corresponding error message. Returns an emoty string otherwise.
|
||||||
|
*/
|
||||||
const char* ErrorMsg() const;
|
const char* ErrorMsg() const;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the size of the link-layer headers with this dumper.
|
||||||
|
*/
|
||||||
int HdrSize() const;
|
int HdrSize() const;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Writes a packet to the dumper.
|
||||||
|
*
|
||||||
|
* @param pkt The packet to record.
|
||||||
|
*/
|
||||||
bool Record(const Packet* pkt);
|
bool Record(const Packet* pkt);
|
||||||
|
|
||||||
// PktDumper interface for derived classes to implement.
|
// PktDumper interface for derived classes to implement.
|
||||||
virtual void Close() = 0;
|
|
||||||
|
/**
|
||||||
|
* Called by the manager system to open the source.
|
||||||
|
*
|
||||||
|
* Derived classes must implement this method. If successful, the
|
||||||
|
* implementation must call \a Opened(); if not, it must call Error()
|
||||||
|
* with a corresponding message.
|
||||||
|
*/
|
||||||
virtual void Open() = 0;
|
virtual void Open() = 0;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Called by the manager system to close the dumper.
|
||||||
|
*
|
||||||
|
* Derived classes must implement this method. If successful, the
|
||||||
|
* implementation must call \a Closed(); if not, it must call Error()
|
||||||
|
* with a corresponding message.
|
||||||
|
*/
|
||||||
|
virtual void Close() = 0;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Called to write a packet to the dumper.
|
||||||
|
*
|
||||||
|
* Derived classes must implement this method.
|
||||||
|
*
|
||||||
|
* @param pkt The packet to record.
|
||||||
|
*
|
||||||
|
* @return True if succesful, false otherwise (in which case \a
|
||||||
|
* Error() must have been called.)
|
||||||
|
*/
|
||||||
virtual bool Dump(const Packet* pkt) = 0;
|
virtual bool Dump(const Packet* pkt) = 0;
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
friend class Manager;
|
friend class Manager;
|
||||||
|
|
||||||
// Methods to use by derived classed.
|
/**
|
||||||
//
|
* Structure to pass back information about the packet dumper to the
|
||||||
|
* base class. Derived class pass an instance of this to \a Opened().
|
||||||
|
*/
|
||||||
struct Properties {
|
struct Properties {
|
||||||
std::string path;
|
std::string path;
|
||||||
int hdr_size;
|
int hdr_size;
|
||||||
double open_time;
|
double open_time;
|
||||||
};
|
};
|
||||||
|
|
||||||
void Init();
|
/**
|
||||||
void Done();
|
* Called from the implementations of \a Open() to signal that the
|
||||||
|
* source has been successully opened.
|
||||||
|
*
|
||||||
|
* @param props A properties instance describing the now open source.
|
||||||
|
*/
|
||||||
void Opened(const Properties& props);
|
void Opened(const Properties& props);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Called from the implementations of \a Close() to signal that the
|
||||||
|
* source has been closed.
|
||||||
|
*/
|
||||||
void Closed();
|
void Closed();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Called from derived classes to signal an error.
|
||||||
|
*
|
||||||
|
* @param msg A corresponding error message.
|
||||||
|
*/
|
||||||
void Error(const std::string& msg);
|
void Error(const std::string& msg);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Called by the manager to initialize the dumper.
|
||||||
|
*/
|
||||||
|
void Init();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Called by the manager to shutdown the dumper.
|
||||||
|
*/
|
||||||
|
void Done();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
bool is_open;
|
bool is_open;
|
||||||
Properties props;
|
Properties props;
|
||||||
|
|
|
@ -53,6 +53,11 @@ uint32 PktSrc::Netmask() const
|
||||||
return IsOpen() ? props.netmask : PCAP_NETMASK_UNKNOWN;
|
return IsOpen() ? props.netmask : PCAP_NETMASK_UNKNOWN;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool PktSrc::IsError() const
|
||||||
|
{
|
||||||
|
return ErrorMsg();
|
||||||
|
}
|
||||||
|
|
||||||
int PktSrc::HdrSize() const
|
int PktSrc::HdrSize() const
|
||||||
{
|
{
|
||||||
return IsOpen() ? props.hdr_size : -1;
|
return IsOpen() ? props.hdr_size : -1;
|
||||||
|
@ -87,7 +92,7 @@ void PktSrc::Opened(const Properties& arg_props)
|
||||||
props = arg_props;
|
props = arg_props;
|
||||||
SetClosed(false);
|
SetClosed(false);
|
||||||
|
|
||||||
if ( ! PrecompileFilter(0, props.filter) || ! SetFilter(0) )
|
if ( ! PrecompileFilter(0, "") || ! SetFilter(0) )
|
||||||
{
|
{
|
||||||
Close();
|
Close();
|
||||||
return;
|
return;
|
||||||
|
@ -378,7 +383,7 @@ void PktSrc::Process()
|
||||||
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, current_packet.data, pkt_hdr_size, this);
|
||||||
|
|
||||||
have_packet = 0;
|
have_packet = 0;
|
||||||
DoneWithPacket(¤t_packet);
|
DoneWithPacket();
|
||||||
}
|
}
|
||||||
|
|
||||||
const char* PktSrc::Tag()
|
const char* PktSrc::Tag()
|
||||||
|
@ -386,7 +391,7 @@ const char* PktSrc::Tag()
|
||||||
return "PktSrc";
|
return "PktSrc";
|
||||||
}
|
}
|
||||||
|
|
||||||
int PktSrc::ExtractNextPacketInternal()
|
bool PktSrc::ExtractNextPacketInternal()
|
||||||
{
|
{
|
||||||
if ( have_packet )
|
if ( have_packet )
|
||||||
return true;
|
return true;
|
||||||
|
@ -426,7 +431,7 @@ int PktSrc::ExtractNextPacketInternal()
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
int PktSrc::PrecompileBPFFilter(int index, const std::string& filter)
|
bool PktSrc::PrecompileBPFFilter(int index, const std::string& filter)
|
||||||
{
|
{
|
||||||
char errbuf[PCAP_ERRBUF_SIZE];
|
char errbuf[PCAP_ERRBUF_SIZE];
|
||||||
|
|
||||||
|
@ -466,7 +471,7 @@ BPF_Program* PktSrc::GetBPFFilter(int index)
|
||||||
return code;
|
return code;
|
||||||
}
|
}
|
||||||
|
|
||||||
int PktSrc::ApplyBPFFilter(int index, const struct pcap_pkthdr *hdr, const u_char *pkt)
|
bool PktSrc::ApplyBPFFilter(int index, const struct pcap_pkthdr *hdr, const u_char *pkt)
|
||||||
{
|
{
|
||||||
BPF_Program* code = GetBPFFilter(index);
|
BPF_Program* code = GetBPFFilter(index);
|
||||||
|
|
||||||
|
@ -476,5 +481,18 @@ int PktSrc::ApplyBPFFilter(int index, const struct pcap_pkthdr *hdr, const u_cha
|
||||||
Close();
|
Close();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if ( code->MatchesAnything() )
|
||||||
|
return true;
|
||||||
|
|
||||||
return pcap_offline_filter(code->GetProgram(), hdr, pkt);
|
return pcap_offline_filter(code->GetProgram(), hdr, pkt);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool PktSrc::GetCurrentPacket(const pcap_pkthdr** hdr, const u_char** pkt)
|
||||||
|
{
|
||||||
|
if ( ! have_packet )
|
||||||
|
return false;
|
||||||
|
|
||||||
|
*hdr = current_packet.hdr;
|
||||||
|
*pkt = current_packet.data;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
|
@ -17,69 +17,206 @@ namespace iosource {
|
||||||
|
|
||||||
class PktSrc : public IOSource {
|
class PktSrc : public IOSource {
|
||||||
public:
|
public:
|
||||||
|
/**
|
||||||
|
* Struct for returning statistics on a packet source.
|
||||||
|
*/
|
||||||
struct Stats {
|
struct Stats {
|
||||||
unsigned int received; // pkts received (w/o drops)
|
/**
|
||||||
|
* Packets received by source after filtering (w/o drops).
|
||||||
|
*/
|
||||||
|
unsigned int received;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Packets dropped by source.
|
||||||
|
*/
|
||||||
unsigned int dropped; // pkts dropped
|
unsigned int dropped; // pkts dropped
|
||||||
unsigned int link; // total packets on link
|
|
||||||
// (not always not available)
|
/**
|
||||||
//
|
* Total number of packets on link before filtering.
|
||||||
|
* Optional, can be left unset if not available.
|
||||||
|
*/
|
||||||
|
unsigned int link;
|
||||||
|
|
||||||
Stats() { received = dropped = link = 0; }
|
Stats() { received = dropped = link = 0; }
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Constructor.
|
||||||
|
*/
|
||||||
PktSrc();
|
PktSrc();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Destructor.
|
||||||
|
*/
|
||||||
virtual ~PktSrc();
|
virtual ~PktSrc();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the path associated with the source. This is the interface
|
||||||
|
* name for live source, and a filename for offline sources.
|
||||||
|
*/
|
||||||
const std::string& Path() const;
|
const std::string& Path() const;
|
||||||
const std::string& Filter() const;
|
|
||||||
|
/**
|
||||||
|
* Returns true if this is a live source.
|
||||||
|
*/
|
||||||
bool IsLive() const;
|
bool IsLive() const;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the link type of the source.
|
||||||
|
*/
|
||||||
int LinkType() const;
|
int LinkType() const;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the netmask associated with the source, or \c
|
||||||
|
* PCAP_NETMASK_UNKNOWN if unknown.
|
||||||
|
*/
|
||||||
uint32 Netmask() const;
|
uint32 Netmask() const;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns true if the source has flagged an error.
|
||||||
|
*/
|
||||||
|
bool IsError() const;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* If the source encountered an error, returns a corresponding error
|
||||||
|
* message. Returns an empty string otherwise.
|
||||||
|
*/
|
||||||
const char* ErrorMsg() const;
|
const char* ErrorMsg() const;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the size of the link-layer header for this source.
|
||||||
|
*/
|
||||||
int HdrSize() const;
|
int HdrSize() const;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the snap length for this source.
|
||||||
|
*/
|
||||||
int SnapLen() const;
|
int SnapLen() const;
|
||||||
|
|
||||||
// Only valid in pseudo-realtime mode.
|
/**
|
||||||
|
* In pseudo-realtime mode, returns the logical timestamp of the
|
||||||
|
* current packet. Undefined if not running pseudo-realtime mode.
|
||||||
|
*/
|
||||||
double CurrentPacketTimestamp();
|
double CurrentPacketTimestamp();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* In pseudo-realtime mode, returns the wall clock time associated
|
||||||
|
* with current packet. Undefined if not running pseudo-realtime
|
||||||
|
* mode.
|
||||||
|
*/
|
||||||
double CurrentPacketWallClock();
|
double CurrentPacketWallClock();
|
||||||
|
|
||||||
// Signal packet source that processing was suspended and is now
|
/**
|
||||||
// going to be continued.
|
* Signals packet source that processing is going to be continued
|
||||||
|
* after previous suspension.
|
||||||
|
*/
|
||||||
void ContinueAfterSuspend();
|
void ContinueAfterSuspend();
|
||||||
|
|
||||||
// Precompiles a BPF filter and associates the given index with it.
|
/**
|
||||||
// Returns true on success, 0 if a problem occurred. The compiled
|
* Precompiles a BPF filter and associates the given index with it.
|
||||||
// filter will be then available via GetBPFFilter*(.
|
* The compiled filter will be then available via \a GetBPFFilter().
|
||||||
int PrecompileBPFFilter(int index, const std::string& filter);
|
*
|
||||||
|
* This is primarily a helper for packet source implementation that
|
||||||
|
* want to apply BPF filtering to their packets.
|
||||||
|
*
|
||||||
|
* @param index The index to associate with the filter.
|
||||||
|
*
|
||||||
|
* @param BPF filter The filter string to precompile.
|
||||||
|
*
|
||||||
|
* @return True on success, false if a problem occurred.
|
||||||
|
*/
|
||||||
|
bool PrecompileBPFFilter(int index, const std::string& filter);
|
||||||
|
|
||||||
// Returns the BPF filter with the given index, as compiled by
|
/**
|
||||||
// PrecompileBPFFilter(), or null if none has been (successfully)
|
* Returns the precompiled BPF filter associated with a given index,
|
||||||
// compiled.
|
* if any, as compiled by \a PrecompileBPFFilter().
|
||||||
|
*
|
||||||
|
* This is primarily a helper for packet source implementation that
|
||||||
|
* want to apply BPF filtering to their packets.
|
||||||
|
*
|
||||||
|
* @return The BPF filter associated, or null if none has been
|
||||||
|
* (successfully) compiled.
|
||||||
|
*/
|
||||||
BPF_Program* GetBPFFilter(int index);
|
BPF_Program* GetBPFFilter(int index);
|
||||||
|
|
||||||
// Applies a precompiled BPF filter to a packet, returning true if it
|
/**
|
||||||
// maches. This will close the source with an error message if no
|
* Applies a precompiled BPF filter to a packet. This will close the
|
||||||
// filter with that index has been compiled.
|
* source with an error message if no filter with that index has been
|
||||||
int ApplyBPFFilter(int index, const struct pcap_pkthdr *hdr, const u_char *pkt);
|
* compiled.
|
||||||
|
*
|
||||||
|
* This is primarily a helper for packet source implementation that
|
||||||
|
* want to apply BPF filtering to their packets.
|
||||||
|
*
|
||||||
|
* @param index The index of the filter to apply.
|
||||||
|
*
|
||||||
|
* @param hdr The header of the packet to filter.
|
||||||
|
*
|
||||||
|
* @param pkt The content of the packet to filter.
|
||||||
|
*
|
||||||
|
* @return True if it maches. */
|
||||||
|
bool ApplyBPFFilter(int index, const struct pcap_pkthdr *hdr, const u_char *pkt);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the packet currently being processed, if available.
|
||||||
|
*
|
||||||
|
* @param hdr A pointer to pass the header of the current packet back.
|
||||||
|
*
|
||||||
|
* @param pkt A pointer to pass the content of the current packet
|
||||||
|
* back.
|
||||||
|
*
|
||||||
|
* @return True if the current packet is available, or false if not.
|
||||||
|
*/
|
||||||
|
bool GetCurrentPacket(const pcap_pkthdr** hdr, const u_char** pkt);
|
||||||
|
|
||||||
// PacketSource interace for derived classes to override.
|
// PacketSource interace for derived classes to override.
|
||||||
|
|
||||||
// Returns the packet last processed; false if there is no
|
/**
|
||||||
// current packet available.
|
* Precompiles a filter and associates a given index with it. The
|
||||||
virtual bool GetCurrentPacket(const pcap_pkthdr** hdr, const u_char** pkt) = 0;
|
* filter syntax is defined by the packet source's implenentation.
|
||||||
|
*
|
||||||
|
* Derived classes must implement this to implement their filtering.
|
||||||
|
* If they want to use BPF but don't support it natively, they can
|
||||||
|
* call the corresponding helper method provided by \a PktSrc.
|
||||||
|
*
|
||||||
|
* @param index The index to associate with the filter
|
||||||
|
*
|
||||||
|
* @param filter The filter string to precompile.
|
||||||
|
*
|
||||||
|
* @return True on success, false if a problem occurred or filtering
|
||||||
|
* is not supported.
|
||||||
|
*/
|
||||||
|
virtual bool PrecompileFilter(int index, const std::string& filter) = 0;
|
||||||
|
|
||||||
// Precompiles a filter and associates the given index with it.
|
/**
|
||||||
// Returns true on success, 0 if a problem occurred or filtering is
|
* Activates a precompiled filter with the given index.
|
||||||
// not supported.
|
*
|
||||||
virtual int PrecompileFilter(int index, const std::string& filter) = 0;
|
* Derived classes must implement this to implement their filtering.
|
||||||
|
* If they want to use BPF but don't support it natively, they can
|
||||||
|
* call the corresponding helper method provided by \a PktSrc.
|
||||||
|
*
|
||||||
|
* @param index The index of the filter to activate.
|
||||||
|
*
|
||||||
|
* @return True on success, false if a problem occurred or the
|
||||||
|
* filtering is not supported.
|
||||||
|
*/
|
||||||
|
virtual bool SetFilter(int index) = 0;
|
||||||
|
|
||||||
// Activates the filter with the given index. Returns true on
|
/**
|
||||||
// success, 0 if a problem occurred or the filtering is not
|
* Returns current statistics about the source.
|
||||||
// supported.
|
*
|
||||||
virtual int SetFilter(int index) = 0;
|
* Derived classes must implement this method.
|
||||||
|
*
|
||||||
// Returns current statistics about the source.
|
* @param stats A statistics structure that the method fill out.
|
||||||
|
*/
|
||||||
virtual void Statistics(Stats* stats) = 0;
|
virtual void Statistics(Stats* stats) = 0;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Helper method to return the header size for a given link tyoe.
|
||||||
|
*
|
||||||
|
* @param link_type The link tyoe.
|
||||||
|
*
|
||||||
|
* @return The header size in bytes.
|
||||||
|
*/
|
||||||
static int GetLinkHeaderSize(int link_type);
|
static int GetLinkHeaderSize(int link_type);
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
|
@ -87,13 +224,45 @@ protected:
|
||||||
|
|
||||||
// Methods to use by derived classes.
|
// Methods to use by derived classes.
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Structure to pass back information about the packet source to the
|
||||||
|
* base class. Derived class pass an instance of this to \a Opened().
|
||||||
|
*/
|
||||||
struct Properties {
|
struct Properties {
|
||||||
|
/**
|
||||||
|
* The path associated with the source. This is the interface
|
||||||
|
* name for live source, and a filename for offline sources.
|
||||||
|
*/
|
||||||
std::string path;
|
std::string path;
|
||||||
std::string filter; // Maybe different than what's passed in if not (directly) supported.
|
|
||||||
|
/**
|
||||||
|
* A file descriptor suitable to use with \a select() for
|
||||||
|
* determining if there's input available from this source.
|
||||||
|
*/
|
||||||
int selectable_fd;
|
int selectable_fd;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The link type for packets from this source.
|
||||||
|
*/
|
||||||
int link_type;
|
int link_type;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The size of the link-layer header for packets from this
|
||||||
|
* source. \a GetLinkHeaderSize() may be used to derive this
|
||||||
|
* value.
|
||||||
|
*/
|
||||||
int hdr_size;
|
int hdr_size;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The netmask associated with the source, or \c
|
||||||
|
* PCAP_NETMASK_UNKNOWN if unknown.
|
||||||
|
*/
|
||||||
uint32 netmask;
|
uint32 netmask;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* True if the source is reading live inout, false for
|
||||||
|
* working offline.
|
||||||
|
*/
|
||||||
bool is_live;
|
bool is_live;
|
||||||
|
|
||||||
Properties()
|
Properties()
|
||||||
|
@ -102,34 +271,120 @@ protected:
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Structure describing a packet.
|
||||||
|
*/
|
||||||
struct Packet {
|
struct Packet {
|
||||||
|
/**
|
||||||
|
* Time associated with the packet.
|
||||||
|
*/
|
||||||
double ts;
|
double ts;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The pcap header associated with the packet.
|
||||||
|
*/
|
||||||
const struct ::pcap_pkthdr* hdr;
|
const struct ::pcap_pkthdr* hdr;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The full content of the packet.
|
||||||
|
*/
|
||||||
const u_char* data;
|
const u_char* data;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Called from the implementations of \a Open() to signal that the
|
||||||
|
* source has been successully opened.
|
||||||
|
*
|
||||||
|
* @param props A properties instance describing the now open source.
|
||||||
|
*/
|
||||||
void Opened(const Properties& props);
|
void Opened(const Properties& props);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Called from the implementations of \a Close() to signal that the
|
||||||
|
* source has been closed.
|
||||||
|
*/
|
||||||
void Closed();
|
void Closed();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Can be called from derived classes to send an informational
|
||||||
|
* message to the user.
|
||||||
|
*
|
||||||
|
* @param msg The message to pass on.
|
||||||
|
*/
|
||||||
void Info(const std::string& msg);
|
void Info(const std::string& msg);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Can be called from derived classes to flag send an error.
|
||||||
|
*
|
||||||
|
* @param msg The message going with the error.
|
||||||
|
*/
|
||||||
void Error(const std::string& msg);
|
void Error(const std::string& msg);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Can be called from derived classes to flah a "weird" situation.
|
||||||
|
*
|
||||||
|
* @param msg The message to pass on.
|
||||||
|
*
|
||||||
|
* @param pkt The packet associated with the weird, or null if none.
|
||||||
|
*/
|
||||||
void Weird(const std::string& msg, const Packet* pkt);
|
void Weird(const std::string& msg, const Packet* pkt);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Can be called from derived classes to flag an internal error,
|
||||||
|
* which will abort execution.
|
||||||
|
*
|
||||||
|
* @param msg The message to pass on.
|
||||||
|
*/
|
||||||
void InternalError(const std::string& msg);
|
void InternalError(const std::string& msg);
|
||||||
|
|
||||||
// PktSrc interface for derived classes to implement.
|
// PktSrc interface for derived classes to implement.
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Called by the manager system to open the source.
|
||||||
|
*
|
||||||
|
* Derived classes must implement this method. If successful, the
|
||||||
|
* implementation must call \a Opened(); if not, it must call Error()
|
||||||
|
* with a corresponding message.
|
||||||
|
*/
|
||||||
virtual void Open() = 0;
|
virtual void Open() = 0;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Called by the manager system to close the source.
|
||||||
|
*
|
||||||
|
* Derived classes must implement this method. If successful, the
|
||||||
|
* implementation must call \a Closed(); if not, it must call Error()
|
||||||
|
* with a corresponding message.
|
||||||
|
*/
|
||||||
virtual void Close() = 0;
|
virtual void Close() = 0;
|
||||||
// Returns 1 on success, 0 on time-out/gone dry.
|
|
||||||
virtual int ExtractNextPacket(Packet* pkt) = 0;
|
/**
|
||||||
virtual void DoneWithPacket(Packet* pkt) = 0;
|
* Provides the next packet from the source.
|
||||||
|
*
|
||||||
|
* @param pkt The packet structure to fill in with the packet's
|
||||||
|
* information. The callee keep ownership of the data but must
|
||||||
|
* guaranetee that it stays available at least until \a
|
||||||
|
* DoneWithPacket() is called. It is guaranteed that no two calls to
|
||||||
|
* this method will hapen with \a DoneWithPacket() in between.
|
||||||
|
*
|
||||||
|
* @return True if a packet is available and *pkt* filled in. False
|
||||||
|
* if not packet is available or an error occured (which must be
|
||||||
|
* flageed via Error()).
|
||||||
|
*/
|
||||||
|
virtual bool ExtractNextPacket(Packet* pkt) = 0;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Signals that the data of previously extracted packet will no
|
||||||
|
* longer be needed.
|
||||||
|
*/
|
||||||
|
virtual void DoneWithPacket() = 0;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
// Checks if the current packet has a pseudo-time <= current_time.
|
// Checks if the current packet has a pseudo-time <= current_time. If
|
||||||
// If yes, returns pseudo-time, otherwise 0.
|
// yes, returns pseudo-time, otherwise 0.
|
||||||
double CheckPseudoTime();
|
double CheckPseudoTime();
|
||||||
|
|
||||||
// XXX
|
// Internal helper for ExtractNextPacket().
|
||||||
int ExtractNextPacketInternal();
|
bool ExtractNextPacketInternal();
|
||||||
|
|
||||||
// IOSource interface implementation.
|
// IOSource interface implementation.
|
||||||
virtual void Init();
|
virtual void Init();
|
||||||
|
@ -159,5 +414,4 @@ private:
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -16,10 +16,9 @@ PcapSource::~PcapSource()
|
||||||
Close();
|
Close();
|
||||||
}
|
}
|
||||||
|
|
||||||
PcapSource::PcapSource(const std::string& path, const std::string& filter, bool is_live)
|
PcapSource::PcapSource(const std::string& path, bool is_live)
|
||||||
{
|
{
|
||||||
props.path = path;
|
props.path = path;
|
||||||
props.filter = filter;
|
|
||||||
props.is_live = is_live;
|
props.is_live = is_live;
|
||||||
last_data = 0;
|
last_data = 0;
|
||||||
}
|
}
|
||||||
|
@ -141,10 +140,10 @@ void PcapSource::OpenOffline()
|
||||||
Opened(props);
|
Opened(props);
|
||||||
}
|
}
|
||||||
|
|
||||||
int PcapSource::ExtractNextPacket(Packet* pkt)
|
bool PcapSource::ExtractNextPacket(Packet* pkt)
|
||||||
{
|
{
|
||||||
if ( ! pd )
|
if ( ! pd )
|
||||||
return 0;
|
return false;
|
||||||
|
|
||||||
const u_char* data = pcap_next(pd, ¤t_hdr);
|
const u_char* data = pcap_next(pd, ¤t_hdr);
|
||||||
|
|
||||||
|
@ -156,7 +155,7 @@ int PcapSource::ExtractNextPacket(Packet* pkt)
|
||||||
if ( ! props.is_live )
|
if ( ! props.is_live )
|
||||||
Close();
|
Close();
|
||||||
|
|
||||||
return 0;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
pkt->ts = current_hdr.ts.tv_sec + double(current_hdr.ts.tv_usec) / 1e6;
|
pkt->ts = current_hdr.ts.tv_sec + double(current_hdr.ts.tv_usec) / 1e6;
|
||||||
|
@ -166,29 +165,29 @@ int PcapSource::ExtractNextPacket(Packet* pkt)
|
||||||
if ( current_hdr.len == 0 || current_hdr.caplen == 0 )
|
if ( current_hdr.len == 0 || current_hdr.caplen == 0 )
|
||||||
{
|
{
|
||||||
Weird("empty_pcap_header", pkt);
|
Weird("empty_pcap_header", pkt);
|
||||||
return 0;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
last_hdr = current_hdr;
|
last_hdr = current_hdr;
|
||||||
last_data = data;
|
last_data = data;
|
||||||
++stats.received;
|
++stats.received;
|
||||||
return 1;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
void PcapSource::DoneWithPacket(Packet* pkt)
|
void PcapSource::DoneWithPacket()
|
||||||
{
|
{
|
||||||
// Nothing to do.
|
// Nothing to do.
|
||||||
}
|
}
|
||||||
|
|
||||||
int PcapSource::PrecompileFilter(int index, const std::string& filter)
|
bool PcapSource::PrecompileFilter(int index, const std::string& filter)
|
||||||
{
|
{
|
||||||
return PktSrc::PrecompileBPFFilter(index, filter);
|
return PktSrc::PrecompileBPFFilter(index, filter);
|
||||||
}
|
}
|
||||||
|
|
||||||
int PcapSource::SetFilter(int index)
|
bool PcapSource::SetFilter(int index)
|
||||||
{
|
{
|
||||||
if ( ! pd )
|
if ( ! pd )
|
||||||
return 1; // Prevent error message
|
return true; // Prevent error message
|
||||||
|
|
||||||
char errbuf[PCAP_ERRBUF_SIZE];
|
char errbuf[PCAP_ERRBUF_SIZE];
|
||||||
|
|
||||||
|
@ -200,13 +199,13 @@ int PcapSource::SetFilter(int index)
|
||||||
"No precompiled pcap filter for index %d",
|
"No precompiled pcap filter for index %d",
|
||||||
index);
|
index);
|
||||||
Error(errbuf);
|
Error(errbuf);
|
||||||
return 0;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
if ( pcap_setfilter(pd, code->GetProgram()) < 0 )
|
if ( pcap_setfilter(pd, code->GetProgram()) < 0 )
|
||||||
{
|
{
|
||||||
PcapError();
|
PcapError();
|
||||||
return 0;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifndef HAVE_LINUX
|
#ifndef HAVE_LINUX
|
||||||
|
@ -214,7 +213,7 @@ int PcapSource::SetFilter(int index)
|
||||||
stats.received = stats.dropped = stats.link = 0;
|
stats.received = stats.dropped = stats.link = 0;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
return 1;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
void PcapSource::Statistics(Stats* s)
|
void PcapSource::Statistics(Stats* s)
|
||||||
|
@ -246,16 +245,6 @@ void PcapSource::Statistics(Stats* s)
|
||||||
s->dropped = 0;
|
s->dropped = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool PcapSource::GetCurrentPacket(const pcap_pkthdr** hdr, const u_char** pkt)
|
|
||||||
{
|
|
||||||
if ( ! last_data )
|
|
||||||
return false;
|
|
||||||
|
|
||||||
*hdr = &last_hdr;
|
|
||||||
*pkt = last_data;
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
void PcapSource::PcapError()
|
void PcapSource::PcapError()
|
||||||
{
|
{
|
||||||
if ( pd )
|
if ( pd )
|
||||||
|
@ -285,7 +274,7 @@ void PcapSource::SetHdrSize()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
iosource::PktSrc* PcapSource::Instantiate(const std::string& path, const std::string& filter, bool is_live)
|
iosource::PktSrc* PcapSource::Instantiate(const std::string& path, bool is_live)
|
||||||
{
|
{
|
||||||
return new PcapSource(path, filter, is_live);
|
return new PcapSource(path, is_live);
|
||||||
}
|
}
|
||||||
|
|
|
@ -11,22 +11,21 @@ namespace pcap {
|
||||||
class PcapSource : public iosource::PktSrc {
|
class PcapSource : public iosource::PktSrc {
|
||||||
public:
|
public:
|
||||||
// XXX
|
// XXX
|
||||||
PcapSource(const std::string& path, const std::string& filter, bool is_live);
|
PcapSource(const std::string& path, bool is_live);
|
||||||
|
|
||||||
virtual ~PcapSource();
|
virtual ~PcapSource();
|
||||||
|
|
||||||
static PktSrc* Instantiate(const std::string& path, const std::string& filter, bool is_live);
|
static PktSrc* Instantiate(const std::string& path, bool is_live);
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
// PktSrc interface.
|
// PktSrc interface.
|
||||||
virtual void Open();
|
virtual void Open();
|
||||||
virtual void Close();
|
virtual void Close();
|
||||||
virtual int ExtractNextPacket(Packet* pkt);
|
virtual bool ExtractNextPacket(Packet* pkt);
|
||||||
virtual void DoneWithPacket(Packet* pkt);
|
virtual void DoneWithPacket();
|
||||||
virtual int PrecompileFilter(int index, const std::string& filter);
|
virtual bool PrecompileFilter(int index, const std::string& filter);
|
||||||
virtual int SetFilter(int index);
|
virtual bool SetFilter(int index);
|
||||||
virtual void Statistics(Stats* stats);
|
virtual void Statistics(Stats* stats);
|
||||||
virtual bool GetCurrentPacket(const pcap_pkthdr** hdr, const u_char** pkt);
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
void OpenLive();
|
void OpenLive();
|
||||||
|
|
|
@ -991,7 +991,7 @@ int main(int argc, char** argv)
|
||||||
snaplen = internal_val("snaplen")->AsCount();
|
snaplen = internal_val("snaplen")->AsCount();
|
||||||
|
|
||||||
if ( dns_type != DNS_PRIME )
|
if ( dns_type != DNS_PRIME )
|
||||||
net_init(interfaces, read_files, writefile, "", do_watchdog);
|
net_init(interfaces, read_files, writefile, do_watchdog);
|
||||||
|
|
||||||
BroFile::SetDefaultRotation(log_rotate_interval, log_max_size);
|
BroFile::SetDefaultRotation(log_rotate_interval, log_max_size);
|
||||||
|
|
||||||
|
|
|
@ -3,7 +3,7 @@
|
||||||
# @TEST-EXEC: echo ---- >>output
|
# @TEST-EXEC: echo ---- >>output
|
||||||
# @TEST-EXEC: bro -r $TRACES/workshop_2011_browse.trace %INPUT >>output 2>&1
|
# @TEST-EXEC: bro -r $TRACES/workshop_2011_browse.trace %INPUT >>output 2>&1
|
||||||
# @TEST-EXEC: test -e conn.log
|
# @TEST-EXEC: test -e conn.log
|
||||||
# @TEST-EXEC: btest-diff output
|
# @TEST-EXEC: TEST_DIFF_CANONIFIER=$SCRIPTS/diff-remove-abspath btest-diff output
|
||||||
|
|
||||||
redef enum PcapFilterID += { A };
|
redef enum PcapFilterID += { A };
|
||||||
|
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue