From: Eric Leblond Date: Thu, 25 Mar 2021 08:16:48 +0000 (+0100) Subject: unix-socket: add command to get flow stats X-Git-Tag: suricata-7.0.0-beta1~108 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=bb93d67dddec6f8908c67c22deab23b111e59ab1;p=thirdparty%2Fsuricata.git unix-socket: add command to get flow stats 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. --- diff --git a/python/suricata/sc/specs.py b/python/suricata/sc/specs.py index 9b42074169..99253f9a88 100644 --- a/python/suricata/sc/specs.py +++ b/python/suricata/sc/specs.py @@ -194,4 +194,11 @@ argsd = { "required": 1, }, ], + "get-flow-stats-by-id": [ + { + "name": "flow_id", + "type": int, + "required": 1, + }, + ], } diff --git a/python/suricata/sc/suricatasc.py b/python/suricata/sc/suricatasc.py index fa0638961d..d171a78f2d 100644 --- a/python/suricata/sc/suricatasc.py +++ b/python/suricata/sc/suricatasc.py @@ -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 diff --git a/src/runmode-unix-socket.c b/src/runmode-unix-socket.c index 24ac172179..e318060475 100644 --- a/src/runmode-unix-socket.c +++ b/src/runmode-unix-socket.c @@ -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 diff --git a/src/runmode-unix-socket.h b/src/runmode-unix-socket.h index 21134eb845..ded10349f0 100644 --- a/src/runmode-unix-socket.h +++ b/src/runmode-unix-socket.h @@ -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__ */ diff --git a/src/unix-manager.c b/src/unix-manager.c index a377f5aa91..1d408e4af2 100644 --- a/src/unix-manager.c +++ b/src/unix-manager.c @@ -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; }