app-layer: error counters

Per app-layer error counters for:
gap, parser, internal (AppLayerResult issues), alloc
pull/6924/head
Victor Julien 4 years ago committed by Victor Julien
parent ae0b8d92da
commit 609a7eaab2

@ -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;
}

@ -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);
}
}
}
}

@ -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)
{

Loading…
Cancel
Save