mirror of
https://github.com/zeek/zeek.git
synced 2025-10-02 14:48:21 +00:00
Bugfixes and test updates.
This commit is contained in:
parent
c1c4e6eb63
commit
4a66a8e341
19 changed files with 212 additions and 771 deletions
|
@ -1,4 +0,0 @@
|
|||
- Tests
|
||||
- pktsrc plugin
|
||||
- pktdump plugin
|
||||
|
|
@ -405,7 +405,7 @@ DNS_Mgr::~DNS_Mgr()
|
|||
delete [] dir;
|
||||
}
|
||||
|
||||
void DNS_Mgr::Init()
|
||||
void DNS_Mgr::InitPostScript()
|
||||
{
|
||||
if ( did_init )
|
||||
return;
|
||||
|
|
|
@ -45,7 +45,7 @@ public:
|
|||
DNS_Mgr(DNS_MgrMode mode);
|
||||
virtual ~DNS_Mgr();
|
||||
|
||||
void Init();
|
||||
void InitPostScript();
|
||||
void Flush();
|
||||
|
||||
// Looks up the address or addresses of the given host, and returns
|
||||
|
|
709
src/PktSrc.cc
709
src/PktSrc.cc
|
@ -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;
|
||||
}
|
|
@ -558,7 +558,7 @@ RemoteSerializer::~RemoteSerializer()
|
|||
delete io;
|
||||
}
|
||||
|
||||
void RemoteSerializer::Init()
|
||||
void RemoteSerializer::Enable()
|
||||
{
|
||||
if ( initialized )
|
||||
return;
|
||||
|
|
|
@ -28,7 +28,7 @@ public:
|
|||
virtual ~RemoteSerializer();
|
||||
|
||||
// Initialize the remote serializer (calling this will fork).
|
||||
void Init();
|
||||
void Enable();
|
||||
|
||||
// FIXME: Use SourceID directly (or rename everything to Peer*).
|
||||
typedef SourceID PeerID;
|
||||
|
|
|
@ -4459,7 +4459,7 @@ function enable_communication%(%): any
|
|||
return 0;
|
||||
|
||||
using_communication = 1;
|
||||
remote_serializer->Init();
|
||||
remote_serializer->Enable();
|
||||
return 0;
|
||||
%}
|
||||
|
||||
|
|
|
@ -1,3 +1,4 @@
|
|||
// See the file "COPYING" in the main distribution directory for copyright.
|
||||
|
||||
#include "Component.h"
|
||||
|
||||
|
|
|
@ -22,7 +22,10 @@ public:
|
|||
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);
|
||||
|
||||
|
@ -38,7 +41,12 @@ public:
|
|||
|
||||
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);
|
||||
};
|
||||
|
@ -48,12 +56,29 @@ protected:
|
|||
*/
|
||||
class PktSrcComponent : public iosource::Component {
|
||||
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);
|
||||
|
||||
/**
|
||||
* 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);
|
||||
|
||||
|
|
|
@ -14,56 +14,120 @@ extern "C" {
|
|||
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 {
|
||||
public:
|
||||
/**
|
||||
* Constructor.
|
||||
*/
|
||||
IOSource() { idle = false; closed = false; }
|
||||
|
||||
/**
|
||||
* Destructor.
|
||||
*/
|
||||
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; }
|
||||
|
||||
// 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; }
|
||||
|
||||
// XXX
|
||||
/**
|
||||
* Initializes the source. Can be overwritten by derived classes.
|
||||
*/
|
||||
virtual void Init() { }
|
||||
|
||||
// XXX
|
||||
/**
|
||||
* Finalizes the source when it's being closed. Can be overwritten by
|
||||
* derived classes.
|
||||
*/
|
||||
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;
|
||||
|
||||
// The following two methods are only called when either IsIdle()
|
||||
// returns false or select() on one of the fds indicates that there's
|
||||
// data to process.
|
||||
|
||||
// Returns timestamp (in global network time) associated with next
|
||||
// data item. If the source wants the data item to be processed
|
||||
// with a local network time, it sets the argument accordingly.
|
||||
/**
|
||||
* Returns the timestamp (in \a global network time) associated with
|
||||
* next data item from this source. 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;
|
||||
|
||||
// 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;
|
||||
|
||||
// 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; }
|
||||
|
||||
// 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;
|
||||
|
||||
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; }
|
||||
|
||||
// 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; }
|
||||
|
||||
private:
|
||||
|
|
|
@ -1,3 +1,4 @@
|
|||
// See the file "COPYING" in the main distribution directory for copyright.
|
||||
|
||||
#include <sys/types.h>
|
||||
#include <sys/time.h>
|
||||
|
@ -22,7 +23,7 @@ Manager::~Manager()
|
|||
{
|
||||
for ( SourceList::iterator i = sources.begin(); i != sources.end(); ++i )
|
||||
{
|
||||
// ??? (*i)->src->Done();
|
||||
(*i)->src->Done();
|
||||
delete *i;
|
||||
}
|
||||
|
||||
|
|
|
@ -12,43 +12,100 @@ class IOSource;
|
|||
class PktSrc;
|
||||
class PktDumper;
|
||||
|
||||
/**
|
||||
* Singleton class managing all IOSources.
|
||||
*/
|
||||
class Manager {
|
||||
public:
|
||||
/**
|
||||
* Constructor.
|
||||
*/
|
||||
Manager() { call_count = 0; dont_counts = 0; }
|
||||
|
||||
/**
|
||||
* Destructor.
|
||||
*/
|
||||
~Manager();
|
||||
|
||||
// If dont_count is true, this source does not contribute to the
|
||||
// number of IOSources returned by Size(). The effect is that
|
||||
// if all sources but the non-counting ones have gone dry,
|
||||
// processing will shut down.
|
||||
/**
|
||||
* Registers an IOSource with the manager.
|
||||
*
|
||||
* @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);
|
||||
|
||||
// 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);
|
||||
|
||||
/**
|
||||
* 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; }
|
||||
|
||||
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; }
|
||||
|
||||
// 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(); }
|
||||
|
||||
/**
|
||||
* 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);
|
||||
|
||||
/**
|
||||
* 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);
|
||||
|
||||
protected:
|
||||
void Register(PktSrc* src);
|
||||
|
||||
// When looking for a source with something to process,
|
||||
// every SELECT_FREQUENCY calls we will go ahead and
|
||||
// block on a select().
|
||||
private:
|
||||
/**
|
||||
* When looking for a source with something to process, every
|
||||
* SELECT_FREQUENCY calls we will go ahead and block on a select().
|
||||
*/
|
||||
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;
|
||||
|
||||
void Register(PktSrc* src);
|
||||
void RemoveAll();
|
||||
|
||||
unsigned int call_count;
|
||||
|
|
|
@ -7,6 +7,9 @@
|
|||
|
||||
namespace iosource {
|
||||
|
||||
/**
|
||||
* Base class for packet dumpers.
|
||||
*/
|
||||
class PktDumper {
|
||||
public:
|
||||
/**
|
||||
|
|
|
@ -387,13 +387,13 @@ void PktSrc::Process()
|
|||
if ( pseudo_realtime )
|
||||
{
|
||||
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 )
|
||||
first_wallclock = current_time(true);
|
||||
}
|
||||
|
||||
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;
|
||||
DoneWithPacket();
|
||||
|
|
|
@ -11,6 +11,9 @@ declare(PDict,BPF_Program);
|
|||
|
||||
namespace iosource {
|
||||
|
||||
/**
|
||||
* Base class for packet sources.
|
||||
*/
|
||||
class PktSrc : public IOSource {
|
||||
public:
|
||||
/**
|
||||
|
|
|
@ -1,3 +1,4 @@
|
|||
// See the file in the main distribution directory for copyright.
|
||||
|
||||
#ifndef IOSOURCE_PKTSRC_PCAP_DUMPER_H
|
||||
#define IOSOURCE_PKTSRC_PCAP_DUMPER_H
|
||||
|
|
|
@ -1,3 +1,4 @@
|
|||
// See the file in the main distribution directory for copyright.
|
||||
|
||||
#include <assert.h>
|
||||
|
||||
|
|
|
@ -377,18 +377,14 @@ void terminate_bro()
|
|||
|
||||
delete broxygen_mgr;
|
||||
delete timer_mgr;
|
||||
delete dns_mgr;
|
||||
delete persistence_serializer;
|
||||
delete event_player;
|
||||
delete event_serializer;
|
||||
delete state_serializer;
|
||||
delete event_registry;
|
||||
delete remote_serializer;
|
||||
delete analyzer_mgr;
|
||||
delete file_mgr;
|
||||
delete log_mgr;
|
||||
delete plugin_mgr;
|
||||
delete thread_mgr;
|
||||
delete reporter;
|
||||
delete iosource_mgr;
|
||||
|
||||
|
@ -841,6 +837,7 @@ int main(int argc, char** argv)
|
|||
// policy, but we can't parse policy without DNS resolution.
|
||||
dns_mgr->SetDir(".state");
|
||||
|
||||
iosource_mgr = new iosource::Manager();
|
||||
persistence_serializer = new PersistenceSerializer();
|
||||
remote_serializer = new RemoteSerializer();
|
||||
event_registry = new EventRegistry();
|
||||
|
@ -848,7 +845,6 @@ int main(int argc, char** argv)
|
|||
log_mgr = new logging::Manager();
|
||||
input_mgr = new input::Manager();
|
||||
file_mgr = new file_analysis::Manager();
|
||||
iosource_mgr = new iosource::Manager();
|
||||
|
||||
plugin_mgr->InitPreScript();
|
||||
analyzer_mgr->InitPreScript();
|
||||
|
@ -908,6 +904,7 @@ int main(int argc, char** argv)
|
|||
|
||||
analyzer_mgr->InitPostScript();
|
||||
file_mgr->InitPostScript();
|
||||
dns_mgr->InitPostScript();
|
||||
|
||||
if ( parse_only )
|
||||
{
|
||||
|
|
|
@ -3,7 +3,7 @@
|
|||
#empty_field (empty)
|
||||
#unset_field -
|
||||
#path loaded_scripts
|
||||
#open 2014-08-14-04-31-10
|
||||
#open 2014-09-06-01-19-42
|
||||
#fields name
|
||||
#types string
|
||||
scripts/base/init-bare.bro
|
||||
|
@ -43,6 +43,7 @@ scripts/base/init-bare.bro
|
|||
scripts/base/frameworks/files/magic/__load__.bro
|
||||
build/scripts/base/bif/__load__.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/cardinality-counter.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
|
||||
scripts/policy/misc/loaded-scripts.bro
|
||||
scripts/base/utils/paths.bro
|
||||
#close 2014-08-14-04-31-10
|
||||
#close 2014-09-06-01-19-42
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue