diff --git a/src/Conn.cc b/src/Conn.cc index 5d55e47095..6169559e7c 100644 --- a/src/Conn.cc +++ b/src/Conn.cc @@ -20,6 +20,7 @@ #include "zeek/analyzer/Manager.h" #include "zeek/iosource/IOSource.h" #include "zeek/packet_analysis/protocol/ip/SessionAdapter.h" +#include "zeek/packet_analysis/protocol/tcp/TCP.h" namespace zeek { @@ -125,23 +126,23 @@ void Connection::CheckEncapsulation(const std::shared_ptr& a void Connection::Done() { - // TODO: this still doesn't feel like the right place to do this, but it's better - // here than in SessionManager. This really should be down in the TCP analyzer - // somewhere, but it's session-related, so maybe not? - if ( ConnTransport() == TRANSPORT_TCP ) - { - auto* ta = static_cast(adapter); - assert(ta->IsAnalyzer("TCP")); - analyzer::tcp::TCP_Endpoint* to = ta->Orig(); - analyzer::tcp::TCP_Endpoint* tr = ta->Resp(); - - session_mgr->tcp_stats.StateLeft(to->state, tr->state); - } - finished = 1; - if ( adapter && ! adapter->IsFinished() ) - adapter->Done(); + if ( adapter ) + { + if ( ConnTransport() == TRANSPORT_TCP ) + { + auto* ta = static_cast(adapter); + assert(ta->IsAnalyzer("TCP")); + analyzer::tcp::TCP_Endpoint* to = ta->Orig(); + analyzer::tcp::TCP_Endpoint* tr = ta->Resp(); + + packet_analysis::TCP::TCPAnalyzer::GetStats().StateLeft(to->state, tr->state); + } + + if ( ! adapter->IsFinished() ) + adapter->Done(); + } } void Connection::NextPacket(double t, bool is_orig, diff --git a/src/Stats.cc b/src/Stats.cc index 9acca4e9f9..65e22ee4a8 100644 --- a/src/Stats.cc +++ b/src/Stats.cc @@ -15,6 +15,7 @@ #include "zeek/broker/Manager.h" #include "zeek/input.h" #include "zeek/Func.h" +#include "zeek/packet_analysis/protocol/tcp/TCP.h" uint64_t zeek::detail::killed_by_inactivity = 0; uint64_t& killed_by_inactivity = zeek::detail::killed_by_inactivity; @@ -155,7 +156,7 @@ void ProfileLogger::Log() s.num_ICMP_conns, s.max_ICMP_conns )); - session_mgr->tcp_stats.PrintStats(file, + packet_analysis::TCP::TCPAnalyzer::GetStats().PrintStats(file, util::fmt("%.06f TCP-States:", run_state::network_time)); // Alternatively, if you prefer more compact output... diff --git a/src/analyzer/protocol/tcp/CMakeLists.txt b/src/analyzer/protocol/tcp/CMakeLists.txt index 270beb36d8..885897cd31 100644 --- a/src/analyzer/protocol/tcp/CMakeLists.txt +++ b/src/analyzer/protocol/tcp/CMakeLists.txt @@ -4,7 +4,7 @@ include(ZeekPlugin) include_directories(BEFORE ${CMAKE_CURRENT_SOURCE_DIR} ${CMAKE_CURRENT_BINARY_DIR}) zeek_plugin_begin(Zeek TCP) -zeek_plugin_cc(TCP.cc TCP_Endpoint.cc TCP_Reassembler.cc ContentLine.cc Stats.cc Plugin.cc) +zeek_plugin_cc(TCP.cc TCP_Endpoint.cc TCP_Reassembler.cc ContentLine.cc Plugin.cc) zeek_plugin_bif(events.bif) zeek_plugin_bif(types.bif) zeek_plugin_bif(functions.bif) diff --git a/src/analyzer/protocol/tcp/Stats.cc b/src/analyzer/protocol/tcp/Stats.cc deleted file mode 100644 index 96b085954b..0000000000 --- a/src/analyzer/protocol/tcp/Stats.cc +++ /dev/null @@ -1,85 +0,0 @@ -#include "zeek/analyzer/protocol/tcp/Stats.h" - -#include "zeek/File.h" - -#include "zeek/analyzer/protocol/tcp/events.bif.h" - -namespace zeek::analyzer::tcp { - -TCPStateStats::TCPStateStats() - { - for ( int i = 0; i < TCP_ENDPOINT_RESET + 1; ++i ) - for ( int j = 0; j < TCP_ENDPOINT_RESET + 1; ++j ) - state_cnt[i][j] = 0; - } - -void TCPStateStats::ChangeState(EndpointState o_prev, EndpointState o_now, - EndpointState r_prev, EndpointState r_now) - { - --state_cnt[o_prev][r_prev]; - ++state_cnt[o_now][r_now]; - } - -void TCPStateStats::FlipState(EndpointState orig, EndpointState resp) - { - --state_cnt[orig][resp]; - ++state_cnt[resp][orig]; - } - -unsigned int TCPStateStats::NumStatePartial() const - { - unsigned int sum = 0; - for ( int i = 0; i < TCP_ENDPOINT_RESET + 1; ++i ) - { - sum += state_cnt[TCP_ENDPOINT_PARTIAL][i]; - sum += state_cnt[i][TCP_ENDPOINT_PARTIAL]; - } - - return sum; - } - -void TCPStateStats::PrintStats(File* file, const char* prefix) - { - file->Write(prefix); - file->Write(" Inact. Syn. SA Part. Est. Fin. Rst.\n"); - - for ( int i = 0; i < TCP_ENDPOINT_RESET + 1; ++i ) - { - file->Write(prefix); - - switch ( i ) { -#define STATE_STRING(state, str) \ - case state: \ - file->Write(str); \ - break; - - STATE_STRING(TCP_ENDPOINT_INACTIVE, "Inact."); - STATE_STRING(TCP_ENDPOINT_SYN_SENT, "Syn. "); - STATE_STRING(TCP_ENDPOINT_SYN_ACK_SENT, "SA "); - STATE_STRING(TCP_ENDPOINT_PARTIAL, "Part. "); - STATE_STRING(TCP_ENDPOINT_ESTABLISHED, "Est. "); - STATE_STRING(TCP_ENDPOINT_CLOSED, "Fin. "); - STATE_STRING(TCP_ENDPOINT_RESET, "Rst. "); - - } - - file->Write(" "); - - for ( int j = 0; j < TCP_ENDPOINT_RESET + 1; ++j ) - { - unsigned int n = state_cnt[i][j]; - if ( n > 0 ) - { - char buf[32]; - snprintf(buf, sizeof(buf), "%-8d", state_cnt[i][j]); - file->Write(buf); - } - else - file->Write(" "); - } - - file->Write("\n"); - } - } - -} // namespace zeek::analyzer::tcp diff --git a/src/analyzer/protocol/tcp/Stats.h b/src/analyzer/protocol/tcp/Stats.h deleted file mode 100644 index d9ca5127e7..0000000000 --- a/src/analyzer/protocol/tcp/Stats.h +++ /dev/null @@ -1,67 +0,0 @@ -#pragma once - -#include "zeek/analyzer/protocol/tcp/TCP_Endpoint.h" - -namespace zeek::analyzer::tcp { - -// A TCPStateStats object tracks the distribution of TCP states for -// the currently active connections. -class TCPStateStats { -public: - TCPStateStats(); - ~TCPStateStats() = default; - - void ChangeState(EndpointState o_prev, EndpointState o_now, - EndpointState r_prev, EndpointState r_now); - void FlipState(EndpointState orig, EndpointState resp); - - void StateEntered (EndpointState o_state, EndpointState r_state) - { ++state_cnt[o_state][r_state]; } - void StateLeft (EndpointState o_state, EndpointState r_state) - { --state_cnt[o_state][r_state]; } - - unsigned int Cnt(EndpointState state) const - { return Cnt(state, state); } - unsigned int Cnt(EndpointState state1, EndpointState state2) const - { return state_cnt[state1][state2]; } - - unsigned int NumStateEstablished() const - { return Cnt(TCP_ENDPOINT_ESTABLISHED); } - unsigned int NumStateHalfClose() const - { // corresponds to S2,S3 - return Cnt(TCP_ENDPOINT_ESTABLISHED, TCP_ENDPOINT_CLOSED) + - Cnt(TCP_ENDPOINT_CLOSED, TCP_ENDPOINT_ESTABLISHED); - } - unsigned int NumStateHalfRst() const - { - return Cnt(TCP_ENDPOINT_ESTABLISHED, TCP_ENDPOINT_RESET) + - Cnt(TCP_ENDPOINT_RESET, TCP_ENDPOINT_ESTABLISHED); - } - unsigned int NumStateClosed() const - { return Cnt(TCP_ENDPOINT_CLOSED); } - unsigned int NumStateRequest() const - { - assert(Cnt(TCP_ENDPOINT_INACTIVE, TCP_ENDPOINT_SYN_SENT)==0); - return Cnt(TCP_ENDPOINT_SYN_SENT, TCP_ENDPOINT_INACTIVE); - } - unsigned int NumStateSuccRequest() const - { - return Cnt(TCP_ENDPOINT_SYN_SENT, TCP_ENDPOINT_SYN_ACK_SENT) + - Cnt(TCP_ENDPOINT_SYN_ACK_SENT, TCP_ENDPOINT_SYN_SENT); - } - unsigned int NumStateRstRequest() const - { - return Cnt(TCP_ENDPOINT_SYN_SENT, TCP_ENDPOINT_RESET) + - Cnt(TCP_ENDPOINT_RESET, TCP_ENDPOINT_SYN_SENT); - } - unsigned int NumStateInactive() const - { return Cnt(TCP_ENDPOINT_INACTIVE); } - unsigned int NumStatePartial() const; - - void PrintStats(File* file, const char* prefix); - -private: - unsigned int state_cnt[TCP_ENDPOINT_RESET+1][TCP_ENDPOINT_RESET+1]; -}; - -} // namespace zeek::analyzer::tcp diff --git a/src/analyzer/protocol/tcp/TCP_Endpoint.cc b/src/analyzer/protocol/tcp/TCP_Endpoint.cc index 98e3265337..38560235dc 100644 --- a/src/analyzer/protocol/tcp/TCP_Endpoint.cc +++ b/src/analyzer/protocol/tcp/TCP_Endpoint.cc @@ -13,6 +13,8 @@ #include "zeek/Event.h" #include "zeek/File.h" #include "zeek/Val.h" +#include "zeek/packet_analysis/Analyzer.h" +#include "zeek/packet_analysis/protocol/tcp/TCP.h" #include "zeek/analyzer/protocol/tcp/events.bif.h" @@ -65,8 +67,10 @@ void TCP_Endpoint::SetPeer(TCP_Endpoint* p) { peer = p; if ( IsOrig() ) + { // Only one Endpoint adds the initial state to the counter. - session_mgr->tcp_stats.StateEntered(state, peer->state); + packet_analysis::TCP::TCPAnalyzer::GetStats().StateEntered(state, peer->state); + } } bool TCP_Endpoint::HadGap() const @@ -144,12 +148,13 @@ void TCP_Endpoint::SetState(EndpointState new_state) prev_state = state; state = new_state; + if ( IsOrig() ) - session_mgr->tcp_stats.ChangeState(prev_state, state, - peer->state, peer->state); + packet_analysis::TCP::TCPAnalyzer::GetStats().ChangeState(prev_state, state, + peer->state, peer->state); else - session_mgr->tcp_stats.ChangeState(peer->state, peer->state, - prev_state, state); + packet_analysis::TCP::TCPAnalyzer::GetStats().ChangeState(peer->state, peer->state, + prev_state, state); } } diff --git a/src/packet_analysis/protocol/tcp/CMakeLists.txt b/src/packet_analysis/protocol/tcp/CMakeLists.txt index 8f440a70bd..d9077fa5ef 100644 --- a/src/packet_analysis/protocol/tcp/CMakeLists.txt +++ b/src/packet_analysis/protocol/tcp/CMakeLists.txt @@ -4,5 +4,5 @@ include(ZeekPlugin) include_directories(BEFORE ${CMAKE_CURRENT_SOURCE_DIR} ${CMAKE_CURRENT_BINARY_DIR}) zeek_plugin_begin(PacketAnalyzer TCP_PKT) -zeek_plugin_cc(TCP.cc TCPSessionAdapter.cc Plugin.cc) +zeek_plugin_cc(TCP.cc TCPSessionAdapter.cc Plugin.cc Stats.cc) zeek_plugin_end() diff --git a/src/packet_analysis/protocol/tcp/Stats.cc b/src/packet_analysis/protocol/tcp/Stats.cc new file mode 100644 index 0000000000..f25eeef685 --- /dev/null +++ b/src/packet_analysis/protocol/tcp/Stats.cc @@ -0,0 +1,87 @@ +// See the file "COPYING" in the main distribution directory for copyright. + +#include "zeek/packet_analysis/protocol/tcp/Stats.h" + +#include "zeek/File.h" + +#include "zeek/analyzer/protocol/tcp/events.bif.h" + +namespace zeek::packet_analysis::TCP { + +TCPStateStats::TCPStateStats() + { + for ( int i = 0; i < analyzer::tcp::TCP_ENDPOINT_RESET + 1; ++i ) + for ( int j = 0; j < analyzer::tcp::TCP_ENDPOINT_RESET + 1; ++j ) + state_cnt[i][j] = 0; + } + +void TCPStateStats::ChangeState(analyzer::tcp::EndpointState o_prev, analyzer::tcp::EndpointState o_now, + analyzer::tcp::EndpointState r_prev, analyzer::tcp::EndpointState r_now) + { + --state_cnt[o_prev][r_prev]; + ++state_cnt[o_now][r_now]; + } + +void TCPStateStats::FlipState(analyzer::tcp::EndpointState orig, analyzer::tcp::EndpointState resp) + { + --state_cnt[orig][resp]; + ++state_cnt[resp][orig]; + } + +unsigned int TCPStateStats::NumStatePartial() const + { + unsigned int sum = 0; + for ( int i = 0; i < analyzer::tcp::TCP_ENDPOINT_RESET + 1; ++i ) + { + sum += state_cnt[analyzer::tcp::TCP_ENDPOINT_PARTIAL][i]; + sum += state_cnt[i][analyzer::tcp::TCP_ENDPOINT_PARTIAL]; + } + + return sum; + } + +void TCPStateStats::PrintStats(File* file, const char* prefix) + { + file->Write(prefix); + file->Write(" Inact. Syn. SA Part. Est. Fin. Rst.\n"); + + for ( int i = 0; i < analyzer::tcp::TCP_ENDPOINT_RESET + 1; ++i ) + { + file->Write(prefix); + + switch ( i ) { +#define STATE_STRING(state, str) \ + case state: \ + file->Write(str); \ + break; + + STATE_STRING(analyzer::tcp::TCP_ENDPOINT_INACTIVE, "Inact."); + STATE_STRING(analyzer::tcp::TCP_ENDPOINT_SYN_SENT, "Syn. "); + STATE_STRING(analyzer::tcp::TCP_ENDPOINT_SYN_ACK_SENT, "SA "); + STATE_STRING(analyzer::tcp::TCP_ENDPOINT_PARTIAL, "Part. "); + STATE_STRING(analyzer::tcp::TCP_ENDPOINT_ESTABLISHED, "Est. "); + STATE_STRING(analyzer::tcp::TCP_ENDPOINT_CLOSED, "Fin. "); + STATE_STRING(analyzer::tcp::TCP_ENDPOINT_RESET, "Rst. "); + + } + + file->Write(" "); + + for ( int j = 0; j < analyzer::tcp::TCP_ENDPOINT_RESET + 1; ++j ) + { + unsigned int n = state_cnt[i][j]; + if ( n > 0 ) + { + char buf[32]; + snprintf(buf, sizeof(buf), "%-8d", state_cnt[i][j]); + file->Write(buf); + } + else + file->Write(" "); + } + + file->Write("\n"); + } + } + +} // namespace zeek::packet_analysis::TCP diff --git a/src/packet_analysis/protocol/tcp/Stats.h b/src/packet_analysis/protocol/tcp/Stats.h new file mode 100644 index 0000000000..c28d89d442 --- /dev/null +++ b/src/packet_analysis/protocol/tcp/Stats.h @@ -0,0 +1,71 @@ +// See the file "COPYING" in the main distribution directory for copyright. + +#pragma once + +#include "zeek/analyzer/protocol/tcp/TCP_Endpoint.h" + +namespace zeek::packet_analysis::TCP { + +/** + * A TCPStateStats object tracks the distribution of TCP states for + * the currently active connections. + */ +class TCPStateStats { +public: + TCPStateStats(); + ~TCPStateStats() = default; + + void ChangeState(analyzer::tcp::EndpointState o_prev, analyzer::tcp::EndpointState o_now, + analyzer::tcp::EndpointState r_prev, analyzer::tcp::EndpointState r_now); + void FlipState(analyzer::tcp::EndpointState orig, analyzer::tcp::EndpointState resp); + + void StateEntered (analyzer::tcp::EndpointState o_state, analyzer::tcp::EndpointState r_state) + { ++state_cnt[o_state][r_state]; } + void StateLeft (analyzer::tcp::EndpointState o_state, analyzer::tcp::EndpointState r_state) + { --state_cnt[o_state][r_state]; } + + unsigned int Cnt(analyzer::tcp::EndpointState state) const + { return Cnt(state, state); } + unsigned int Cnt(analyzer::tcp::EndpointState state1, analyzer::tcp::EndpointState state2) const + { return state_cnt[state1][state2]; } + + unsigned int NumStateEstablished() const + { return Cnt(analyzer::tcp::TCP_ENDPOINT_ESTABLISHED); } + unsigned int NumStateHalfClose() const + { // corresponds to S2,S3 + return Cnt(analyzer::tcp::TCP_ENDPOINT_ESTABLISHED, analyzer::tcp::TCP_ENDPOINT_CLOSED) + + Cnt(analyzer::tcp::TCP_ENDPOINT_CLOSED, analyzer::tcp::TCP_ENDPOINT_ESTABLISHED); + } + unsigned int NumStateHalfRst() const + { + return Cnt(analyzer::tcp::TCP_ENDPOINT_ESTABLISHED, analyzer::tcp::TCP_ENDPOINT_RESET) + + Cnt(analyzer::tcp::TCP_ENDPOINT_RESET, analyzer::tcp::TCP_ENDPOINT_ESTABLISHED); + } + unsigned int NumStateClosed() const + { return Cnt(analyzer::tcp::TCP_ENDPOINT_CLOSED); } + unsigned int NumStateRequest() const + { + assert(Cnt(analyzer::tcp::TCP_ENDPOINT_INACTIVE, analyzer::tcp::TCP_ENDPOINT_SYN_SENT)==0); + return Cnt(analyzer::tcp::TCP_ENDPOINT_SYN_SENT, analyzer::tcp::TCP_ENDPOINT_INACTIVE); + } + unsigned int NumStateSuccRequest() const + { + return Cnt(analyzer::tcp::TCP_ENDPOINT_SYN_SENT, analyzer::tcp::TCP_ENDPOINT_SYN_ACK_SENT) + + Cnt(analyzer::tcp::TCP_ENDPOINT_SYN_ACK_SENT, analyzer::tcp::TCP_ENDPOINT_SYN_SENT); + } + unsigned int NumStateRstRequest() const + { + return Cnt(analyzer::tcp::TCP_ENDPOINT_SYN_SENT, analyzer::tcp::TCP_ENDPOINT_RESET) + + Cnt(analyzer::tcp::TCP_ENDPOINT_RESET, analyzer::tcp::TCP_ENDPOINT_SYN_SENT); + } + unsigned int NumStateInactive() const + { return Cnt(analyzer::tcp::TCP_ENDPOINT_INACTIVE); } + unsigned int NumStatePartial() const; + + void PrintStats(File* file, const char* prefix); + +private: + unsigned int state_cnt[analyzer::tcp::TCP_ENDPOINT_RESET+1][analyzer::tcp::TCP_ENDPOINT_RESET+1]; +}; + +} // namespace zeek::packet_analysis::TCP diff --git a/src/packet_analysis/protocol/tcp/TCP.h b/src/packet_analysis/protocol/tcp/TCP.h index 1fab601e53..c2217f9953 100644 --- a/src/packet_analysis/protocol/tcp/TCP.h +++ b/src/packet_analysis/protocol/tcp/TCP.h @@ -5,6 +5,7 @@ #include "zeek/packet_analysis/Analyzer.h" #include "zeek/packet_analysis/Component.h" #include "zeek/packet_analysis/protocol/ip/IPBasedAnalyzer.h" +#include "zeek/packet_analysis/protocol/tcp/Stats.h" #include "zeek/analyzer/protocol/tcp/TCP_Flags.h" namespace zeek::analyzer::tcp { class TCP_Endpoint; } @@ -30,6 +31,12 @@ public: */ void Initialize() override; + static TCPStateStats& GetStats() + { + static TCPStateStats stats; + return stats; + } + protected: /** diff --git a/src/packet_analysis/protocol/tcp/TCPSessionAdapter.cc b/src/packet_analysis/protocol/tcp/TCPSessionAdapter.cc index df48fa836b..d9a7c69916 100644 --- a/src/packet_analysis/protocol/tcp/TCPSessionAdapter.cc +++ b/src/packet_analysis/protocol/tcp/TCPSessionAdapter.cc @@ -12,6 +12,7 @@ #include "zeek/analyzer/protocol/pia/PIA.h" #include "zeek/analyzer/protocol/stepping-stone/SteppingStone.h" #include "zeek/analyzer/protocol/conn-size/ConnSize.h" +#include "zeek/packet_analysis/protocol/tcp/TCP.h" #include "zeek/analyzer/protocol/tcp/events.bif.h" #include "zeek/analyzer/protocol/tcp/types.bif.h" @@ -536,7 +537,7 @@ void TCPSessionAdapter::FlipRoles() { Analyzer::FlipRoles(); - session_mgr->tcp_stats.FlipState(orig->state, resp->state); + TCPAnalyzer::GetStats().FlipState(orig->state, resp->state); analyzer::tcp::TCP_Endpoint* tmp_ep = resp; resp = orig; orig = tmp_ep; diff --git a/src/packet_analysis/protocol/tcp/TCPSessionAdapter.h b/src/packet_analysis/protocol/tcp/TCPSessionAdapter.h index dbdd339d3a..2c7be7a4ba 100644 --- a/src/packet_analysis/protocol/tcp/TCPSessionAdapter.h +++ b/src/packet_analysis/protocol/tcp/TCPSessionAdapter.h @@ -7,14 +7,10 @@ #include "zeek/packet_analysis/protocol/ip/SessionAdapter.h" #include "zeek/session/Manager.h" #include "zeek/analyzer/protocol/tcp/TCP_Flags.h" +#include "zeek/analyzer/protocol/tcp/TCP_Endpoint.h" namespace zeek::analyzer::pia { class PIA_TCP; } -namespace zeek::analyzer::tcp { - -class TCP_Endpoint; -class TCP_Reassembler; - -} +namespace zeek::analyzer::tcp { class TCP_Reassembler; } namespace zeek::packet_analysis::TCP { diff --git a/src/session/Manager.h b/src/session/Manager.h index 0b108adfaa..34ca6cb084 100644 --- a/src/session/Manager.h +++ b/src/session/Manager.h @@ -8,7 +8,6 @@ #include "zeek/Frag.h" #include "zeek/NetVar.h" -#include "zeek/analyzer/protocol/tcp/Stats.h" #include "zeek/telemetry/Manager.h" #include "zeek/Hash.h" #include "zeek/session/Session.h" @@ -103,9 +102,6 @@ public: unsigned int MemoryAllocation(); - // TODO: should this move somewhere else? - analyzer::tcp::TCPStateStats tcp_stats; // keeps statistics on TCP states - private: using SessionMap = std::map;