Add prototype file analysis interfaces.

Nothing connects to them yet and nothing would happen even if it did.
Work on analyzers/actions for files coming soon.
This commit is contained in:
Jon Siwek 2013-01-11 13:12:49 -06:00
parent 564e27abb6
commit 390e4082c7
14 changed files with 635 additions and 2 deletions

View file

@ -0,0 +1 @@
@load ./main.bro

View file

@ -0,0 +1,81 @@
##! TODO add some comments here
@load base/file_analysis.bif
# TODO: do logging here?
@load base/frameworks/logging
module FileAnalysis;
export {
redef enum Log::ID += {
## Logging stream for file analysis.
LOG
};
## The default buffer size used to reassemble files.
# TODO: what's a reasonable default?
const default_reassembly_buffer_size: count = 1024*1024 &redef;
## The default buffer size used for storing the beginning of files.
# TODO: what's a reasonable default?
const default_bof_buffer_size: count = 256 &redef;
## The default amount of time file analysis will wait for new file data
## before giving up.
## TODO: what's a reasonable default?
#const default_timeout_interval: interval = 2 mins &redef;
const default_timeout_interval: interval = 10 sec &redef;
## The default amount of data that a user is allowed to extract
## from a file to an event with the
## :bro:see:`FileAnalysis::ACTION_DATA_EVENT` action.
## TODO: what's a reasonable default?
const default_data_event_len: count = 1024*1024 &redef;
## Contains all metadata related to the analysis of a given file, some
## of which is logged.
type Info: record {
## Unique identifier associated with a single file.
file_id: string &log;
## Unique identifier associated with the file if it was extracted
## from a container file as part of the analysis.
parent_file_id: string &log &optional;
## The network protocol over which the file was transferred.
protocol: string &log &optional;
## The set of connections over which the file was transferred,
## indicated by UID strings.
conn_uids: set[string] &log &optional;
## The set of connections over which the file was transferred,
## indicated by 5-tuples.
conn_ids: set[conn_id] &optional;
## Number of bytes provided to the file analysis engine for the file.
seen_bytes: count &log &default=0;
## Total number of bytes that are supposed to comprise the file content.
total_bytes: count &log &optional;
## The number of not all-in-sequence bytes over the course of the
## analysis that had to be discarded due to a reassembly buffer size
## of *reassembly_buffer_size* being filled.
undelivered: count &default=0;
## The amount of time between receiving new data for this file that
## the analysis engine will wait before giving up on it.
timeout_interval: interval &default=default_timeout_interval;
} &redef;
## TODO: document
global policy: hook(trig: Trigger, info: Info);
## TODO: document
global postpone_timeout: function(file_id: string): bool;
}
function postpone_timeout(file_id: string): bool
{
return __postpone_timeout(file_id);
}

View file

@ -2866,3 +2866,4 @@ const snaplen = 8192 &redef;
@load base/frameworks/input @load base/frameworks/input
@load base/frameworks/file-analysis

View file

@ -145,6 +145,7 @@ set(BIF_SRCS
logging.bif logging.bif
input.bif input.bif
event.bif event.bif
file_analysis.bif
const.bif const.bif
types.bif types.bif
strings.bif strings.bif
@ -328,6 +329,7 @@ set(bro_SRCS
FTP.cc FTP.cc
File.cc File.cc
FileAnalyzer.cc FileAnalyzer.cc
FileAnalysisManager.cc
Finger.cc Finger.cc
FlowSrc.cc FlowSrc.cc
Frag.cc Frag.cc

View file

@ -16,7 +16,7 @@ DebugLogger::Stream DebugLogger::streams[NUM_DBGS] = {
{ "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 } { "threading", 0, false }, { "file_analysis", 0, false }
}; };
DebugLogger::DebugLogger(const char* filename) DebugLogger::DebugLogger(const char* filename)

View file

@ -26,6 +26,7 @@ enum DebugStream {
DBG_LOGGING, // Logging streams DBG_LOGGING, // Logging streams
DBG_INPUT, // Input streams DBG_INPUT, // Input streams
DBG_THREADING, // Threading system DBG_THREADING, // Threading system
DBG_FILE_ANALYSIS, // File analysis
NUM_DBGS // Has to be last NUM_DBGS // Has to be last
}; };

276
src/FileAnalysisManager.cc Normal file
View file

@ -0,0 +1,276 @@
#include <vector>
#include "FileAnalysisManager.h"
#include "util.h"
using namespace file_analysis;
static TableVal* empty_conn_id_set()
{
TypeList* set_index = new TypeList(conn_id);
set_index->Append(conn_id->Ref());
return new TableVal(new SetType(set_index, 0));
}
static StringVal* get_conn_uid_val(Connection* conn)
{
char tmp[20];
if ( ! conn->GetUID() )
conn->SetUID(calculate_unique_id());
return new StringVal(uitoa_n(conn->GetUID(), tmp, sizeof(tmp), 62));
}
static RecordVal* get_conn_id_val(const Connection* conn)
{
RecordVal* v = new RecordVal(conn_id);
v->Assign(0, new AddrVal(conn->OrigAddr()));
v->Assign(1, new PortVal(ntohs(conn->OrigPort()), conn->ConnTransport()));
v->Assign(2, new AddrVal(conn->RespAddr()));
v->Assign(3, new PortVal(ntohs(conn->RespPort()), conn->ConnTransport()));
return v;
}
int Info::file_id_idx = -1;
int Info::parent_file_id_idx = -1;
int Info::protocol_idx = -1;
int Info::conn_uids_idx = -1;
int Info::conn_ids_idx = -1;
int Info::seen_bytes_idx = -1;
int Info::total_bytes_idx = -1;
int Info::undelivered_idx = -1;
int Info::timeout_interval_idx = -1;
Info::Info(const string& file_id, Connection* conn, AnalyzerTag::Tag at)
: val(0), last_activity_time(network_time), postpone_timeout(false)
{
DBG_LOG(DBG_FILE_ANALYSIS, "Creating new Info object %s", file_id.c_str());
if ( file_id_idx == -1 )
{
file_id_idx = Idx("file_id");
parent_file_id_idx = Idx("parent_file_id");
protocol_idx = Idx("protocol");
conn_uids_idx = Idx("conn_uids");
conn_ids_idx = Idx("conn_ids");
seen_bytes_idx = Idx("seen_bytes");
total_bytes_idx = Idx("total_bytes");
undelivered_idx = Idx("undelivered");
timeout_interval_idx = Idx("timeout_interval");
}
val = new RecordVal(BifType::Record::FileAnalysis::Info);
val->Assign(file_id_idx, new StringVal(file_id.c_str()));
UpdateConnectionFields(conn);
if ( at != AnalyzerTag::Error )
val->Assign(protocol_idx, new StringVal(Analyzer::GetTagName(at)));
ScheduleInactivityTimer();
Manager::EvaluatePolicy(BifEnum::FileAnalysis::TRIGGER_NEW, this);
}
Info::~Info()
{
DBG_LOG(DBG_FILE_ANALYSIS, "Destroying Info object %s", FileID().c_str());
Unref(val);
}
void Info::UpdateConnectionFields(Connection* conn)
{
if ( ! conn ) return;
Val* conn_uids = val->Lookup(conn_uids_idx);
Val* conn_ids = val->Lookup(conn_ids_idx);
if ( ! conn_uids )
val->Assign(conn_uids_idx, conn_uids = new TableVal(string_set));
if ( ! conn_ids )
val->Assign(conn_ids_idx, conn_ids = empty_conn_id_set());
conn_uids->AsTableVal()->Assign(get_conn_uid_val(conn), 0);
conn_ids->AsTableVal()->Assign(get_conn_id_val(conn), 0);
}
int Info::Idx(const string& field)
{
int rval = BifType::Record::FileAnalysis::Info->FieldOffset(field.c_str());
if ( rval < 0 )
reporter->InternalError("Unkown FileAnalysis::Info field: %s",
field.c_str());
return rval;
}
double Info::TimeoutInterval() const
{
return val->LookupWithDefault(timeout_interval_idx)->AsInterval();
}
string Info::FileID() const
{
return val->Lookup(file_id_idx)->AsString()->CheckString();
}
void Info::SetTotalBytes(uint64 size)
{
val->Assign(total_bytes_idx, new Val(size, TYPE_COUNT));
if ( val->LookupWithDefault(seen_bytes_idx)->AsCount() >= size )
{
Manager::EvaluatePolicy(BifEnum::FileAnalysis::TRIGGER_DONE, this);
file_mgr->Remove(FileID());
}
}
void Info::ScheduleInactivityTimer() const
{
timer_mgr->Add(new InfoTimer(network_time, FileID(), TimeoutInterval()));
}
void InfoTimer::Dispatch(double t, int is_expire)
{
Info* info = file_mgr->Lookup(file_id);
if ( ! info ) return;
double last_active = info->LastActivityTime();
double inactive_time = t > last_active ? t - last_active : 0.0;
DBG_LOG(DBG_FILE_ANALYSIS, "Checking inactivity for %s, last active at %f, "
"inactive for %f", file_id.c_str(), last_active, inactive_time);
if ( last_active == 0.0 )
{
// was created when network_time was zero, so re-schedule w/ valid time
info->UpdateLastActivityTime();
info->ScheduleInactivityTimer();
return;
}
if ( inactive_time >= info->TimeoutInterval() )
file_mgr->Timeout(file_id);
else if ( ! is_expire )
info->ScheduleInactivityTimer();
}
Manager::Manager()
{
}
Manager::~Manager()
{
Terminate();
}
void Manager::Terminate()
{
vector<string> keys;
for ( FileMap::iterator it = file_map.begin(); it != file_map.end(); ++it )
keys.push_back(it->first);
for ( size_t i = 0; i < keys.size(); ++i )
Timeout(keys[i], true);
}
void Manager::DataIn(const string& file_id, const u_char* data, uint64 len,
uint64 offset, Connection* conn, AnalyzerTag::Tag at)
{
Info* info = IDtoInfo(file_id, conn, at);
info->UpdateLastActivityTime();
info->UpdateConnectionFields(conn);
// TODO: more stuff
}
void Manager::DataIn(const string& file_id, const u_char* data, uint64 len,
Connection* conn, AnalyzerTag::Tag at)
{
Info* info = IDtoInfo(file_id, conn, at);
info->UpdateLastActivityTime();
info->UpdateConnectionFields(conn);
// TODO: more stuff
}
void Manager::SetSize(const string& file_id, uint64 size,
Connection* conn, AnalyzerTag::Tag at)
{
Info* info = IDtoInfo(file_id, conn, at);
info->UpdateLastActivityTime();
info->UpdateConnectionFields(conn);
info->SetTotalBytes(size);
}
void Manager::EvaluatePolicy(BifEnum::FileAnalysis::Trigger t, Info* info)
{
const ID* id = global_scope()->Lookup("FileAnalysis::policy");
assert(id);
const Func* hook = id->ID_Val()->AsFunc();
val_list vl(2);
vl.append(new EnumVal(t, BifType::Enum::FileAnalysis::Trigger));
vl.append(info->val->Ref());
info->postpone_timeout = false;
Val* result = hook->Call(&vl);
Unref(result);
}
bool Manager::PostponeTimeout(const string& file_id) const
{
Info* info = Lookup(file_id);
if ( ! info ) return false;
info->postpone_timeout = true;
return true;
}
Info* Manager::IDtoInfo(const string& file_id, Connection* conn,
AnalyzerTag::Tag at)
{
Info* rval = file_map[file_id];
if ( ! rval )
rval = file_map[file_id] = new Info(file_id, conn, at);
return rval;
}
Info* Manager::Lookup(const string& file_id) const
{
FileMap::const_iterator it = file_map.find(file_id);
if ( it == file_map.end() ) return 0;
return it->second;
}
void Manager::Timeout(const string& file_id, bool is_terminating)
{
Info* info = Lookup(file_id);
if ( ! info ) return;
EvaluatePolicy(BifEnum::FileAnalysis::TRIGGER_TIMEOUT, info);
if ( info->postpone_timeout && ! is_terminating )
{
DBG_LOG(DBG_FILE_ANALYSIS, "Postpone file analysis timeout for %s",
info->FileID().c_str());
info->UpdateLastActivityTime();
info->ScheduleInactivityTimer();
return;
}
DBG_LOG(DBG_FILE_ANALYSIS, "File analysis timeout for %s",
info->FileID().c_str());
file_map.erase(file_id);
delete info;
}
void Manager::Remove(const string& file_id)
{
FileMap::iterator it = file_map.find(file_id);
if ( it == file_map.end() ) return;
delete it->second;
file_map.erase(it);
}

199
src/FileAnalysisManager.h Normal file
View file

@ -0,0 +1,199 @@
#ifndef FILE_ANALYSIS_MANAGER_H
#define FILE_ANALYSIS_MANAGER_H
#include <string>
#include <map>
#include "Conn.h"
#include "Analyzer.h"
#include "AnalyzerTags.h"
#include "Timer.h"
#include "Val.h"
#include "Reporter.h"
namespace file_analysis {
/**
* Wrapper class around \c FileAnalysis::Info record values from script layer.
*/
class Info {
public:
~Info();
/**
* @return value (seconds) of the "timeout_interval" field from #val record.
*/
double TimeoutInterval() const;
/**
* @return value of the "file_id" field from #val record.
*/
string FileID() const;
/**
* @return #last_activity_time
*/
double LastActivityTime() const { return last_activity_time; }
/**
* Refreshes #last_activity_time with current network time.
*/
void UpdateLastActivityTime() { last_activity_time = network_time; }
/**
* Set "total_bytes" field of #val record to \a size, check if "seen_bytes"
* is greater or equal to it, and evaluate \c FileAnalysis::policy if so.
*/
void SetTotalBytes(uint64 size);
/**
* Create a timer to be dispatched after the amount of time indicated by
* the "timeout_interval" field of the #val record in order to check if
* #last_activity_time is old enough to timeout analysis of the file.
*/
void ScheduleInactivityTimer() const;
protected:
friend class Manager;
/**
* Constructor; only file_analysis::Manager should be creating these.
*/
Info(const string& file_id, Connection* conn = 0,
AnalyzerTag::Tag at = AnalyzerTag::Error);
/**
* Updates the "conn_ids" and "conn_uids" fields in #val record with the
* \c conn_id and UID taken from \a conn.
*/
void UpdateConnectionFields(Connection* conn);
RecordVal* val; /**< \c FileAnalysis::Info from script layer. */
double last_activity_time; /**< Time of last activity. */
bool postpone_timeout; /**< Whether postponing timeout is requested. */
/**
* @return the field offset in #val record corresponding to \a field_name.
*/
static int Idx(const string& field_name);
static int file_id_idx;
static int parent_file_id_idx;
static int protocol_idx;
static int conn_uids_idx;
static int conn_ids_idx;
static int seen_bytes_idx;
static int total_bytes_idx;
static int undelivered_idx;
static int timeout_interval_idx;
};
/**
* Timer to periodically check if file analysis for a given file is inative.
*/
class InfoTimer : public Timer {
public:
InfoTimer(double t, const string& id, double interval)
: Timer(t + interval, TIMER_FILE_ANALYSIS_INACTIVITY), file_id(id) { }
~InfoTimer() { }
/**
* Check inactivity of file_analysis::Info corresponding to #file_id,
* reschedule if active, else call file_analysis::Manager::Timeout.
*/
void Dispatch(double t, int is_expire);
protected:
string file_id;
};
/**
* Main entry point for interacting with file analysis.
*/
class Manager {
public:
Manager();
~Manager();
/**
* Times out any active file analysis to prepare for shutdown.
*/
void Terminate();
/**
* Pass in non-sequential file data.
*/
void DataIn(const string& file_id, const u_char* data, uint64 len,
uint64 offset, Connection* conn = 0,
AnalyzerTag::Tag at = AnalyzerTag::Error);
/**
* Pass in sequential file data.
*/
void DataIn(const string& file_id, const u_char* data, uint64 len,
Connection* conn = 0,
AnalyzerTag::Tag at = AnalyzerTag::Error);
/**
* Provide the expected number of bytes that comprise a file.
*/
void SetSize(const string& file_id, uint64 size, Connection* conn = 0,
AnalyzerTag::Tag at = AnalyzerTag::Error);
/**
* Discard the file_analysis::Info object associated with \a file_id.
*/
void Remove(const string& file_id);
/**
* If called during \c FileAnalysis::policy evaluation for a
* \c FileAnalysis::TRIGGER_TIMEOUT, requests deferral of analysis timeout.
*/
bool PostponeTimeout(const string& file_id) const;
/**
* Calls the \c FileAnalysis::policy hook.
*/
static void EvaluatePolicy(BifEnum::FileAnalysis::Trigger t, Info* info);
protected:
friend class InfoTimer;
typedef map<string, Info*> FileMap;
/**
* @return the Info object mapped to \a file_id. One is created if mapping
* doesn't exist.
*/
Info* IDtoInfo(const string& file_id, Connection* conn = 0,
AnalyzerTag::Tag at = AnalyzerTag::Error);
/**
* @return the Info object mapped to \a file_id, or a null pointer if no
* mapping exists.
*/
Info* Lookup(const string& file_id) const;
/**
* Evaluate timeout policy for a file and remove the Info object mapped to
* \a file_id if needed.
*/
void Timeout(const string& file_id, bool is_terminating = ::terminating);
FileMap file_map; /**< Map strings to \c FileAnalysis::Info records. */
};
} // namespace file_analysis
extern file_analysis::Manager* file_mgr;
#endif

View file

@ -557,12 +557,14 @@ void builtin_error(const char* msg, BroObj* arg)
#include "input.bif.func_h" #include "input.bif.func_h"
#include "reporter.bif.func_h" #include "reporter.bif.func_h"
#include "strings.bif.func_h" #include "strings.bif.func_h"
#include "file_analysis.bif.func_h"
#include "bro.bif.func_def" #include "bro.bif.func_def"
#include "logging.bif.func_def" #include "logging.bif.func_def"
#include "input.bif.func_def" #include "input.bif.func_def"
#include "reporter.bif.func_def" #include "reporter.bif.func_def"
#include "strings.bif.func_def" #include "strings.bif.func_def"
#include "file_analysis.bif.func_def"
void init_builtin_funcs() void init_builtin_funcs()
{ {
@ -578,6 +580,7 @@ void init_builtin_funcs()
#include "input.bif.func_init" #include "input.bif.func_init"
#include "reporter.bif.func_init" #include "reporter.bif.func_init"
#include "strings.bif.func_init" #include "strings.bif.func_init"
#include "file_analysis.bif.func_init"
did_builtin_init = true; did_builtin_init = true;
} }

View file

@ -246,6 +246,7 @@ StringVal* cmd_line_bpf_filter;
#include "logging.bif.netvar_def" #include "logging.bif.netvar_def"
#include "input.bif.netvar_def" #include "input.bif.netvar_def"
#include "reporter.bif.netvar_def" #include "reporter.bif.netvar_def"
#include "file_analysis.bif.netvar_def"
void init_event_handlers() void init_event_handlers()
{ {
@ -308,6 +309,7 @@ void init_net_var()
#include "logging.bif.netvar_init" #include "logging.bif.netvar_init"
#include "input.bif.netvar_init" #include "input.bif.netvar_init"
#include "reporter.bif.netvar_init" #include "reporter.bif.netvar_init"
#include "file_analysis.bif.netvar_init"
gtpv1_hdr_type = internal_type("gtpv1_hdr")->AsRecordType(); gtpv1_hdr_type = internal_type("gtpv1_hdr")->AsRecordType();
conn_id = internal_type("conn_id")->AsRecordType(); conn_id = internal_type("conn_id")->AsRecordType();

View file

@ -256,5 +256,6 @@ extern void init_net_var();
#include "logging.bif.netvar_h" #include "logging.bif.netvar_h"
#include "input.bif.netvar_h" #include "input.bif.netvar_h"
#include "reporter.bif.netvar_h" #include "reporter.bif.netvar_h"
#include "file_analysis.bif.netvar_h"
#endif #endif

View file

@ -22,6 +22,7 @@ enum TimerType {
TIMER_CONN_INACTIVITY, TIMER_CONN_INACTIVITY,
TIMER_CONN_STATUS_UPDATE, TIMER_CONN_STATUS_UPDATE,
TIMER_DNS_EXPIRE, TIMER_DNS_EXPIRE,
TIMER_FILE_ANALYSIS_INACTIVITY,
TIMER_FRAG, TIMER_FRAG,
TIMER_INCREMENTAL_SEND, TIMER_INCREMENTAL_SEND,
TIMER_INCREMENTAL_WRITE, TIMER_INCREMENTAL_WRITE,

59
src/file_analysis.bif Normal file
View file

@ -0,0 +1,59 @@
##! Internal functions and types used by the logging framework.
module FileAnalysis;
%%{
#include "FileAnalysisManager.h"
%%}
type Info: record;
## An enumeration of possibly-interesting "events" that can occur over
## the course of analyzing files. The :bro:see:`FileAnalysis::policy`
## hook is called each time a trigger occurs.
enum Trigger %{
## Raised when any part of a new file is detected.
TRIGGER_NEW,
## Raised when file analysis has likely seen a complete file. That
## is when a number of bytes indicated by the *total_bytes* field of
## :bro:see:`FileAnalysis::Info` have been processed. Note that
## the *undelivered* field does not have to be zero for this to have
## occurred.
TRIGGER_DONE,
## Raised when file analysis for a given file is aborted due
## to not seeing any data for it recently. Note that this doesn't
## necessarily mean the full file wasn't seen (e.g. if the
## :bro:see:`FileAnalysis::Info` record indicates the file *total_bytes*
## isn't known). Use :bro:see:`FileAnalysis::postpone_timeout`
## during a :bro:see:`FileAnalysis::policy` handler for this trigger to
## defer the timeout until later.
TRIGGER_TIMEOUT,
## Raised when the beginning of a file is detected.
TRIGGER_BOF,
## Raised when the beginning of a file is available and that beginning
## is at least the number of bytes indicated by the *bof_buffer_size*
## field of :bro:see:`FileAnalysis::Info`.
TRIGGER_BOF_BUFFER_AVAIL,
## Raised when the mime type of a file is matched based on magic
## numbers. TODO: re-purposing protocols/http/file-ident.sig for
## doing this is tricky since the signature engine doesn't expect
## to be decoupled from connections, so figure out what work needs
## done there.
TRIGGER_MIME_TYPE,
## Raised when the end of a file is detected. If the file is not
## being transferred linearly, then this doesn't have to mean the full
## file has been transferred.
TRIGGER_EOF,
## The reassembly buffer for the file filled and had to be discarded.
## The *undelivered* field of :bro:see:`FileAnalysis::Info` will
## indicate the number of bytes, if any, that were not all-in-sequence.
## TODO: Is it possible to extend the reassembly buffer when "handling"
## this trigger?
TRIGGER_REASSEMBLY_BUFFER_FULL,
%}
function FileAnalysis::__postpone_timeout%(file_id: string%): bool
%{
bool result = file_mgr->PostponeTimeout(file_id->CheckString());
return new Val(result, TYPE_BOOL);
%}

View file

@ -58,6 +58,8 @@ extern "C" void OPENSSL_add_all_algorithms_conf(void);
#include "logging/Manager.h" #include "logging/Manager.h"
#include "logging/writers/Ascii.h" #include "logging/writers/Ascii.h"
#include "FileAnalysisManager.h"
#include "binpac_bro.h" #include "binpac_bro.h"
Brofiler brofiler; Brofiler brofiler;
@ -86,6 +88,7 @@ TimerMgr* timer_mgr;
logging::Manager* log_mgr = 0; logging::Manager* log_mgr = 0;
threading::Manager* thread_mgr = 0; threading::Manager* thread_mgr = 0;
input::Manager* input_mgr = 0; input::Manager* input_mgr = 0;
file_analysis::Manager* file_mgr = 0;
Stmt* stmts; Stmt* stmts;
EventHandlerPtr net_done = 0; EventHandlerPtr net_done = 0;
RuleMatcher* rule_matcher = 0; RuleMatcher* rule_matcher = 0;
@ -319,6 +322,7 @@ void terminate_bro()
mgr.Drain(); mgr.Drain();
file_mgr->Terminate();
log_mgr->Terminate(); log_mgr->Terminate();
thread_mgr->Terminate(); thread_mgr->Terminate();
@ -336,6 +340,7 @@ void terminate_bro()
delete dpm; delete dpm;
delete log_mgr; delete log_mgr;
delete thread_mgr; delete thread_mgr;
delete file_mgr;
delete reporter; delete reporter;
reporter = 0; reporter = 0;
@ -775,7 +780,8 @@ int main(int argc, char** argv)
remote_serializer = new RemoteSerializer(); remote_serializer = new RemoteSerializer();
event_registry = new EventRegistry(); event_registry = new EventRegistry();
log_mgr = new logging::Manager(); log_mgr = new logging::Manager();
input_mgr = new input::Manager(); input_mgr = new input::Manager();
file_mgr = new file_analysis::Manager();
if ( events_file ) if ( events_file )
event_player = new EventPlayer(events_file); event_player = new EventPlayer(events_file);