Removing netmap, remaining pieces of the 2ndary path, and left-over

files of packet sorter.

Netmap will move to a plugin.
This commit is contained in:
Robin Sommer 2014-08-22 16:13:33 -07:00
parent bf6dd2e9ca
commit 93e6a4a9db
20 changed files with 16 additions and 999 deletions

View file

@ -7,3 +7,4 @@
- PktDumper: Move Dump() to public and remove Record() - PktDumper: Move Dump() to public and remove Record()
- Wrap BPF_Program into namespace and clean up - Wrap BPF_Program into namespace and clean up
- Tests, in particular the packet dumping needs testing. - Tests, in particular the packet dumping needs testing.
- Add an interface for derived pkt source to run a BPF filter.

View file

@ -16,7 +16,7 @@ DebugLogger::Stream DebugLogger::streams[NUM_DBGS] = {
{ "compressor", 0, false }, {"string", 0, false }, { "compressor", 0, false }, {"string", 0, false },
{ "notifiers", 0, false }, { "main-loop", 0, false }, { "notifiers", 0, false }, { "main-loop", 0, false },
{ "dpd", 0, false }, { "tm", 0, false }, { "dpd", 0, false }, { "tm", 0, false },
{ "logging", 0, false }, {"input", 0, false }, { "logging", 0, false }, {"input", 0, false },
{ "threading", 0, false }, { "file_analysis", 0, false }, { "threading", 0, false }, { "file_analysis", 0, false },
{ "plugins", 0, false }, { "broxygen", 0, false }, { "plugins", 0, false }, { "broxygen", 0, false },
{ "pktio", 0, false} { "pktio", 0, false}

View file

@ -155,10 +155,10 @@ 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,
name_list& netflows, name_list& flowfiles, name_list& netflows, name_list& flowfiles,
const char* writefile, const char* filter, const char* writefile, const char* filter,
const char* secondary_filter, int do_watchdog) int do_watchdog)
{ {
if ( readfiles.length() > 0 || flowfiles.length() > 0 ) if ( readfiles.length() > 0 )
{ {
reading_live = pseudo_realtime > 0.0; reading_live = pseudo_realtime > 0.0;
reading_traces = 1; reading_traces = 1;
@ -202,6 +202,11 @@ void net_init(name_list& interfaces, name_list& readfiles,
if ( writefile ) if ( writefile )
{ {
pkt_dumper = iosource_mgr->OpenPktDumper(writefile, false); 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());
ID* id = global_scope()->Lookup("trace_output_file"); ID* id = global_scope()->Lookup("trace_output_file");
if ( ! id ) if ( ! id )

View file

@ -16,7 +16,7 @@
extern void net_init(name_list& interfaces, name_list& readfiles, extern void net_init(name_list& interfaces, name_list& readfiles,
name_list& netflows, name_list& flowfiles, name_list& netflows, name_list& flowfiles,
const char* writefile, const char* filter, const char* writefile, const char* filter,
const char* secondary_filter, 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);

View file

@ -1,364 +0,0 @@
#include "IP.h"
#include "PacketSort.h"
const bool DEBUG_packetsort = false;
PacketSortElement::PacketSortElement(iosource::PktSrc* arg_src,
double arg_timestamp, const struct pcap_pkthdr* arg_hdr,
const u_char* arg_pkt, int arg_hdr_size)
{
src = arg_src;
timestamp = arg_timestamp;
hdr = *arg_hdr;
hdr_size = arg_hdr_size;
pkt = new u_char[hdr.caplen];
memcpy(pkt, arg_pkt, hdr.caplen);
is_tcp = 0;
ip_hdr = 0;
tcp_flags = 0;
endp = 0;
payload_length = 0;
key = 0;
// Now check if it is a "parsable" TCP packet.
uint32 caplen = hdr.caplen;
uint32 tcp_offset;
if ( caplen >= sizeof(struct ip) + hdr_size )
{
const struct ip* ip = (const struct ip*) (pkt + hdr_size);
if ( ip->ip_v == 4 )
ip_hdr = new IP_Hdr(ip, false);
else if ( ip->ip_v == 6 && (caplen >= sizeof(struct ip6_hdr) + hdr_size) )
ip_hdr = new IP_Hdr((const struct ip6_hdr*) ip, false, caplen - hdr_size);
else
// Weird will be generated later in NetSessions::NextPacket.
return;
if ( ip_hdr->NextProto() == IPPROTO_TCP &&
// Note: can't sort fragmented packets
( ! ip_hdr->IsFragment() ) )
{
tcp_offset = hdr_size + ip_hdr->HdrLen();
if ( caplen >= tcp_offset + sizeof(struct tcphdr) )
{
const struct tcphdr* tp = (const struct tcphdr*)
(pkt + tcp_offset);
id.src_addr = ip_hdr->SrcAddr();
id.dst_addr = ip_hdr->DstAddr();
id.src_port = tp->th_sport;
id.dst_port = tp->th_dport;
id.is_one_way = 0;
endp = addr_port_canon_lt(id.src_addr,
id.src_port,
id.dst_addr,
id.dst_port) ? 0 : 1;
seq[endp] = ntohl(tp->th_seq);
if ( tp->th_flags & TH_ACK )
seq[1-endp] = ntohl(tp->th_ack);
else
seq[1-endp] = 0;
tcp_flags = tp->th_flags;
// DEBUG_MSG("%.6f: %u, %u\n", timestamp, seq[0], seq[1]);
payload_length = ip_hdr->PayloadLen() - tp->th_off * 4;
key = BuildConnIDHashKey(id);
is_tcp = 1;
}
}
}
if ( DEBUG_packetsort && ! is_tcp )
DEBUG_MSG("%.6f non-TCP packet\n", timestamp);
}
PacketSortElement::~PacketSortElement()
{
delete [] pkt;
delete ip_hdr;
delete key;
}
int PacketSortPQ::Timestamp_Cmp(PacketSortElement* a, PacketSortElement* b)
{
double d = a->timestamp - b->timestamp;
if ( d > 0 ) return 1;
else if ( d < 0 ) return -1;
else return 0;
}
int PacketSortPQ::UpdatePQ(PacketSortElement* prev_e, PacketSortElement* new_e)
{
int index = prev_e->pq_index[pq_level];
new_e->pq_index[pq_level] = index;
pq[index] = new_e;
if ( Cmp(prev_e, new_e) > 0 )
return FixUp(new_e, index);
else
{
FixDown(new_e, index);
return index == 0;
}
}
int PacketSortPQ::AddToPQ(PacketSortElement* new_e)
{
int index = pq.size();
new_e->pq_index[pq_level] = index;
pq.push_back(new_e);
return FixUp(new_e, index);
}
int PacketSortPQ::RemoveFromPQ(PacketSortElement* prev_e)
{
if ( pq.size() > 1 )
{
PacketSortElement* new_e = pq[pq.size() - 1];
pq.pop_back();
return UpdatePQ(prev_e, new_e);
}
else
{
pq.pop_back();
return 1;
}
}
void PacketSortPQ::Assign(int k, PacketSortElement* e)
{
pq[k] = e;
e->pq_index[pq_level] = k;
}
PacketSortConnPQ::~PacketSortConnPQ()
{
// Delete elements only in ConnPQ (not in GlobalPQ) to avoid
// double delete.
for ( int i = 0; i < (int) pq.size(); ++i )
{
delete pq[i];
pq[i] = 0;
}
}
int PacketSortConnPQ::Cmp(PacketSortElement* a, PacketSortElement* b)
{
// Note: here we do not distinguish between packets without
// an ACK and packets with seq/ack of 0. The later will sorted
// only by their timestamps.
if ( a->seq[0] && b->seq[0] && a->seq[0] != b->seq[0] )
return (a->seq[0] > b->seq[0]) ? 1 : -1;
else if ( a->seq[1] && b->seq[1] && a->seq[1] != b->seq[1] )
return (a->seq[1] > b->seq[1]) ? 1 : -1;
else
return Timestamp_Cmp(a, b);
}
int PacketSortPQ::FixUp(PacketSortElement* e, int k)
{
if ( k == 0 )
{
Assign(0, e);
return 1;
}
int parent = (k-1) / 2;
if ( Cmp(pq[parent], e) > 0 )
{
Assign(k, pq[parent]);
return FixUp(e, parent);
}
else
{
Assign(k, e);
return 0;
}
}
void PacketSortPQ::FixDown(PacketSortElement* e, int k)
{
uint32 kid = k * 2 + 1;
if ( kid >= pq.size() )
{
Assign(k, e);
return;
}
if ( kid + 1 < pq.size() && Cmp(pq[kid], pq[kid+1]) > 0 )
++kid;
if ( Cmp(e, pq[kid]) > 0 )
{
Assign(k, pq[kid]);
FixDown(e, kid);
}
else
Assign(k, e);
}
int PacketSortConnPQ::Add(PacketSortElement* e)
{
#if 0
int endp = e->endp;
uint32 end_seq = e->seq[endp] + e->payload_length;
int p = 1 - endp;
if ( (e->tcp_flags & TH_RST) && ! (e->tcp_flags & TH_ACK) )
{
DEBUG_MSG("%.6f %c: %u -> %u\n",
e->TimeStamp(), (p == endp) ? 'S' : 'A',
e->seq[p], next_seq[p]);
e->seq[p] = next_seq[p];
}
if ( end_seq > next_seq[endp] )
next_seq[endp] = end_seq;
#endif
return AddToPQ(e);
}
void PacketSortConnPQ::UpdateDeliveredSeq(int endp, int seq, int len, int ack)
{
if ( delivered_seq[endp] == 0 || delivered_seq[endp] == seq )
delivered_seq[endp] = seq + len;
if ( ack > delivered_seq[1 - endp] )
delivered_seq[endp] = ack;
}
bool PacketSortConnPQ::IsContentGapSafe(PacketSortElement* e)
{
int ack = e->seq[1 - e->endp];
return ack <= delivered_seq[1 - e->endp];
}
int PacketSortConnPQ::Remove(PacketSortElement* e)
{
int ret = RemoveFromPQ(e);
UpdateDeliveredSeq(e->endp, e->seq[e->endp], e->payload_length,
e->seq[1 - e->endp]);
return ret;
}
static void DeleteConnPQ(void* p)
{
delete (PacketSortConnPQ*) p;
}
PacketSortGlobalPQ::PacketSortGlobalPQ()
{
pq_level = GLOBAL_PQ;
conn_pq_table.SetDeleteFunc(DeleteConnPQ);
}
PacketSortGlobalPQ::~PacketSortGlobalPQ()
{
// Destruction of PacketSortConnPQ will delete all conn_pq's.
}
int PacketSortGlobalPQ::Add(PacketSortElement* e)
{
if ( e->is_tcp )
{
// TCP packets are sorted by sequence numbers
PacketSortConnPQ* conn_pq = FindConnPQ(e);
PacketSortElement* prev_min = conn_pq->Min();
if ( conn_pq->Add(e) )
{
ASSERT(conn_pq->Min() != prev_min);
if ( prev_min )
return UpdatePQ(prev_min, e);
else
return AddToPQ(e);
}
else
{
ASSERT(conn_pq->Min() == prev_min);
return 0;
}
}
else
return AddToPQ(e);
}
PacketSortElement* PacketSortGlobalPQ::RemoveMin(double timestamp)
{
PacketSortElement* e = Min();
if ( ! e )
return 0;
if ( e->is_tcp )
{
PacketSortConnPQ* conn_pq = FindConnPQ(e);
#if 0
// Note: the content gap safety check does not work
// because we remove the state for a connection once
// it has no packet in the priority queue.
// Do not deliver e if it arrives later than timestamp,
// and is not content-gap-safe.
if ( e->timestamp > timestamp &&
! conn_pq->IsContentGapSafe(e) )
return 0;
#else
if ( e->timestamp > timestamp )
return 0;
#endif
conn_pq->Remove(e);
PacketSortElement* new_e = conn_pq->Min();
if ( new_e )
UpdatePQ(e, new_e);
else
{
RemoveFromPQ(e);
conn_pq_table.Remove(e->key);
delete conn_pq;
}
}
else
RemoveFromPQ(e);
return e;
}
PacketSortConnPQ* PacketSortGlobalPQ::FindConnPQ(PacketSortElement* e)
{
if ( ! e->is_tcp )
reporter->InternalError("cannot find a connection for an invalid id");
PacketSortConnPQ* pq = (PacketSortConnPQ*) conn_pq_table.Lookup(e->key);
if ( ! pq )
{
pq = new PacketSortConnPQ();
conn_pq_table.Insert(e->key, pq);
}
return pq;
}

View file

@ -1,130 +0,0 @@
#ifndef packetsort_h
#define packetsort_h
// Timestamps can be imprecise and even inconsistent among packets
// from different sources. This class tries to guess a "correct"
// order by looking at TCP sequence numbers.
//
// In particular, it tries to eliminate "false" content gaps.
#include "Dict.h"
#include "Conn.h"
enum {
CONN_PQ,
GLOBAL_PQ,
NUM_OF_PQ_LEVEL,
};
class PacketSortElement {
public:
PacketSortElement(iosource::PktSrc* src, double timestamp,
const struct pcap_pkthdr* hdr,
const u_char* pkt, int hdr_size);
~PacketSortElement();
iosource::PktSrc* Src() const { return src; }
double TimeStamp() const { return timestamp; }
const struct pcap_pkthdr* Hdr() const { return &hdr; }
const u_char* Pkt() const { return pkt; }
int HdrSize() const { return hdr_size; }
const IP_Hdr* IPHdr() const { return ip_hdr; }
protected:
iosource::PktSrc* src;
double timestamp;
struct pcap_pkthdr hdr;
u_char* pkt;
int hdr_size;
IP_Hdr* ip_hdr;
int is_tcp;
ConnID id;
uint32 seq[2]; // indexed by endpoint
int tcp_flags;
int endp; // 0 or 1
int payload_length;
HashKey* key;
int pq_index[NUM_OF_PQ_LEVEL];
friend class PacketSortPQ;
friend class PacketSortConnPQ;
friend class PacketSortGlobalPQ;
};
class PacketSortPQ {
public:
PacketSortPQ()
{ pq_level = -1; }
virtual ~PacketSortPQ() {}
PacketSortElement* Min() const { return (pq.size() > 0) ? pq[0] : 0; }
protected:
virtual int Cmp(PacketSortElement* a, PacketSortElement* b) = 0;
int Timestamp_Cmp(PacketSortElement* a, PacketSortElement* b);
int UpdatePQ(PacketSortElement* prev_e, PacketSortElement* new_e);
int AddToPQ(PacketSortElement* e);
int RemoveFromPQ(PacketSortElement* e);
void Assign(int k, PacketSortElement* e);
int FixUp(PacketSortElement* e, int k);
void FixDown(PacketSortElement* e, int k);
vector<PacketSortElement*> pq;
int pq_level;
};
// Sort by sequence numbers within a connection
class PacketSortConnPQ : public PacketSortPQ {
public:
PacketSortConnPQ()
{
pq_level = CONN_PQ;
delivered_seq[0] = delivered_seq[1] = 0;
}
~PacketSortConnPQ();
int Add(PacketSortElement* e);
int Remove(PacketSortElement* e);
bool IsContentGapSafe(PacketSortElement* e);
protected:
int Cmp(PacketSortElement* a, PacketSortElement* b);
void UpdateDeliveredSeq(int endp, int seq, int len, int ack);
int delivered_seq[2];
};
declare(PDict, PacketSortConnPQ);
// Sort by timestamps.
class PacketSortGlobalPQ : public PacketSortPQ {
public:
PacketSortGlobalPQ();
~PacketSortGlobalPQ();
int Add(PacketSortElement* e);
int Empty() const { return conn_pq_table.Length() == 0; }
// Returns the next packet to dispatch if it arrives earlier than the
// given timestamp, otherwise returns 0.
// The packet, if to be returned, is also removed from the
// priority queue.
PacketSortElement* RemoveMin(double timestamp);
protected:
int Cmp(PacketSortElement* a, PacketSortElement* b)
{ return Timestamp_Cmp(a, b); }
PacketSortConnPQ* FindConnPQ(PacketSortElement* e);
PDict(PacketSortConnPQ) conn_pq_table;
};
#endif

View file

@ -364,10 +364,6 @@ int PktSrc::PrecompileFilter(int index, const char* filter)
int PktSrc::SetFilter(int index) int PktSrc::SetFilter(int index)
{ {
// We don't want load-level filters for the secondary path.
if ( filter_type == TYPE_FILTER_SECONDARY && index > 0 )
return 1;
HashKey* hash = new HashKey(HashKey(bro_int_t(index))); HashKey* hash = new HashKey(HashKey(bro_int_t(index)));
BPF_Program* code = filters.Lookup(hash); BPF_Program* code = filters.Lookup(hash);
delete hash; delete hash;
@ -421,28 +417,6 @@ void PktSrc::Close()
} }
} }
void PktSrc::AddSecondaryTablePrograms()
{
BPF_Program* program;
loop_over_list(secondary_path->EventTable(), i)
{
SecondaryEvent* se = secondary_path->EventTable()[i];
program = new BPF_Program();
if ( ! program->Compile(snaplen, datalink, se->Filter(),
netmask, errbuf, sizeof(errbuf)) )
{
delete program;
Close();
return;
}
SecondaryProgram* sp = new SecondaryProgram(program, se);
program_list.append(sp);
}
}
void PktSrc::Statistics(Stats* s) void PktSrc::Statistics(Stats* s)
{ {
if ( reading_traces ) if ( reading_traces )
@ -581,75 +555,6 @@ PktFileSrc::PktFileSrc(const char* arg_readfile, const char* filter,
closed = true; closed = true;
} }
SecondaryPath::SecondaryPath()
{
filter = 0;
// Glue together the secondary filter, if exists.
Val* secondary_fv = internal_val("secondary_filters");
if ( secondary_fv->AsTableVal()->Size() == 0 )
return;
int did_first = 0;
const TableEntryValPDict* v = secondary_fv->AsTable();
IterCookie* c = v->InitForIteration();
TableEntryVal* tv;
HashKey* h;
while ( (tv = v->NextEntry(h, c)) )
{
// Get the index values.
ListVal* index =
secondary_fv->AsTableVal()->RecoverIndex(h);
const char* str =
index->Index(0)->Ref()->AsString()->CheckString();
if ( ++did_first == 1 )
{
filter = copy_string(str);
}
else
{
if ( strlen(filter) > 0 )
{
char* tmp_f = new char[strlen(str) + strlen(filter) + 32];
if ( strlen(str) == 0 )
sprintf(tmp_f, "%s", filter);
else
sprintf(tmp_f, "(%s) or (%s)", filter, str);
delete [] filter;
filter = tmp_f;
}
}
// Build secondary_path event table item and link it.
SecondaryEvent* se =
new SecondaryEvent(index->Index(0)->Ref()->AsString()->CheckString(),
tv->Value()->AsFunc() );
event_list.append(se);
delete h;
Unref(index);
}
}
SecondaryPath::~SecondaryPath()
{
loop_over_list(event_list, i)
delete event_list[i];
delete [] filter;
}
SecondaryProgram::~SecondaryProgram()
{
delete program;
}
PktDumper::PktDumper(const char* arg_filename, bool arg_append) PktDumper::PktDumper(const char* arg_filename, bool arg_append)
{ {
filename[0] = '\0'; filename[0] = '\0';

View file

@ -259,55 +259,6 @@ void NetSessions::NextPacket(double t, const struct pcap_pkthdr* hdr,
DumpPacket(hdr, pkt); DumpPacket(hdr, pkt);
} }
void NetSessions::NextPacketSecondary(double /* t */, const struct pcap_pkthdr* hdr,
const u_char* const pkt, int hdr_size,
const iosource::PktSrc* src_ps)
{
SegmentProfiler(segment_logger, "processing-secondary-packet");
++num_packets_processed;
uint32 caplen = hdr->caplen - hdr_size;
if ( caplen < sizeof(struct ip) )
{
Weird("truncated_IP", hdr, pkt);
return;
}
#if 0
const struct ip* ip = (const struct ip*) (pkt + hdr_size);
if ( ip->ip_v == 4 )
{
const secondary_program_list& spt = src_ps->ProgramTable();
loop_over_list(spt, i)
{
SecondaryProgram* sp = spt[i];
if ( ! net_packet_match(sp->Program(), pkt,
hdr->len, hdr->caplen) )
continue;
val_list* args = new val_list;
StringVal* cmd_val =
new StringVal(sp->Event()->Filter());
args->append(cmd_val);
IP_Hdr ip_hdr(ip, false);
args->append(ip_hdr.BuildPktHdrVal());
// ### Need to queue event here.
try
{
sp->Event()->Event()->Call(args);
}
catch ( InterpreterException& e )
{ /* Already reported. */ }
delete args;
}
}
#endif
}
int NetSessions::CheckConnectionTag(Connection* conn) int NetSessions::CheckConnectionTag(Connection* conn)
{ {
if ( current_iosrc->GetCurrentTag() ) if ( current_iosrc->GetCurrentTag() )

View file

@ -69,8 +69,8 @@ public:
~NetSessions(); ~NetSessions();
// Main entry point for packet processing. Dispatches the packet // Main entry point for packet processing. Dispatches the packet
// either through NextPacket() or NextPacketSecondary(), optionally // either through NextPacket(), optionally employing the packet
// employing the packet sorter first. // sorter first.
void DispatchPacket(double t, const struct pcap_pkthdr* hdr, void DispatchPacket(double t, const struct pcap_pkthdr* hdr,
const u_char* const pkt, int hdr_size, const u_char* const pkt, int hdr_size,
iosource::PktSrc* src_ps); iosource::PktSrc* src_ps);
@ -221,10 +221,6 @@ protected:
void NextPacket(double t, const struct pcap_pkthdr* hdr, void NextPacket(double t, const struct pcap_pkthdr* hdr,
const u_char* const pkt, int hdr_size); const u_char* const pkt, int hdr_size);
void NextPacketSecondary(double t, const struct pcap_pkthdr* hdr,
const u_char* const pkt, int hdr_size,
const iosource::PktSrc* src_ps);
// Record the given packet (if a dumper is active). If len=0 // Record the given packet (if a dumper is active). If len=0
// then the whole packet is recorded, otherwise just the first // then the whole packet is recorded, otherwise just the first
// len bytes. // len bytes.

View file

@ -1,3 +1,2 @@
add_subdirectory(pcap) add_subdirectory(pcap)
add_subdirectory(netmap)

View file

@ -59,14 +59,6 @@ public:
static int GetLinkHeaderSize(int link_type); static int GetLinkHeaderSize(int link_type);
#if 0
PktSrc_Filter_Type FilterType() const { return filter_type; }
void AddSecondaryTablePrograms();
const secondary_program_list& ProgramTable() const
{ return program_list; }
#endif
protected: protected:
// Methods to use by derived classes. // Methods to use by derived classes.
@ -129,11 +121,6 @@ private:
double next_sync_point; // For trace synchronziation in pseudo-realtime double next_sync_point; // For trace synchronziation in pseudo-realtime
std::string errbuf; std::string errbuf;
#if 0
PktSrc_Filter_Type filter_type; // normal path or secondary path
secondary_program_list program_list;
#endif
}; };
} }

View file

@ -1,12 +0,0 @@
set(CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} ${CMAKE_CURRENT_SOURCE_DIR})
find_package(Netmap)
if ( NETMAP_FOUND )
include(BroPlugin)
include_directories(BEFORE ${CMAKE_CURRENT_SOURCE_DIR} ${CMAKE_CURRENT_BINARY_DIR} ${NETMAP_INCLUDE_DIR}/sys)
bro_plugin_begin(Bro Netmap)
bro_plugin_cc(Source.cc Plugin.cc)
bro_plugin_end()
endif ()

View file

@ -1,33 +0,0 @@
# - Try to find netmap includes.
#
#
# Variables used by this module, they can change the default behaviour and need
# to be set before calling find_package:
#
# NETMAP_ROOT_DIR Set this variable to the root installation of
# netmap if the module has problems finding the
# proper installation path.
#
# Variables defined by this module:
#
# NETMAP_FOUND System has netmap API files.
# NETMAP_INCLUDE_DIR The netmap include directory.
find_path(NETMAP_ROOT_DIR
NAMES sys/net/netmap_user.h
)
find_path(NETMAP_INCLUDE_DIR
NAMES sys/net/netmap_user.h
HINTS ${NETMAP_ROOT_DIR}
)
include(FindPackageHandleStandardArgs)
find_package_handle_standard_args(Netmap DEFAULT_MSG
NETMAP_INCLUDE_DIR
)
mark_as_advanced(
NETMAP_ROOT_DIR
NETMAP_INCLUDE_DIR
)

View file

@ -1,26 +0,0 @@
// See the file in the main distribution directory for copyright.
#include "plugin/Plugin.h"
#include "Source.h"
namespace plugin {
namespace Bro_Netmap {
class Plugin : public plugin::Plugin {
public:
plugin::Configuration Configure()
{
AddComponent(new ::iosource::pktsrc::SourceComponent("NetmapReader", "netmap", ::iosource::pktsrc::SourceComponent::LIVE, ::iosource::pktsrc::NetmapSource::InstantiateNetmap));
AddComponent(new ::iosource::pktsrc::SourceComponent("NetmapReader", "vale", ::iosource::pktsrc::SourceComponent::LIVE, ::iosource::pktsrc::NetmapSource::InstantiateVale));
plugin::Configuration config;
config.name = "Bro::Netmap";
config.description = "Packet aquisition via netmap";
return config;
}
} plugin;
}
}

View file

@ -1,127 +0,0 @@
#include <assert.h>
#include "config.h"
#include "Source.h"
using namespace iosource::pktsrc;
NetmapSource::~NetmapSource()
{
Close();
}
NetmapSource::NetmapSource(const std::string& path, const std::string& filter, bool is_live, const std::string& arg_kind)
{
if ( ! is_live )
Error("netmap source does not support offline input");
kind = arg_kind;
props.path = path;
props.filter = filter;
last_data = 0;
}
void NetmapSource::Close()
{
if ( ! nd )
return;
nm_close(nd);
nd = 0;
last_data = 0;
Closed();
}
void NetmapSource::Open()
{
std::string iface = kind + ":" + props.path;
nd = nm_open(iface.c_str(), getenv("NETMAP_RING_ID"), 0, 0);
if ( ! nd )
{
Error(errno ? strerror(errno) : "invalid interface");
return;
}
props.selectable_fd = NETMAP_FD(nd);
props.is_live = true;
props.link_type = DLT_EN10MB;
props.hdr_size = GetLinkHeaderSize(props.link_type);
assert(props.hdr_size >= 0);
Info(fmt("netmap listening on %s\n", props.path.c_str()));
Opened(props);
}
int NetmapSource::ExtractNextPacket(Packet* pkt)
{
nm_hdr_t hdr;
const u_char* data = nm_nextpkt(nd, &hdr);
if ( ! data )
// Source has gone dry.
return 0;
current_hdr.ts = hdr.ts;
current_hdr.caplen = hdr.caplen;
current_hdr.len = hdr.len;
pkt->ts = current_hdr.ts.tv_sec + double(current_hdr.ts.tv_usec) / 1e6;
pkt->hdr = &current_hdr;
pkt->data = last_data = data;
if ( current_hdr.len == 0 || current_hdr.caplen == 0 )
{
Weird("empty_netmap_header", pkt);
return 0;
}
last_hdr = current_hdr;
last_data = data;
++stats.received;
return 1;
}
void NetmapSource::DoneWithPacket(Packet* pkt)
{
// Nothing to do.
}
void NetmapSource::Statistics(Stats* s)
{
if ( ! nd )
{
s->received = s->link = s->dropped = 0;
return;
}
s->received = stats.received;
// TODO: Seems these counter's aren't actually set?
s->link = nd->st.ps_recv;
s->dropped = nd->st.ps_drop + nd->st.ps_ifdrop;
}
bool NetmapSource::GetCurrentPacket(const pcap_pkthdr** hdr, const u_char** pkt)
{
if ( ! last_data )
return false;
*hdr = &last_hdr;
*pkt = last_data;
return true;
}
iosource::PktSrc* NetmapSource::InstantiateNetmap(const std::string& path, const std::string& filter, bool is_live)
{
return new NetmapSource(path, filter, is_live, "netmap");
}
iosource::PktSrc* NetmapSource::InstantiateVale(const std::string& path, const std::string& filter, bool is_live)
{
return new NetmapSource(path, filter, is_live, "value");
}

View file

@ -1,48 +0,0 @@
// See the file "COPYING" in the main distribution directory for copyright.
#ifndef IOSOURCE_PKTSRC_NETMAP_SOURCE_H
#define IOSOURCE_PKTSRC_NETMAP_SOURCE_H
extern "C" {
#define NETMAP_WITH_LIBS
#include <net/netmap_user.h>
}
#include "../PktSrc.h"
namespace iosource {
namespace pktsrc {
class NetmapSource : public iosource::PktSrc {
public:
// XXX
NetmapSource(const std::string& path, const std::string& filter, bool is_live, const std::string& kind);
virtual ~NetmapSource();
static PktSrc* InstantiateNetmap(const std::string& path, const std::string& filter, bool is_live);
static PktSrc* InstantiateVale(const std::string& path, const std::string& filter, bool is_live);
protected:
// PktSrc interface.
virtual void Open();
virtual void Close();
virtual int ExtractNextPacket(Packet* pkt);
virtual void DoneWithPacket(Packet* pkt);
virtual void Statistics(Stats* stats);
virtual bool GetCurrentPacket(const pcap_pkthdr** hdr, const u_char** pkt);
private:
std::string kind;
Properties props;
Stats stats;
nm_desc_t *nd;
pcap_pkthdr current_hdr;
pcap_pkthdr last_hdr;
const u_char* last_data;
};
}
}
#endif

View file

@ -1,69 +0,0 @@
// Whether a PktSrc object is used by the normal filter structure or the
// secondary-path structure.
typedef enum {
TYPE_FILTER_NORMAL, // the normal filter
TYPE_FILTER_SECONDARY, // the secondary-path filter
} PktSrc_Filter_Type;
// {filter,event} tuples conforming the secondary path.
class SecondaryEvent {
public:
SecondaryEvent(const char* arg_filter, Func* arg_event)
{
filter = arg_filter;
event = arg_event;
}
const char* Filter() { return filter; }
Func* Event() { return event; }
private:
const char* filter;
Func* event;
};
declare(PList,SecondaryEvent);
typedef PList(SecondaryEvent) secondary_event_list;
class SecondaryPath {
public:
SecondaryPath();
~SecondaryPath();
secondary_event_list& EventTable() { return event_list; }
const char* Filter() { return filter; }
private:
secondary_event_list event_list;
// OR'ed union of all SecondaryEvent filters
char* filter;
};
// Main secondary-path object.
extern SecondaryPath* secondary_path;
// {program, {filter,event}} tuple table.
class SecondaryProgram {
public:
SecondaryProgram(BPF_Program* arg_program, SecondaryEvent* arg_event)
{
program = arg_program;
event = arg_event;
}
~SecondaryProgram();
BPF_Program* Program() { return program; }
SecondaryEvent* Event() { return event; }
private:
// Associated program.
BPF_Program *program;
// Event that is run in case the program is matched.
SecondaryEvent* event;
};
declare(PList,SecondaryProgram);
typedef PList(SecondaryProgram) secondary_program_list;

View file

@ -245,12 +245,6 @@ int PcapSource::SetFilter(int index)
char errbuf[PCAP_ERRBUF_SIZE]; char errbuf[PCAP_ERRBUF_SIZE];
#if 0
// We don't want load-level filters for the secondary path.
if ( filter_type == TYPE_FILTER_SECONDARY && index > 0 )
return 1;
#endif
HashKey* hash = new HashKey(HashKey(bro_int_t(index))); HashKey* hash = new HashKey(HashKey(bro_int_t(index)));
BPF_Program* code = filters.Lookup(hash); BPF_Program* code = filters.Lookup(hash);
delete hash; delete hash;

View file

@ -111,9 +111,6 @@ int optimize = 0;
int do_notice_analysis = 0; int do_notice_analysis = 0;
int rule_bench = 0; int rule_bench = 0;
int generate_documentation = 0; int generate_documentation = 0;
#if 0
SecondaryPath* secondary_path = 0;
#endif
extern char version[]; extern char version[];
char* command_line_policy = 0; char* command_line_policy = 0;
vector<string> params; vector<string> params;
@ -386,9 +383,6 @@ void terminate_bro()
delete event_serializer; delete event_serializer;
delete state_serializer; delete state_serializer;
delete event_registry; delete event_registry;
#if 0
delete secondary_path;
#endif
delete remote_serializer; delete remote_serializer;
delete analyzer_mgr; delete analyzer_mgr;
delete file_mgr; delete file_mgr;
@ -1007,15 +1001,9 @@ int main(int argc, char** argv)
snaplen = internal_val("snaplen")->AsCount(); snaplen = internal_val("snaplen")->AsCount();
#if 0
// Initialize the secondary path, if it's needed.
secondary_path = new SecondaryPath();
#endif
if ( dns_type != DNS_PRIME ) if ( dns_type != DNS_PRIME )
net_init(interfaces, read_files, netflows, flow_files, net_init(interfaces, read_files, netflows, flow_files,
writefile, "", writefile, "", do_watchdog);
"", do_watchdog);
BroFile::SetDefaultRotation(log_rotate_interval, log_max_size); BroFile::SetDefaultRotation(log_rotate_interval, log_max_size);

View file

@ -12,7 +12,7 @@ namespace plugin {
namespace component { namespace component {
/** /**
* Component types. * Component types.
*/ */
enum Type { enum Type {
READER, /// An input reader (not currently used). READER, /// An input reader (not currently used).
@ -28,7 +28,7 @@ enum Type {
/** /**
* Base class for plugin components. A component is a specific piece of * Base class for plugin components. A component is a specific piece of
* functionality that a plugin provides, such as a protocol analyzer or a log * functionality that a plugin provides, such as a protocol analyzer or a log
* writer. * writer.
*/ */
class Component class Component
{ {