Conn/Session: Lift history logic into Session

This should allow to mangle a Session's history also from packet
analyzers without necessarily knowing the concrete connection type.

Given Connection is a subclass of Session, I don't think this
changes much.
This commit is contained in:
Arne Welzel 2023-11-30 17:18:53 +01:00
parent fddbdf6232
commit b4e86f28b8
4 changed files with 97 additions and 60 deletions

View file

@ -158,39 +158,6 @@ void Connection::NextPacket(double t, bool is_orig, const IP_Hdr* ip, int len, i
bool Connection::IsReuse(double t, const u_char* pkt) { return adapter && adapter->IsReuse(t, pkt); }
bool Connection::ScaledHistoryEntry(char code, uint32_t& counter, uint32_t& scaling_threshold, uint32_t scaling_base) {
if ( ++counter == scaling_threshold ) {
AddHistory(code);
auto new_threshold = scaling_threshold * scaling_base;
if ( new_threshold <= scaling_threshold )
// This can happen due to wrap-around. In that
// case, reset the counter but leave the threshold
// unchanged.
counter = 0;
else
scaling_threshold = new_threshold;
return true;
}
return false;
}
void Connection::HistoryThresholdEvent(EventHandlerPtr e, bool is_orig, uint32_t threshold) {
if ( ! e )
return;
if ( threshold == 1 )
// This will be far and away the most common case,
// and at this stage it's not a *multiple* instance.
return;
EnqueueEvent(e, nullptr, GetVal(), val_mgr->Bool(is_orig), val_mgr->Count(threshold));
}
namespace {
// Flip everything that needs to be flipped in the connection
// record that is known on this level. This needs to align

View file

@ -179,30 +179,6 @@ public:
static uint64_t TotalConnections() { return total_connections; }
static uint64_t CurrentConnections() { return current_connections; }
// Returns true if the history was already seen, false otherwise.
bool CheckHistory(uint32_t mask, char code) {
if ( (hist_seen & mask) == 0 ) {
hist_seen |= mask;
AddHistory(code);
return false;
}
else
return true;
}
// Increments the passed counter and adds it as a history
// code if it has crossed the next scaling threshold. Scaling
// is done in terms of powers of the third argument.
// Returns true if the threshold was crossed, false otherwise.
bool ScaledHistoryEntry(char code, uint32_t& counter, uint32_t& scaling_threshold, uint32_t scaling_base = 10);
void HistoryThresholdEvent(EventHandlerPtr e, bool is_orig, uint32_t threshold);
void AddHistory(char code) { history += code; }
const std::string& GetHistory() const { return history; }
void ReplaceHistory(std::string new_h) { history = std::move(new_h); }
// Sets the root of the analyzer tree as well as the primary PIA.
void SetSessionAdapter(packet_analysis::IP::SessionAdapter* aa, analyzer::pia::PIA* pia);
packet_analysis::IP::SessionAdapter* GetSessionAdapter() { return adapter; }
@ -246,9 +222,6 @@ private:
unsigned int finished : 1;
unsigned int saw_first_orig_packet : 1, saw_first_resp_packet : 1;
uint32_t hist_seen;
std::string history;
packet_analysis::IP::SessionAdapter* adapter;
analyzer::pia::PIA* primary_PIA;

View file

@ -186,4 +186,37 @@ void Session::SetAnalyzerState(const zeek::Tag& tag, AnalyzerConfirmationState v
analyzer_confirmations.insert_or_assign(tag, value);
}
bool Session::ScaledHistoryEntry(char code, uint32_t& counter, uint32_t& scaling_threshold, uint32_t scaling_base) {
if ( ++counter == scaling_threshold ) {
AddHistory(code);
auto new_threshold = scaling_threshold * scaling_base;
if ( new_threshold <= scaling_threshold )
// This can happen due to wrap-around. In that
// case, reset the counter but leave the threshold
// unchanged.
counter = 0;
else
scaling_threshold = new_threshold;
return true;
}
return false;
}
void Session::HistoryThresholdEvent(EventHandlerPtr e, bool is_orig, uint32_t threshold) {
if ( ! e )
return;
if ( threshold == 1 )
// This will be far and away the most common case,
// and at this stage it's not a *multiple* instance.
return;
EnqueueEvent(e, nullptr, GetVal(), val_mgr->Bool(is_orig), val_mgr->Count(threshold));
}
} // namespace zeek::session

View file

@ -185,6 +185,67 @@ public:
AnalyzerConfirmationState AnalyzerState(const zeek::Tag& tag) const;
void SetAnalyzerState(const zeek::Tag& tag, AnalyzerConfirmationState);
/**
* Add \a code to history unless already seen.
*
* @param mask Bitmask used for the given code character.
* @param code The character to add to the history.
*
* @return True if the given \a code was already seen (mask set),
* otherwise false after adding it.
*/
bool CheckHistory(uint32_t mask, char code) {
if ( (hist_seen & mask) == 0 ) {
hist_seen |= mask;
AddHistory(code);
return false;
}
return true;
}
/**
* Increments the passed counter and adds it as a history
* code if it has crossed the next scaling threshold. Scaling
* is done in terms of powers of the third argument.
*
* @param code The history code.
* @param counter Reference to counter for this code.
* @param scaling_threshold The next threshold, updated to next threshold if crossed.
* @param scaling_base Base to compute the next scaling_threshold.
*
* @return True if the threshold was crossed, false otherwise.
*/
bool ScaledHistoryEntry(char code, uint32_t& counter, uint32_t& scaling_threshold, uint32_t scaling_base = 10);
/**
* Helper to enqueue a history threshold event \a e with the Connection object of this session.
*
* @param e The event to enqueue
* @param is_orig True if this is the originator of the session.
* @param threshold Crossed threshold to use as event argument.
*/
void HistoryThresholdEvent(EventHandlerPtr e, bool is_orig, uint32_t threshold);
/**
* Add \a code to the history.
*
* @param code Code to add
*/
void AddHistory(char code) { history += code; }
/**
* @return The current history value.
*/
const std::string& GetHistory() const { return history; }
/**
* Replace the history of this session with a new one.
*
* @param new_h The new history.
*/
void ReplaceHistory(std::string new_h) { history = std::move(new_h); }
protected:
friend class detail::Timer;
@ -234,6 +295,9 @@ protected:
bool in_session_table;
std::map<zeek::Tag, AnalyzerConfirmationState> analyzer_confirmations;
uint32_t hist_seen;
std::string history;
};
namespace detail {