zeek/src/analyzer/protocol/file/File.cc
Jon Siwek b6862c5c59 Add methods to queue events without handler existence check
Added ConnectionEventFast() and QueueEventFast() methods to avoid
redundant event handler existence checks.

It's common practice for caller to already check for event handler
existence before doing all the work of constructing the arguments, so
it's desirable to not have to check for existence again.

E.g. going through ConnectionEvent() means 3 existence checks:
one you do yourself before calling it, one in ConnectionEvent(), and then
another in QueueEvent().

The existence check itself can be more than a few operations sometimes
as it needs to check a few flags that determine if it's enabled, has
a local body, or has any remote receivers in the old comm. system or
has been flagged as something to publish in the new comm. system.
2019-04-11 20:30:25 -07:00

88 lines
2.1 KiB
C++

#include <algorithm>
#include "File.h"
#include "file_analysis/Manager.h"
#include "RuleMatcher.h"
#include "Reporter.h"
#include "util.h"
#include "events.bif.h"
using namespace analyzer::file;
File_Analyzer::File_Analyzer(const char* name, Connection* conn)
: TCP_ApplicationAnalyzer(name, conn)
{
buffer_len = 0;
}
void File_Analyzer::DeliverStream(int len, const u_char* data, bool orig)
{
tcp::TCP_ApplicationAnalyzer::DeliverStream(len, data, orig);
int n = min(len, BUFFER_SIZE - buffer_len);
if ( n )
{
strncpy(buffer + buffer_len, (const char*) data, n);
buffer_len += n;
if ( buffer_len == BUFFER_SIZE )
Identify();
}
if ( orig )
file_id_orig = file_mgr->DataIn(data, len, GetAnalyzerTag(), Conn(),
orig, file_id_orig);
else
file_id_resp = file_mgr->DataIn(data, len, GetAnalyzerTag(), Conn(),
orig, file_id_resp);
}
void File_Analyzer::Undelivered(uint64 seq, int len, bool orig)
{
TCP_ApplicationAnalyzer::Undelivered(seq, len, orig);
if ( orig )
file_id_orig = file_mgr->Gap(seq, len, GetAnalyzerTag(), Conn(), orig,
file_id_orig);
else
file_id_resp = file_mgr->Gap(seq, len, GetAnalyzerTag(), Conn(), orig,
file_id_resp);
}
void File_Analyzer::Done()
{
tcp::TCP_ApplicationAnalyzer::Done();
if ( buffer_len && buffer_len != BUFFER_SIZE )
Identify();
if ( ! file_id_orig.empty() )
file_mgr->EndOfFile(file_id_orig);
else
file_mgr->EndOfFile(GetAnalyzerTag(), Conn(), true);
if ( ! file_id_resp.empty() )
file_mgr->EndOfFile(file_id_resp);
else
file_mgr->EndOfFile(GetAnalyzerTag(), Conn(), false);
}
void File_Analyzer::Identify()
{
RuleMatcher::MIME_Matches matches;
file_mgr->DetectMIME(reinterpret_cast<const u_char*>(buffer), buffer_len,
&matches);
string match = matches.empty() ? "<unknown>"
: *(matches.begin()->second.begin());
if ( file_transferred )
ConnectionEventFast(file_transferred, {
BuildConnVal(),
new StringVal(buffer_len, buffer),
new StringVal("<unknown>"),
new StringVal(match),
});
}