Allow to overwrite packet analysis mappings.

This commit is contained in:
Jan Grashoefer 2020-08-26 13:53:06 +02:00 committed by Tim Wojtulewicz
parent fc814bd7e2
commit 54961b5ea2
5 changed files with 50 additions and 52 deletions

View file

@ -42,9 +42,9 @@ bool Analyzer::IsAnalyzer(const char* name)
return packet_mgr->GetComponentName(tag) == name; return packet_mgr->GetComponentName(tag) == name;
} }
bool Analyzer::RegisterAnalyzerMapping(uint32_t identifier, AnalyzerPtr analyzer) void Analyzer::RegisterAnalyzerMapping(uint32_t identifier, AnalyzerPtr analyzer)
{ {
return dispatcher.Register(identifier, std::move(analyzer)); dispatcher.Register(identifier, std::move(analyzer));
} }
void Analyzer::RegisterDefaultAnalyzer(AnalyzerPtr default_analyzer) void Analyzer::RegisterDefaultAnalyzer(AnalyzerPtr default_analyzer)

View file

@ -74,9 +74,8 @@ public:
* *
* @param identifier The identifier an analyzer should be called for. * @param identifier The identifier an analyzer should be called for.
* @param analyzer The analyzer that should be called. * @param analyzer The analyzer that should be called.
* @return True if the registration was successful.
*/ */
bool RegisterAnalyzerMapping(uint32_t identifier, AnalyzerPtr analyzer); void RegisterAnalyzerMapping(uint32_t identifier, AnalyzerPtr analyzer);
/** /**
* Registers a default analyzer. * Registers a default analyzer.

View file

@ -4,6 +4,7 @@
#include "Dispatcher.h" #include "Dispatcher.h"
#include "Analyzer.h" #include "Analyzer.h"
#include "Reporter.h"
#include "DebugLogger.h" #include "DebugLogger.h"
namespace zeek::packet_analysis { namespace zeek::packet_analysis {
@ -13,14 +14,14 @@ Dispatcher::~Dispatcher()
FreeValues(); FreeValues();
} }
bool Dispatcher::Register(uint32_t identifier, AnalyzerPtr analyzer) void Dispatcher::Register(uint32_t identifier, AnalyzerPtr analyzer)
{ {
// If the table has size 1 and the entry is nullptr, there was nothing added yet. Just add it. // If the table has size 1 and the entry is nullptr, there was nothing added yet. Just add it.
if ( table.size() == 1 && table[0] == nullptr ) if ( table.size() == 1 && table[0] == nullptr )
{ {
table[0] = analyzer; table[0] = std::move(analyzer);
lowest_identifier = identifier; lowest_identifier = identifier;
return true; return;
} }
// If highestIdentifier == identifier, overwrite would happen -> no check needed, will return false // If highestIdentifier == identifier, overwrite would happen -> no check needed, will return false
@ -39,7 +40,7 @@ bool Dispatcher::Register(uint32_t identifier, AnalyzerPtr analyzer)
{ {
if ( table[i] != nullptr ) if ( table[i] != nullptr )
{ {
table.at(i + distance) = table.at(i); table.at(i + distance) = std::move(table.at(i));
table.at(i) = nullptr; table.at(i) = nullptr;
} }
} }
@ -48,36 +49,10 @@ bool Dispatcher::Register(uint32_t identifier, AnalyzerPtr analyzer)
} }
int64_t index = identifier - lowest_identifier; int64_t index = identifier - lowest_identifier;
//TODO: Allow to overwrite mappings? if ( table[index] != nullptr )
if ( table[index] == nullptr ) reporter->InternalWarning("Overwriting packet analyzer mapping %#8" PRIx64 " => %s with %s",
{ index+lowest_identifier, table[index]->GetAnalyzerName(), analyzer->GetAnalyzerName());
table[index] = analyzer; table[index] = std::move(analyzer);
return true;
}
return false;
}
void Dispatcher::Register(const register_map& data)
{
// Search smallest and largest identifier and resize vector
const auto& lowest_new =
std::min_element(data.begin(), data.end(),
[](const register_pair& a, const register_pair& b) {
return a.first < b.first;
});
// Register lowest first in order to do shifting only once
Register(lowest_new->first, lowest_new->second);
for ( auto i = data.begin(); i != data.end(); i++ )
{
// Already added if i == lowest_new
if ( i == lowest_new )
continue;
if ( ! Register(i->first, i->second) )
throw std::invalid_argument("Analyzer already registered!");
}
} }
AnalyzerPtr Dispatcher::Lookup(uint32_t identifier) const AnalyzerPtr Dispatcher::Lookup(uint32_t identifier) const
@ -89,7 +64,7 @@ AnalyzerPtr Dispatcher::Lookup(uint32_t identifier) const
return nullptr; return nullptr;
} }
size_t Dispatcher::Size() const size_t Dispatcher::Count() const
{ {
return std::count_if(table.begin(), table.end(), [](AnalyzerPtr a) { return a != nullptr; }); return std::count_if(table.begin(), table.end(), [](AnalyzerPtr a) { return a != nullptr; });
} }
@ -109,12 +84,12 @@ void Dispatcher::FreeValues()
void Dispatcher::DumpDebug() const void Dispatcher::DumpDebug() const
{ {
#ifdef DEBUG #ifdef DEBUG
DBG_LOG(DBG_PACKET_ANALYSIS, " Dispatcher elements (used/total): %lu/%lu", Size(), table.size()); DBG_LOG(DBG_PACKET_ANALYSIS, "Dispatcher elements (used/total): %lu/%lu", Count(), table.size());
DBG_LOG(DBG_PACKET_ANALYSIS, "TABLE SIZE %lu", table.size());
for ( size_t i = 0; i < table.size(); i++ ) for ( size_t i = 0; i < table.size(); i++ )
{ {
if ( table[i] != nullptr ) if ( table[i] != nullptr )
DBG_LOG(DBG_PACKET_ANALYSIS, " %#8lx => %s", i+lowest_identifier, table[i]->GetAnalyzerName()); DBG_LOG(DBG_PACKET_ANALYSIS, "%#8lx => %s",
i+lowest_identifier, table[i]->GetAnalyzerName());
} }
#endif #endif
} }

View file

@ -12,24 +12,45 @@ namespace zeek::packet_analysis {
class Analyzer; // Forward declaration for Value class Analyzer; // Forward declaration for Value
using AnalyzerPtr = std::shared_ptr<zeek::packet_analysis::Analyzer>; using AnalyzerPtr = std::shared_ptr<zeek::packet_analysis::Analyzer>;
using register_pair = std::pair<uint32_t, AnalyzerPtr>; /**
using register_map = std::map<uint32_t, AnalyzerPtr>; * The Dispatcher class manages identifier-to-analyzer mappings.
*/
class Dispatcher { class Dispatcher {
public: public:
Dispatcher() Dispatcher() : table(std::vector<AnalyzerPtr>(1, nullptr)) { };
: table(std::vector<AnalyzerPtr>(1, nullptr))
{ }
~Dispatcher(); ~Dispatcher();
bool Register(uint32_t identifier, AnalyzerPtr analyzer); /**
void Register(const register_map& data); * Register an analyzer for a given identifier.
*
* @param identifier The identifier.
* @param analyzer The analyzer to register.
*/
void Register(uint32_t identifier, AnalyzerPtr analyzer);
/**
* Looks up the analyzer for an identifier.
*
* @param identifier The identifier to look up.
* @return The analyzer registered for the given identifier. Returns a
* nullptr if no analyzer is registered.
*/
AnalyzerPtr Lookup(uint32_t identifier) const; AnalyzerPtr Lookup(uint32_t identifier) const;
size_t Size() const; /**
* Returns the number of registered analyzers.
* @return Number of registered analyzers.
*/
size_t Count() const;
/**
* Removes all mappings from the dispatcher.
*/
void Clear(); void Clear();
/**
* Dumps out the data structure to the \c analyzer debug stream.
*/
void DumpDebug() const; void DumpDebug() const;
private: private:

View file

@ -90,6 +90,9 @@ void Manager::DumpDebug()
{ {
DBG_LOG(DBG_PACKET_ANALYSIS, " %s", current->Name().c_str()); DBG_LOG(DBG_PACKET_ANALYSIS, " %s", current->Name().c_str());
} }
DBG_LOG(DBG_PACKET_ANALYSIS, "Root dispatcher:");
root_dispatcher.DumpDebug();
#endif #endif
} }