]> git.ipfire.org Git - thirdparty/suricata.git/commitdiff
unix-socket: add command to get flow stats
authorEric Leblond <el@stamus-networks.com>
Thu, 25 Mar 2021 08:16:48 +0000 (09:16 +0100)
committerVictor Julien <vjulien@oisf.net>
Mon, 3 Oct 2022 09:03:09 +0000 (11:03 +0200)
Add a command to extract the accounting data from a live
flow using the unix socket. It takes the flow_id as param
and return the volume of data seen on the flow as well as
its age.

python/suricata/sc/specs.py
python/suricata/sc/suricatasc.py
src/runmode-unix-socket.c
src/runmode-unix-socket.h
src/unix-manager.c

index 9b42074169a44449c91efed31a7f5dac82683f97..99253f9a883e6b2f4820c0d4b823020c02b364bc 100644 (file)
@@ -194,4 +194,11 @@ argsd = {
             "required": 1,
         },
     ],
+    "get-flow-stats-by-id": [
+        {
+            "name": "flow_id",
+            "type": int,
+            "required": 1,
+        },
+    ],
     }
index fa0638961d4835c916159e7d07e407b07cb8eac0..d171a78f2d1bf929a52fa4d4a0ea23567c2d3a1e 100644 (file)
@@ -107,6 +107,7 @@ class SuricataSC:
                 "memcap-show",
                 "dataset-add",
                 "dataset-remove",
+                "get-flow-stats-by-id",
                 ]
         self.cmd_list = self.basic_commands + self.fn_commands
         self.sck_path = sck_path
index 24ac172179fe4b6215d9ea952180917b2c3aac91..e3180604759bb1ed05011493dadb069206f17eef 100644 (file)
@@ -34,6 +34,7 @@
 
 #include "flow-manager.h"
 #include "flow-timeout.h"
+#include "flow-hash.h"
 #include "stream-tcp.h"
 #include "stream-tcp-reassemble.h"
 #include "source-pcap-file-directory-helper.h"
@@ -1541,6 +1542,42 @@ TmEcode UnixSocketShowAllMemcap(json_t *cmd, json_t *answer, void *data)
     json_object_set_new(answer, "message", jmemcaps);
     SCReturnInt(TM_ECODE_OK);
 }
+
+TmEcode UnixSocketGetFlowStatsById(json_t *cmd, json_t *answer, void *data)
+{
+    /* Input: we need the IP tuple including VLAN/tenant and the flow ID */
+    json_t *jarg = json_object_get(cmd, "flow_id");
+    if (!json_is_integer(jarg)) {
+        SCLogInfo("error: command is not a string");
+        json_object_set_new(answer, "message", json_string("flow_id is not an integer"));
+        return TM_ECODE_FAILED;
+    }
+    int64_t flow_id = json_integer_value(jarg);
+
+    Flow *f = FlowGetExistingFlowFromFlowId(flow_id);
+    if (f == NULL) {
+        json_object_set_new(answer, "message", json_string("Not found"));
+        SCReturnInt(TM_ECODE_FAILED);
+    }
+    uint32_t tosrcpktcnt = f->tosrcpktcnt;
+    uint32_t todstpktcnt = f->todstpktcnt;
+    uint64_t tosrcbytecnt = f->tosrcbytecnt;
+    uint64_t todstbytecnt = f->todstbytecnt;
+    uint64_t age = f->lastts.tv_sec - f->startts.tv_sec;
+    FLOWLOCK_UNLOCK(f);
+
+    json_t *flow_info = json_object();
+    if (flow_info == NULL) {
+        SCReturnInt(TM_ECODE_FAILED);
+    }
+    json_object_set_new(flow_info, "pkts_toclient", json_integer(tosrcpktcnt));
+    json_object_set_new(flow_info, "pkts_toserver", json_integer(todstpktcnt));
+    json_object_set_new(flow_info, "bytes_toclient", json_integer(tosrcbytecnt));
+    json_object_set_new(flow_info, "bytes_toserver", json_integer(todstbytecnt));
+    json_object_set_new(flow_info, "age", json_integer(age));
+    json_object_set_new(answer, "message", flow_info);
+    SCReturnInt(TM_ECODE_OK);
+}
 #endif /* BUILD_UNIX_SOCKET */
 
 #ifdef BUILD_UNIX_SOCKET
index 21134eb845c9e1dfcc831d60c8422dac1b3a4b62..ded10349f084ed7210ae03320e42bdff4cfcd312 100644 (file)
@@ -46,6 +46,7 @@ TmEcode UnixSocketHostbitList(json_t *cmd, json_t* answer, void *data);
 TmEcode UnixSocketSetMemcap(json_t *cmd, json_t* answer, void *data);
 TmEcode UnixSocketShowMemcap(json_t *cmd, json_t *answer, void *data);
 TmEcode UnixSocketShowAllMemcap(json_t *cmd, json_t *answer, void *data);
+TmEcode UnixSocketGetFlowStatsById(json_t *cmd, json_t *answer, void *data);
 #endif
 
 #endif /* __RUNMODE_UNIX_SOCKET_H__ */
index a377f5aa913b6259e5816b77b83ec6b6ce8afcd9..1d408e4af2beac3953c69d0effc65f2fa4f6275b 100644 (file)
@@ -1086,6 +1086,8 @@ int UnixManagerInit(void)
 
     UnixManagerRegisterCommand("dataset-add", UnixSocketDatasetAdd, &command, UNIX_CMD_TAKE_ARGS);
     UnixManagerRegisterCommand("dataset-remove", UnixSocketDatasetRemove, &command, UNIX_CMD_TAKE_ARGS);
+    UnixManagerRegisterCommand(
+            "get-flow-stats-by-id", UnixSocketGetFlowStatsById, &command, UNIX_CMD_TAKE_ARGS);
 
     return 0;
 }