--- /dev/null
+/*#############################################################################
+# #
+# telemetryd - The IPFire Telemetry Collection Service #
+# Copyright (C) 2025 IPFire Development Team #
+# #
+# This program is free software: you can redistribute it and/or modify #
+# it under the terms of the GNU General Public License as published by #
+# the Free Software Foundation, either version 3 of the License, or #
+# (at your option) any later version. #
+# #
+# This program is distributed in the hope that it will be useful, #
+# but WITHOUT ANY WARRANTY; without even the implied warranty of #
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the #
+# GNU General Public License for more details. #
+# #
+# You should have received a copy of the GNU General Public License #
+# along with this program. If not, see <http://www.gnu.org/licenses/>. #
+# #
+#############################################################################*/
+
+#include <errno.h>
+
+#include <systemd/sd-json.h>
+
+#include "../command.h"
+#include "../ctx.h"
+#include "../source.h"
+#include "../string.h"
+#include "suricata.h"
+
+static int suricata_check_result(td_ctx* ctx, sd_json_variant* json) {
+ sd_json_variant* ret = NULL;
+ const char* value = NULL;
+
+ // Fetch the value of "return"
+ ret = sd_json_variant_by_key(json, "return");
+ if (!ret) {
+ ERROR(ctx, "JSON response does not have a \"return\" field\n");
+ return -EBADMSG;
+ }
+
+ // Fetch the value of "return"
+ value = sd_json_variant_string(ret);
+ if (!value)
+ return -EBADMSG;
+
+ // Check if the value says "OK"
+ if (!td_string_equals(value, "OK"))
+ return -EBADMSG;
+
+ return 0;
+}
+
+static int suricata_parse_uptime(td_ctx* ctx, td_metrics* metrics, sd_json_variant* json) {
+ sd_json_variant* uptime = NULL;
+ uint64_t value = 0;
+
+ // Fetch the uptime
+ uptime = sd_json_variant_by_key(json, "uptime");
+ if (!uptime)
+ return 0;
+
+ // Fetch the value
+ value = sd_json_variant_unsigned(uptime);
+
+ // Submit the value
+ return td_metrics_push_uint64(metrics, "uptime", value);
+}
+
+static int suricata_parse_decoder(td_ctx* ctx, td_metrics* metrics, sd_json_variant* json) {
+ sd_json_variant* decoder = NULL;
+ sd_json_variant* bytes = NULL;
+ sd_json_variant* pkts = NULL;
+ uint64_t value = 0;
+ int r;
+
+ // Fetch the decoder object
+ decoder = sd_json_variant_by_key(json, "decoder");
+ if (!decoder)
+ return 0;
+
+ // Fetch pkts
+ pkts = sd_json_variant_by_key(decoder, "pkts");
+ if (pkts) {
+ // Fetch the value
+ value = sd_json_variant_unsigned(pkts);
+
+ // Submit value
+ r = td_metrics_push_uint64(metrics, "decoder_pkts", value);
+ if (r < 0)
+ return r;
+ }
+
+ // Fetch bytes
+ bytes = sd_json_variant_by_key(decoder, "bytes");
+ if (bytes) {
+ // Fetch the value
+ value = sd_json_variant_unsigned(bytes);
+
+ // Submit value
+ r = td_metrics_push_uint64(metrics, "decoder_bytes", value);
+ if (r < 0)
+ return r;
+ }
+
+ return 0;
+}
+
+
+static int suricata_parse_message(td_ctx* ctx, td_metrics* metrics, sd_json_variant* json) {
+ sd_json_variant* msg = NULL;
+ int r;
+
+ // Fetch the message
+ msg = sd_json_variant_by_key(json, "message");
+ if (!msg) {
+ ERROR(ctx, "JSON response does not have a \"message\" field\n");
+ return -EBADMSG;
+ }
+
+ // Parse the uptime
+ r = suricata_parse_uptime(ctx, metrics, msg);
+ if (r < 0)
+ return r;
+
+ // Parse the decoder
+ r = suricata_parse_decoder(ctx, metrics, msg);
+ if (r < 0)
+ return r;
+
+ return 0;
+}
+
+static int suricata_on_success(td_ctx* ctx, int rc, td_file* stdout, void* data) {
+ sd_json_variant* json = NULL;
+ td_metrics* metrics = NULL;
+ td_source* source = data;
+ int r;
+
+ // Parse the output as JSON
+ r = td_file_parse_json(stdout, &json, 0);
+ if (r < 0)
+ goto ERROR;
+
+ // Check the result
+ r = suricata_check_result(ctx, json);
+ if (r < 0)
+ goto ERROR;
+
+ // Create a new metrics object
+ r = td_source_create_metrics(source, &metrics, NULL);
+ if (r < 0)
+ goto ERROR;
+
+ // Parse the message
+ r = suricata_parse_message(ctx, metrics, json);
+ if (r < 0)
+ goto ERROR;
+
+ // Submit all collected metrics
+ r = td_source_submit_metrics(source, metrics);
+
+ERROR:
+ if (json)
+ sd_json_variant_unref(json);
+ if (metrics)
+ td_metrics_unref(metrics);
+
+ return r;
+}
+
+static int suricata_heartbeat(td_ctx* ctx, td_source* source) {
+ td_command* command = NULL;
+ int r;
+
+ // Run suricatasc to fetch all counters
+ const char* argv[] = { "suricatasc", "--command=dump-counters", NULL };
+
+ // Create a new command
+ r = td_source_create_command(source, &command);
+ if (r < 0)
+ goto ERROR;
+
+ // Register the success callback
+ td_command_on_success(command, suricata_on_success, source);
+
+ // Execute the command
+ r = td_command_execute(command, argv);
+
+ERROR:
+ if (command)
+ td_command_unref(command);
+
+ return r;
+}
+
+const td_source_impl suricata_source = {
+ .name = "suricata",
+
+ // RRD Data Sources
+ .rrd_dss = {
+ { "uptime", "COUNTER", 0, -1, },
+
+ // Decoder
+ { "decoder_pkts", "DERIVE", 0, -1, },
+ { "decoder_bytes", "DERIVE", 0, -1, },
+
+ { NULL },
+ },
+
+ // Methods
+ .heartbeat = suricata_heartbeat,
+};
--- /dev/null
+/*#############################################################################
+# #
+# telemetryd - The IPFire Telemetry Collection Service #
+# Copyright (C) 2025 IPFire Development Team #
+# #
+# This program is free software: you can redistribute it and/or modify #
+# it under the terms of the GNU General Public License as published by #
+# the Free Software Foundation, either version 3 of the License, or #
+# (at your option) any later version. #
+# #
+# This program is distributed in the hope that it will be useful, #
+# but WITHOUT ANY WARRANTY; without even the implied warranty of #
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the #
+# GNU General Public License for more details. #
+# #
+# You should have received a copy of the GNU General Public License #
+# along with this program. If not, see <http://www.gnu.org/licenses/>. #
+# #
+#############################################################################*/
+
+#ifndef TELEMETRY_SOURCE_SURICATA_H
+#define TELEMETRY_SOURCE_SURICATA_H
+
+#include "../source.h"
+
+extern const td_source_impl suricata_source;
+
+#endif /* TELEMETRY_SOURCE_SURICATA_H */