From a194dfbd5b1ac6b2b2db594267cf3caac7686618 Mon Sep 17 00:00:00 2001 From: Eric Leblond Date: Thu, 26 May 2016 23:11:34 +0200 Subject: [PATCH] app-layer: tx counter implementation This patch adds a transaction counter for application layers supporting it. Analysis is done after the parsing by the different application layers. This result in new data in the stats output, that looks like: ``` "app-layer": { "tx": { "dns_udp": 21433, "http": 12766, "smtp": 0, "dns_tcp": 0 } }, ``` --- src/app-layer-parser.c | 13 ++++++++++ src/app-layer.c | 56 ++++++++++++++++++++++++++++++++++-------- src/app-layer.h | 2 ++ 3 files changed, 61 insertions(+), 10 deletions(-) diff --git a/src/app-layer-parser.c b/src/app-layer-parser.c index bd1962045b..36a2792f5b 100644 --- a/src/app-layer-parser.c +++ b/src/app-layer-parser.c @@ -923,6 +923,7 @@ int AppLayerParserParse(ThreadVars *tv, AppLayerParserThreadCtx *alp_tctx, Flow AppLayerParserState *pstate = NULL; AppLayerParserProtoCtx *p = &alp_ctx.ctxs[f->protomap][alproto]; void *alstate = NULL; + uint64_t p_tx_cnt = 0; /* we don't have the parser registered for this protocol */ if (p->StateAlloc == NULL) @@ -964,6 +965,10 @@ int AppLayerParserParse(ThreadVars *tv, AppLayerParserThreadCtx *alp_tctx, Flow alstate, AppLayerGetProtoName(f->alproto)); } + if (AppLayerParserProtocolIsTxAware(f->proto, alproto)) { + p_tx_cnt = AppLayerParserGetTxCnt(f->proto, alproto, f->alstate); + } + /* invoke the recursive parser, but only on data. We may get empty msgs on EOF */ if (input_len > 0 || (flags & STREAM_EOF)) { /* invoke the parser */ @@ -1011,6 +1016,14 @@ int AppLayerParserParse(ThreadVars *tv, AppLayerParserThreadCtx *alp_tctx, Flow } } + if (AppLayerParserProtocolIsTxAware(f->proto, alproto)) { + if (likely(tv)) { + uint64_t cur_tx_cnt = AppLayerParserGetTxCnt(f->proto, alproto, f->alstate); + if (cur_tx_cnt > p_tx_cnt) { + AppLayerIncTxCounter(tv, f, cur_tx_cnt - p_tx_cnt); + } + } + } /* next, see if we can get rid of transactions now */ AppLayerParserTransactionsCleanup(f); diff --git a/src/app-layer.c b/src/app-layer.c index f88e095fff..8e1855d48e 100644 --- a/src/app-layer.c +++ b/src/app-layer.c @@ -69,7 +69,9 @@ struct AppLayerThreadCtx_ { typedef struct AppLayerCounters_ { char *name; + char *tx_name; uint16_t counter_id; + uint16_t counter_tx_id; } AppLayerCounters; AppLayerCounters applayer_counters[FLOW_PROTO_MAX][ALPROTO_MAX]; @@ -98,6 +100,13 @@ static void AppLayerIncFlowCounter(ThreadVars *tv, Flow *f) } } +void AppLayerIncTxCounter(ThreadVars *tv, Flow *f, uint64_t step) +{ + if (likely(tv)) { + StatsAddUI64(tv, applayer_counters[f->protomap][f->alproto].counter_tx_id, step); + } +} + int AppLayerHandleTCPData(ThreadVars *tv, TcpReassemblyThreadCtx *ra_ctx, Packet *p, Flow *f, TcpSession *ssn, TcpStream *stream, @@ -696,31 +705,49 @@ void AppLayerSetupCounters() for (alproto = 0; alproto < ALPROTO_MAX; alproto++) { if (alprotos[alproto] == 1) { char *str = "app_layer.flow."; + char *tx_str = "app_layer.tx."; char *alproto_str = AppLayerGetProtoName(alproto); int alproto_len = strlen(alproto_str) + 1; uint8_t ipproto_map = FlowGetProtoMapping(ipprotos[ipproto]); + size_t size; if (AppLayerParserProtoIsRegistered(ipprotos[ipproto], alproto) && AppLayerParserProtoIsRegistered(other_ipproto, alproto)) { - applayer_counters[ipproto_map][alproto].name = - SCMalloc(strlen(str) + alproto_len + strlen(ipproto_suffix)); + size = strlen(str) + alproto_len + strlen(ipproto_suffix); + applayer_counters[ipproto_map][alproto].name = SCMalloc(size); if (applayer_counters[ipproto_map][alproto].name == NULL) { return; } - snprintf(applayer_counters[ipproto_map][alproto].name, - strlen(str) + alproto_len + strlen(ipproto_suffix), - "%s%s%s", str, alproto_str, ipproto_suffix); + snprintf(applayer_counters[ipproto_map][alproto].name, size, + "%s%s%s", str, alproto_str, ipproto_suffix); + if (AppLayerParserProtocolIsTxAware(ipprotos[ipproto], alproto)) { + size = strlen(tx_str) + alproto_len + strlen(ipproto_suffix); + applayer_counters[ipproto_map][alproto].tx_name = SCMalloc(size); + if (applayer_counters[ipproto_map][alproto].tx_name == NULL) { + return; + } + snprintf(applayer_counters[ipproto_map][alproto].tx_name, size, + "%s%s%s", tx_str, alproto_str, ipproto_suffix); + } } else { - applayer_counters[ipproto_map][alproto].name = - SCMalloc(strlen(str) + alproto_len); + size = strlen(str) + alproto_len; + applayer_counters[ipproto_map][alproto].name = SCMalloc(size); if (applayer_counters[ipproto_map][alproto].name == NULL) { return; } - snprintf(applayer_counters[ipproto_map][alproto].name, - strlen(str) + alproto_len, - "%s%s", str, alproto_str); + snprintf(applayer_counters[ipproto_map][alproto].name, size, + "%s%s", str, alproto_str); + if (AppLayerParserProtocolIsTxAware(ipprotos[ipproto], alproto)) { + size = strlen(tx_str) + alproto_len; + applayer_counters[ipproto_map][alproto].tx_name = SCMalloc(size); + if (applayer_counters[ipproto_map][alproto].tx_name == NULL) { + return; + } + snprintf(applayer_counters[ipproto_map][alproto].tx_name, size, + "%s%s", tx_str, alproto_str); + } } } } @@ -742,6 +769,11 @@ void AppLayerRegisterThreadCounters(ThreadVars *tv) uint8_t ipproto_map = FlowGetProtoMapping(ipprotos[ipproto]); applayer_counters[ipproto_map][alproto].counter_id = StatsRegisterCounter(applayer_counters[ipproto_map][alproto].name, tv); + + if (AppLayerParserProtocolIsTxAware(ipprotos[ipproto], alproto)) { + applayer_counters[ipproto_map][alproto].counter_tx_id = + StatsRegisterCounter(applayer_counters[ipproto_map][alproto].tx_name, tv); + } } } } @@ -764,6 +796,10 @@ void AppLayerDeSetupCounters() applayer_counters[FlowGetProtoMapping(ipprotos[ipproto])][alproto].name = NULL; } } + if (applayer_counters[FlowGetProtoMapping(ipproto)][alproto].tx_name) { + SCFree(applayer_counters[FlowGetProtoMapping(ipproto)][alproto].tx_name); + applayer_counters[FlowGetProtoMapping(ipproto)][alproto].tx_name = NULL; + } } } } diff --git a/src/app-layer.h b/src/app-layer.h index d138cd24f0..e7e83c6292 100644 --- a/src/app-layer.h +++ b/src/app-layer.h @@ -143,4 +143,6 @@ void AppLayerRegisterGlobalCounters(void); void AppLayerUnittestsRegister(void); #endif +void AppLayerIncTxCounter(ThreadVars *tv, Flow *f, uint64_t step); + #endif -- 2.47.2