diff --git a/etc/schema.json b/etc/schema.json index 28e26df5eadb..15f148e4f6a2 100644 --- a/etc/schema.json +++ b/etc/schema.json @@ -5349,6 +5349,11 @@ "midstream_pickups": { "type": "integer" }, + "midstream_exception_policy": { + "description": + "How many times midstream exception policy was applied, and which one", + "$ref": "#/$defs/exceptionPolicy" + }, "no_flow": { "type": "integer" }, diff --git a/src/stream-tcp.c b/src/stream-tcp.c index dca1811de17e..df2f7d26a07a 100644 --- a/src/stream-tcp.c +++ b/src/stream-tcp.c @@ -142,6 +142,58 @@ ExceptionPolicyStatsSetts stream_reassembly_memcap_eps_stats = { }; // clang-format on +/* Settings order as in the enum */ +// clang-format off +ExceptionPolicyStatsSetts stream_midstream_enabled_eps_stats = { + .valid_settings_ids = { + /* EXCEPTION_POLICY_NOT_SET */ false, + /* EXCEPTION_POLICY_AUTO */ false, + /* EXCEPTION_POLICY_PASS_PACKET */ false, + /* EXCEPTION_POLICY_PASS_FLOW */ true, + /* EXCEPTION_POLICY_BYPASS_FLOW */ false, + /* EXCEPTION_POLICY_DROP_PACKET */ false, + /* EXCEPTION_POLICY_DROP_FLOW */ false, + /* EXCEPTION_POLICY_REJECT */ false, + }, + .valid_settings_ips = { + /* EXCEPTION_POLICY_NOT_SET */ false, + /* EXCEPTION_POLICY_AUTO */ false, + /* EXCEPTION_POLICY_PASS_PACKET */ false, + /* EXCEPTION_POLICY_PASS_FLOW */ true, + /* EXCEPTION_POLICY_BYPASS_FLOW */ false, + /* EXCEPTION_POLICY_DROP_PACKET */ false, + /* EXCEPTION_POLICY_DROP_FLOW */ false, + /* EXCEPTION_POLICY_REJECT */ false, + }, +}; +// clang-format on + +/* Settings order as in the enum */ +// clang-format off +ExceptionPolicyStatsSetts stream_midstream_disabled_eps_stats = { + .valid_settings_ids = { + /* EXCEPTION_POLICY_NOT_SET */ false, + /* EXCEPTION_POLICY_AUTO */ false, + /* EXCEPTION_POLICY_PASS_PACKET */ false, + /* EXCEPTION_POLICY_PASS_FLOW */ true, + /* EXCEPTION_POLICY_BYPASS_FLOW */ true, + /* EXCEPTION_POLICY_DROP_PACKET */ false, + /* EXCEPTION_POLICY_DROP_FLOW */ false, + /* EXCEPTION_POLICY_REJECT */ true, + }, + .valid_settings_ips = { + /* EXCEPTION_POLICY_NOT_SET */ false, + /* EXCEPTION_POLICY_AUTO */ false, + /* EXCEPTION_POLICY_PASS_PACKET */ false, + /* EXCEPTION_POLICY_PASS_FLOW */ true, + /* EXCEPTION_POLICY_BYPASS_FLOW */ true, + /* EXCEPTION_POLICY_DROP_PACKET */ false, + /* EXCEPTION_POLICY_DROP_FLOW */ true, + /* EXCEPTION_POLICY_REJECT */ true, + }, +}; +// clang-format on + static int StreamTcpHandleFin(ThreadVars *tv, StreamTcpThread *, TcpSession *, Packet *); void StreamTcpReturnStreamSegments (TcpStream *); void StreamTcpInitConfig(bool); @@ -982,6 +1034,29 @@ static inline void StreamTcpCloseSsnWithReset(Packet *p, TcpSession *ssn) "TCP_CLOSED", ssn, StreamTcpStateAsString(ssn->state)); } +static bool IsMidstreamExceptionPolicyStatsValid(enum ExceptionPolicy policy) +{ + if (EngineModeIsIPS()) { + if (stream_config.midstream) { + return stream_midstream_enabled_eps_stats.valid_settings_ips[policy]; + } + return stream_midstream_disabled_eps_stats.valid_settings_ips[policy]; + } + if (stream_config.midstream) { + return stream_midstream_enabled_eps_stats.valid_settings_ids[policy]; + } + return stream_midstream_disabled_eps_stats.valid_settings_ids[policy]; +} + +static void StreamTcpMidstreamExceptionPolicyStatsIncr( + ThreadVars *tv, StreamTcpThread *stt, enum ExceptionPolicy policy) +{ + const uint16_t id = stt->counter_tcp_midstream_eps.eps_id[policy]; + if (likely(tv && id > 0)) { + StatsIncr(tv, id); + } +} + static int StreamTcpPacketIsRetransmission(TcpStream *stream, Packet *p) { if (p->payload_len == 0) @@ -1035,6 +1110,7 @@ static int StreamTcpPacketStateNone( } else if (p->tcph->th_flags & TH_FIN) { /* Drop reason will only be used if midstream policy is set to fail closed */ ExceptionPolicyApply(p, stream_config.midstream_policy, PKT_DROP_REASON_STREAM_MIDSTREAM); + StreamTcpMidstreamExceptionPolicyStatsIncr(tv, stt, stream_config.midstream_policy); if (!stream_config.midstream || p->payload_len == 0) { StreamTcpSetEvent(p, STREAM_FIN_BUT_NO_SESSION); @@ -1131,6 +1207,7 @@ static int StreamTcpPacketStateNone( } else if ((p->tcph->th_flags & (TH_SYN | TH_ACK)) == (TH_SYN | TH_ACK)) { /* Drop reason will only be used if midstream policy is set to fail closed */ ExceptionPolicyApply(p, stream_config.midstream_policy, PKT_DROP_REASON_STREAM_MIDSTREAM); + StreamTcpMidstreamExceptionPolicyStatsIncr(tv, stt, stream_config.midstream_policy); if (!stream_config.midstream && !stream_config.async_oneside) { SCLogDebug("Midstream not enabled, so won't pick up a session"); @@ -1303,6 +1380,7 @@ static int StreamTcpPacketStateNone( } else if (p->tcph->th_flags & TH_ACK) { /* Drop reason will only be used if midstream policy is set to fail closed */ ExceptionPolicyApply(p, stream_config.midstream_policy, PKT_DROP_REASON_STREAM_MIDSTREAM); + StreamTcpMidstreamExceptionPolicyStatsIncr(tv, stt, stream_config.midstream_policy); if (!stream_config.midstream) { SCLogDebug("Midstream not enabled, so won't pick up a session"); @@ -5850,6 +5928,16 @@ TmEcode StreamTcpThreadInit(ThreadVars *tv, void *initdata, void **data) stt->counter_tcp_pseudo_failed = StatsRegisterCounter("tcp.pseudo_failed", tv); stt->counter_tcp_invalid_checksum = StatsRegisterCounter("tcp.invalid_checksum", tv); stt->counter_tcp_midstream_pickups = StatsRegisterCounter("tcp.midstream_pickups", tv); + if (stream_config.midstream) { + ExceptionPolicySetStatsCounters(tv, &stt->counter_tcp_midstream_eps, + &stream_midstream_enabled_eps_stats, stream_config.midstream_policy, + "tcp.midstream_exception_policy.", IsMidstreamExceptionPolicyStatsValid); + } else { + ExceptionPolicySetStatsCounters(tv, &stt->counter_tcp_midstream_eps, + &stream_midstream_disabled_eps_stats, stream_config.midstream_policy, + "tcp.midstream_exception_policy.", IsMidstreamExceptionPolicyStatsValid); + } + stt->counter_tcp_wrong_thread = StatsRegisterCounter("tcp.pkt_on_wrong_thread", tv); stt->counter_tcp_ack_unseen_data = StatsRegisterCounter("tcp.ack_unseen_data", tv); diff --git a/src/stream-tcp.h b/src/stream-tcp.h index 8bdb4f7a3a2e..4f5bb35e7711 100644 --- a/src/stream-tcp.h +++ b/src/stream-tcp.h @@ -96,6 +96,8 @@ typedef struct StreamTcpThread_ { uint16_t counter_tcp_invalid_checksum; /** midstream pickups */ uint16_t counter_tcp_midstream_pickups; + /** exception policy stats */ + ExceptionPolicyCounters counter_tcp_midstream_eps; /** wrong thread */ uint16_t counter_tcp_wrong_thread; /** ack for unseen data */