From: Victor Julien Date: Tue, 9 Nov 2021 12:45:54 +0000 (+0100) Subject: app-layer: error counters X-Git-Tag: suricata-7.0.0-beta1~939 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=609a7eaab286e9287efb09d2dee5945e05701faf;p=thirdparty%2Fsuricata.git app-layer: error counters Per app-layer error counters for: gap, parser, internal (AppLayerResult issues), alloc --- diff --git a/src/app-layer-parser.c b/src/app-layer-parser.c index 884f1d7dea..9ba84e0e26 100644 --- a/src/app-layer-parser.c +++ b/src/app-layer-parser.c @@ -1269,6 +1269,7 @@ int AppLayerParserParse(ThreadVars *tv, AppLayerParserThreadCtx *alp_tctx, Flow AppLayerParserStreamTruncated(f->proto, alproto, f->alstate, flags); } + AppLayerIncGapErrorCounter(tv, f); goto error; } } @@ -1276,8 +1277,10 @@ int AppLayerParserParse(ThreadVars *tv, AppLayerParserThreadCtx *alp_tctx, Flow /* Get the parser state (if any) */ if (pstate == NULL) { f->alparser = pstate = AppLayerParserStateAlloc(); - if (pstate == NULL) + if (pstate == NULL) { + AppLayerIncAllocErrorCounter(tv, f); goto error; + } } SetEOFFlags(pstate, flags); @@ -1285,8 +1288,10 @@ int AppLayerParserParse(ThreadVars *tv, AppLayerParserThreadCtx *alp_tctx, Flow alstate = f->alstate; if (alstate == NULL || FlowChangeProto(f)) { f->alstate = alstate = p->StateAlloc(alstate, f->alproto_orig); - if (alstate == NULL) + if (alstate == NULL) { + AppLayerIncAllocErrorCounter(tv, f); goto error; + } SCLogDebug("alloced new app layer state %p (name %s)", alstate, AppLayerGetProtoName(f->alproto)); } else { @@ -1304,6 +1309,7 @@ int AppLayerParserParse(ThreadVars *tv, AppLayerParserThreadCtx *alp_tctx, Flow AppLayerResult res = p->Parser[direction](f, alstate, pstate, stream_slice, alp_tctx->alproto_local_storage[f->protomap][alproto]); if (res.status < 0) { + AppLayerIncParserErrorCounter(tv, f); goto error; } else if (res.status > 0) { DEBUG_VALIDATE_BUG_ON(res.consumed > input_len); @@ -1315,6 +1321,7 @@ int AppLayerParserParse(ThreadVars *tv, AppLayerParserThreadCtx *alp_tctx, Flow /* put protocol in error state on improper use of the * return codes. */ if (res.consumed > input_len || res.needed + res.consumed < input_len) { + AppLayerIncInternalErrorCounter(tv, f); goto error; } diff --git a/src/app-layer.c b/src/app-layer.c index 530d5f8b15..149936b1a1 100644 --- a/src/app-layer.c +++ b/src/app-layer.c @@ -77,11 +77,19 @@ struct AppLayerThreadCtx_ { typedef struct AppLayerCounterNames_ { char name[MAX_COUNTER_SIZE]; char tx_name[MAX_COUNTER_SIZE]; + char gap_error[MAX_COUNTER_SIZE]; + char parser_error[MAX_COUNTER_SIZE]; + char internal_error[MAX_COUNTER_SIZE]; + char alloc_error[MAX_COUNTER_SIZE]; } AppLayerCounterNames; typedef struct AppLayerCounters_ { uint16_t counter_id; uint16_t counter_tx_id; + uint16_t gap_error_id; + uint16_t parser_error_id; + uint16_t internal_error_id; + uint16_t alloc_error_id; } AppLayerCounters; /* counter names. Only used at init. */ @@ -120,6 +128,38 @@ void AppLayerIncTxCounter(ThreadVars *tv, Flow *f, uint64_t step) } } +void AppLayerIncGapErrorCounter(ThreadVars *tv, Flow *f) +{ + const uint16_t id = applayer_counters[f->protomap][f->alproto].gap_error_id; + if (likely(tv && id > 0)) { + StatsIncr(tv, id); + } +} + +void AppLayerIncAllocErrorCounter(ThreadVars *tv, Flow *f) +{ + const uint16_t id = applayer_counters[f->protomap][f->alproto].alloc_error_id; + if (likely(tv && id > 0)) { + StatsIncr(tv, id); + } +} + +void AppLayerIncParserErrorCounter(ThreadVars *tv, Flow *f) +{ + const uint16_t id = applayer_counters[f->protomap][f->alproto].parser_error_id; + if (likely(tv && id > 0)) { + StatsIncr(tv, id); + } +} + +void AppLayerIncInternalErrorCounter(ThreadVars *tv, Flow *f) +{ + const uint16_t id = applayer_counters[f->protomap][f->alproto].internal_error_id; + if (likely(tv && id > 0)) { + StatsIncr(tv, id); + } +} + /* in IDS mode protocol detection is done in reverse order: * when TCP data is ack'd. We want to flag the correct packet, * so in this case we set a flag in the flow so that the first @@ -942,6 +982,7 @@ void AppLayerSetupCounters() AppProto alproto; AppProto alprotos[ALPROTO_MAX]; const char *str = "app_layer.flow."; + const char *estr = "app_layer.error."; AppLayerProtoDetectSupportedAppProtocols(alprotos); @@ -964,6 +1005,21 @@ void AppLayerSetupCounters() snprintf(applayer_counter_names[ipproto_map][alproto].tx_name, sizeof(applayer_counter_names[ipproto_map][alproto].tx_name), "%s%s%s", tx_str, alproto_str, ipproto_suffix); + + if (ipproto == IPPROTO_TCP) { + snprintf(applayer_counter_names[ipproto_map][alproto].gap_error, + sizeof(applayer_counter_names[ipproto_map][alproto].gap_error), + "%s%s%s.gap", estr, alproto_str, ipproto_suffix); + } + snprintf(applayer_counter_names[ipproto_map][alproto].alloc_error, + sizeof(applayer_counter_names[ipproto_map][alproto].alloc_error), + "%s%s%s.alloc", estr, alproto_str, ipproto_suffix); + snprintf(applayer_counter_names[ipproto_map][alproto].parser_error, + sizeof(applayer_counter_names[ipproto_map][alproto].parser_error), + "%s%s%s.parser", estr, alproto_str, ipproto_suffix); + snprintf(applayer_counter_names[ipproto_map][alproto].internal_error, + sizeof(applayer_counter_names[ipproto_map][alproto].internal_error), + "%s%s%s.internal", estr, alproto_str, ipproto_suffix); } else { snprintf(applayer_counter_names[ipproto_map][alproto].name, sizeof(applayer_counter_names[ipproto_map][alproto].name), @@ -971,11 +1027,31 @@ void AppLayerSetupCounters() snprintf(applayer_counter_names[ipproto_map][alproto].tx_name, sizeof(applayer_counter_names[ipproto_map][alproto].tx_name), "%s%s", tx_str, alproto_str); + + if (ipproto == IPPROTO_TCP) { + snprintf(applayer_counter_names[ipproto_map][alproto].gap_error, + sizeof(applayer_counter_names[ipproto_map][alproto].gap_error), + "%s%s.gap", estr, alproto_str); + } + snprintf(applayer_counter_names[ipproto_map][alproto].alloc_error, + sizeof(applayer_counter_names[ipproto_map][alproto].alloc_error), + "%s%s.alloc", estr, alproto_str); + snprintf(applayer_counter_names[ipproto_map][alproto].parser_error, + sizeof(applayer_counter_names[ipproto_map][alproto].parser_error), + "%s%s.parser", estr, alproto_str); + snprintf(applayer_counter_names[ipproto_map][alproto].internal_error, + sizeof(applayer_counter_names[ipproto_map][alproto].internal_error), + "%s%s.internal", estr, alproto_str); } } else if (alproto == ALPROTO_FAILED) { snprintf(applayer_counter_names[ipproto_map][alproto].name, sizeof(applayer_counter_names[ipproto_map][alproto].name), "%s%s%s", str, "failed", ipproto_suffix); + if (ipproto == IPPROTO_TCP) { + snprintf(applayer_counter_names[ipproto_map][alproto].gap_error, + sizeof(applayer_counter_names[ipproto_map][alproto].gap_error), + "%sfailed%s.gap", estr, ipproto_suffix); + } } } } @@ -1000,9 +1076,25 @@ void AppLayerRegisterThreadCounters(ThreadVars *tv) applayer_counters[ipproto_map][alproto].counter_tx_id = StatsRegisterCounter(applayer_counter_names[ipproto_map][alproto].tx_name, tv); + + if (ipproto == IPPROTO_TCP) { + applayer_counters[ipproto_map][alproto].gap_error_id = StatsRegisterCounter( + applayer_counter_names[ipproto_map][alproto].gap_error, tv); + } + applayer_counters[ipproto_map][alproto].alloc_error_id = StatsRegisterCounter( + applayer_counter_names[ipproto_map][alproto].alloc_error, tv); + applayer_counters[ipproto_map][alproto].parser_error_id = StatsRegisterCounter( + applayer_counter_names[ipproto_map][alproto].parser_error, tv); + applayer_counters[ipproto_map][alproto].internal_error_id = StatsRegisterCounter( + applayer_counter_names[ipproto_map][alproto].internal_error, tv); } else if (alproto == ALPROTO_FAILED) { applayer_counters[ipproto_map][alproto].counter_id = StatsRegisterCounter(applayer_counter_names[ipproto_map][alproto].name, tv); + + if (ipproto == IPPROTO_TCP) { + applayer_counters[ipproto_map][alproto].gap_error_id = StatsRegisterCounter( + applayer_counter_names[ipproto_map][alproto].gap_error, tv); + } } } } diff --git a/src/app-layer.h b/src/app-layer.h index 76b40cf9c1..b220092a5c 100644 --- a/src/app-layer.h +++ b/src/app-layer.h @@ -146,6 +146,10 @@ void AppLayerUnittestsRegister(void); #endif void AppLayerIncTxCounter(ThreadVars *tv, Flow *f, uint64_t step); +void AppLayerIncGapErrorCounter(ThreadVars *tv, Flow *f); +void AppLayerIncAllocErrorCounter(ThreadVars *tv, Flow *f); +void AppLayerIncParserErrorCounter(ThreadVars *tv, Flow *f); +void AppLayerIncInternalErrorCounter(ThreadVars *tv, Flow *f); static inline uint8_t StreamSliceGetFlags(const StreamSlice *stream_slice) {