]> git.ipfire.org Git - thirdparty/suricata.git/commitdiff
app-layer: tx counter implementation 2292/head
authorEric Leblond <eric@regit.org>
Thu, 26 May 2016 21:11:34 +0000 (23:11 +0200)
committerGiuseppe Longo <glongo@stamus-networks.com>
Tue, 27 Sep 2016 07:20:56 +0000 (09:20 +0200)
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
src/app-layer.c
src/app-layer.h

index bd1962045b468fac987a3fc4ea34d611e5c42587..36a2792f5b2b2b474eb44585ab94f216b1bf2ec2 100644 (file)
@@ -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);
 
index f88e095fff04bece91be56fb138c8827ae3aeba6..8e1855d48ec6b1dfd56cd9a409ad124017f5dc07 100644 (file)
@@ -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;
+            }
         }
     }
 }
index d138cd24f066f2f0d6c8b2e8dbd247dc9f35a623..e7e83c62923066bdaecf43904ee19accbd6afaee 100644 (file)
@@ -143,4 +143,6 @@ void AppLayerRegisterGlobalCounters(void);
 void AppLayerUnittestsRegister(void);
 #endif
 
+void AppLayerIncTxCounter(ThreadVars *tv, Flow *f, uint64_t step);
+
 #endif