diff --git a/etc/schema.json b/etc/schema.json index df1a027d193d..532047826195 100644 --- a/etc/schema.json +++ b/etc/schema.json @@ -5214,6 +5214,32 @@ "pseudo_failed": { "type": "integer" }, + "reassembly_exception_policy": { + "type": "object", + "anyOf": [ + { + "$ref": "#/$defs/drop_flow" + }, + { + "$ref": "#/$defs/drop_packet" + }, + { + "$ref": "#/$defs/pass_flow" + }, + { + "$ref": "#/$defs/pass_packet" + }, + { + "$ref": "#/$defs/bypass" + }, + { + "$ref": "#/$defs/ignore" + }, + { + "$ref": "#/$defs/reject" + } + ] + }, "reassembly_gap": { "type": "integer" }, diff --git a/src/stream-tcp-reassemble.c b/src/stream-tcp-reassemble.c index 52118ace3818..0d5da7322af6 100644 --- a/src/stream-tcp-reassemble.c +++ b/src/stream-tcp-reassemble.c @@ -1,4 +1,4 @@ -/* Copyright (C) 2007-2022 Open Information Security Foundation +/* Copyright (C) 2007-2023 Open Information Security Foundation * * You can copy, redistribute or modify this Program under the terms of * the GNU General Public License version 2 as published by the Free @@ -1968,6 +1968,34 @@ static int StreamTcpReassembleHandleSegmentUpdateACK (ThreadVars *tv, SCReturnInt(0); } +static void StreamTcpReassembleExceptionPolicyStatsIncr( + ThreadVars *tv, TcpReassemblyThreadCtx *ra_ctx, enum ExceptionPolicy policy) +{ + switch (policy) { + case EXCEPTION_POLICY_NOT_SET: + StatsIncr(tv, ra_ctx->counter_tcp_reas_eps_ignore); + break; + case EXCEPTION_POLICY_REJECT: + StatsIncr(tv, ra_ctx->counter_tcp_reas_eps_reject); + break; + case EXCEPTION_POLICY_BYPASS_FLOW: + StatsIncr(tv, ra_ctx->counter_tcp_reas_eps_bypass); + break; + case EXCEPTION_POLICY_DROP_FLOW: + StatsIncr(tv, ra_ctx->counter_tcp_reas_eps_drop_flow); + break; + case EXCEPTION_POLICY_DROP_PACKET: + StatsIncr(tv, ra_ctx->counter_tcp_reas_eps_drop_packet); + break; + case EXCEPTION_POLICY_PASS_PACKET: + StatsIncr(tv, ra_ctx->counter_tcp_reas_eps_pass_packet); + break; + case EXCEPTION_POLICY_PASS_FLOW: + StatsIncr(tv, ra_ctx->counter_tcp_reas_eps_pass_flow); + break; + } +} + int StreamTcpReassembleHandleSegment(ThreadVars *tv, TcpReassemblyThreadCtx *ra_ctx, TcpSession *ssn, TcpStream *stream, Packet *p) { @@ -2033,6 +2061,8 @@ int StreamTcpReassembleHandleSegment(ThreadVars *tv, TcpReassemblyThreadCtx *ra_ /* failure can only be because of memcap hit, so see if this should lead to a drop */ ExceptionPolicyApply( p, stream_config.reassembly_memcap_policy, PKT_DROP_REASON_STREAM_MEMCAP); + StreamTcpReassembleExceptionPolicyStatsIncr( + tv, ra_ctx, stream_config.reassembly_memcap_policy); SCReturnInt(-1); } diff --git a/src/stream-tcp-reassemble.h b/src/stream-tcp-reassemble.h index 0f1e0fcc9434..4ed0d1bfd1e1 100644 --- a/src/stream-tcp-reassemble.h +++ b/src/stream-tcp-reassemble.h @@ -1,4 +1,4 @@ -/* Copyright (C) 2007-2010 Open Information Security Foundation +/* Copyright (C) 2007-2023 Open Information Security Foundation * * You can copy, redistribute or modify this Program under the terms of * the GNU General Public License version 2 as published by the Free @@ -63,6 +63,14 @@ typedef struct TcpReassemblyThreadCtx_ { /** TCP segments which are not being reassembled due to memcap was reached */ uint16_t counter_tcp_segment_memcap; + /** times exception policy for stream reassembly memcap was applied **/ + uint16_t counter_tcp_reas_eps_ignore; + uint16_t counter_tcp_reas_eps_reject; + uint16_t counter_tcp_reas_eps_bypass; + uint16_t counter_tcp_reas_eps_pass_flow; + uint16_t counter_tcp_reas_eps_pass_packet; + uint16_t counter_tcp_reas_eps_drop_flow; + uint16_t counter_tcp_reas_eps_drop_packet; uint16_t counter_tcp_segment_from_cache; uint16_t counter_tcp_segment_from_pool; diff --git a/src/stream-tcp.c b/src/stream-tcp.c index 4927d9201115..73901fe55df7 100644 --- a/src/stream-tcp.c +++ b/src/stream-tcp.c @@ -5795,6 +5795,20 @@ TmEcode StreamTcpThreadInit(ThreadVars *tv, void *initdata, void **data) SCReturnInt(TM_ECODE_FAILED); stt->ra_ctx->counter_tcp_segment_memcap = StatsRegisterCounter("tcp.segment_memcap_drop", tv); + stt->ra_ctx->counter_tcp_reas_eps_ignore = + StatsRegisterCounter("tcp.reassembly_exception_policy.ignore", tv); + stt->ra_ctx->counter_tcp_reas_eps_reject = + StatsRegisterCounter("tcp.reassembly_exception_policy.reject", tv); + stt->ra_ctx->counter_tcp_reas_eps_bypass = + StatsRegisterCounter("tcp.reassembly_exception_policy.bypass", tv); + stt->ra_ctx->counter_tcp_reas_eps_pass_flow = + StatsRegisterCounter("tcp.reassembly_exception_policy.pass_flow", tv); + stt->ra_ctx->counter_tcp_reas_eps_pass_packet = + StatsRegisterCounter("tcp.reassembly_exception_policy.pass_packet", tv); + stt->ra_ctx->counter_tcp_reas_eps_drop_flow = + StatsRegisterCounter("tcp.reassembly_exception_policy.drop_flow", tv); + stt->ra_ctx->counter_tcp_reas_eps_drop_packet = + StatsRegisterCounter("tcp.reassembly_exception_policy.drop_packet", tv); stt->ra_ctx->counter_tcp_segment_from_cache = StatsRegisterCounter("tcp.segment_from_cache", tv); stt->ra_ctx->counter_tcp_segment_from_pool = StatsRegisterCounter("tcp.segment_from_pool", tv);