]> git.ipfire.org Git - oddments/collecty.git/commitdiff
sources: Add iptables
authorMichael Tremer <michael.tremer@ipfire.org>
Thu, 23 Oct 2025 09:37:48 +0000 (09:37 +0000)
committerMichael Tremer <michael.tremer@ipfire.org>
Thu, 23 Oct 2025 10:23:12 +0000 (10:23 +0000)
Signed-off-by: Michael Tremer <michael.tremer@ipfire.org>
Jenkinsfile
Makefile.am
configure.ac
src/daemon/sources.c
src/daemon/sources/iptables.c [new file with mode: 0644]
src/daemon/sources/iptables.h [new file with mode: 0644]

index 61434f4833f91992d66310c41ee67f513e36087f..f7faa8157031ef55464af526d7ef31f85ea797d5 100644 (file)
@@ -209,6 +209,7 @@ def installBuildDepsRedHat(distro, compier) {
                        ${compiler} \
                        \
                        libatasmart-devel \
+                       libiptc-devel \
                        lm_sensors-devel \
                        rrdtool-devel \
                        systemd-devel
@@ -231,6 +232,7 @@ def installBuildDepsArchLinux(distro, compiler) {
                        pkg-config \
                        ${compiler} \
                        \
+                       iptables \
                        libatasmart \
                        lm_sensors \
                        rrdtool \
@@ -255,6 +257,7 @@ def installBuildDepsDebian(distro, compiler, arch) {
                        ${compiler} \
                        \
                        libatasmart-dev \
+                       libiptc-dev \
                        libsensors-dev \
                        librrd-dev \
                        libsystemd-dev \
index 33ef4663e3a16f9c34f205281ed454d80a3a5dec..0bd0691a9026a7bc7cce6bc0a5d95d2071536d31 100644 (file)
@@ -161,6 +161,8 @@ dist_telemetryd_SOURCES = \
        src/daemon/sources/hostapd.h \
        src/daemon/sources/ipfrag4.c \
        src/daemon/sources/ipfrag4.h \
+       src/daemon/sources/iptables.c \
+       src/daemon/sources/iptables.h \
        src/daemon/sources/loadavg.c \
        src/daemon/sources/loadavg.h \
        src/daemon/sources/memory.c \
@@ -198,6 +200,7 @@ telemetryd_CPPFLAGS = \
 telemetryd_CFLAGS = \
        $(AM_CFLAGS) \
        $(LIBATASMART_CFLAGS) \
+       $(LIBIPTC_CFLAGS) \
        $(RRD_CFLAGS) \
        $(SYSTEMD_CFLAGS) \
        $(UDEV_CFLAGS)
@@ -205,12 +208,14 @@ telemetryd_CFLAGS = \
 telemetryd_LDFLAGS = \
        $(AM_LDFLAGS) \
        $(LIBATASMART_LDFLAGS) \
+       $(LIBIPTC_LDFLAGS) \
        $(RRD_LDFLAGS) \
        $(SYSTEMD_LDFLAGS) \
        $(UDEV_LDFLAGS)
 
 telemetryd_LDADD = \
        $(LIBATASMART_LIBS) \
+       $(LIBIPTC_LIBS) \
        $(RRD_LIBS) \
        $(SYSTEMD_LIBS) \
        $(UDEV_LIBS)
index f06c20932c65b4fb6521705b5b30c3976833b27d..2a0ae0a55e67d1ee55b347d80398655414e7df08 100644 (file)
@@ -142,6 +142,14 @@ PKG_CHECK_MODULES([RRD], [librrd])
 PKG_CHECK_MODULES([SYSTEMD], [libsystemd])
 PKG_CHECK_MODULES([UDEV], [libudev])
 
+# iptables/libiptc
+PKG_CHECK_MODULES([LIBIPTC], [libiptc],
+       [have_libiptc=yes], [have_libiptc=no])
+
+if test "x$have_libiptc" = "xyes"; then
+    AC_DEFINE([HAVE_LIBIPTC], [1], [Define if you have libiptc])
+fi
+
 # libatasmart
 PKG_CHECK_MODULES([LIBATASMART], [libatasmart >= 0.19],
        [have_libatasmart=yes], [have_libatasmart=no])
@@ -229,5 +237,6 @@ AC_MSG_RESULT([
        Generate man-pages:     ${have_manpages}
 
        libatasmart:            ${have_libatasmart}
+       libiptc:                ${have_libiptc}
        sensors:                ${have_sensors}
 ])
index 9e3c8fe653b0c9480203dd94e90168ba482c6df0..f5a33c6c7679e72aca20776870dbd0e321e20a1b 100644 (file)
 #include "sources/unbound.h"
 #include "sources/uptime.h"
 
+// iptables
+#ifdef HAVE_LIBIPTC
+# include "sources/iptables.h"
+#endif /* HAVE_LIBIPTC */
+
 // Load test sources
 #if ENABLE_TESTS
 #include "sources/test-error.h"
@@ -72,6 +77,11 @@ static const td_source_impl* source_impls[] = {
        &unbound_source,
        &uptime_source,
 
+       // iptables
+#ifdef HAVE_LIBIPTC
+       &iptables_source,
+#endif /* HAVE_LIBIPTC */
+
 #if ENABLE_TESTS
        // Tests
        &test_error_source,
diff --git a/src/daemon/sources/iptables.c b/src/daemon/sources/iptables.c
new file mode 100644 (file)
index 0000000..5ca37e5
--- /dev/null
@@ -0,0 +1,174 @@
+/*#############################################################################
+#                                                                             #
+# 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 <libiptc/libiptc.h>
+
+#include <linux/netfilter/x_tables.h>
+#include <linux/netfilter/xt_comment.h>
+
+#include "../ctx.h"
+#include "../source.h"
+#include "../string.h"
+#include "iptables.h"
+
+typedef struct xtc_handle iptc_handle_t;
+typedef struct ipt_entry iptc_rule_t;
+
+static int skip_comment(const char* comment) {
+       // Skip empty comments
+       if (!*comment)
+               return 1;
+
+       // Skip comments that contain anything else but uppercase characters, digits and _
+       for (const char* p = comment; *p; p++) {
+               // Allow uppercase characters
+               if (isupper(*p))
+                       continue;
+
+               // Allow digits
+               else if (isdigit(*p))
+                       continue;
+
+               // Allow underscore
+               else if (*p == '_')
+                       continue;
+
+               // Invalid character found, skip!
+               return 1;
+       }
+
+       return 0;
+}
+
+static int iptables_iterate_matches(td_ctx* ctx, td_source* source,    const iptc_rule_t* rule) {
+       const struct xt_comment_info* comment = NULL;
+       const struct xt_entry_match* match = NULL;
+       int r;
+
+       // Start with the first match and determine the end
+       const unsigned char* p = rule->elems;
+       const unsigned char* e = (const unsigned char*)rule + rule->target_offset;
+
+       // Walk through all matches
+       for (; p + sizeof(*match) < e; p += match->u.match_size) {
+               match = (const struct xt_entry_match*)p;
+
+               // Ensure we did not reach the target area
+               if (p + match->u.match_size > e) {
+                       DEBUG(ctx, "Match reaches the target area\n");
+                       return -EBADMSG;
+               }
+
+               // Only care about comments
+               if (!td_string_equals(match->u.user.name, "comment"))
+                       continue;
+
+               // Pointer to the comment
+               comment = (const struct xt_comment_info*)match->data;
+
+               // Skip the comment?
+               if (skip_comment(comment->comment))
+                       continue;
+
+               // Submit metrics
+               r = td_source_submit_values(source, comment->comment, VALUES(
+                       VALUE_UINT64("packets", &rule->counters.pcnt),
+                       VALUE_UINT64("bytes",   &rule->counters.bcnt)
+               ));
+               if (r < 0)
+                       return r;
+       }
+
+       return 0;
+}
+
+static int iptables_iterate_chain(td_ctx* ctx, td_source* source,
+               iptc_handle_t* handle, const char* chain) {
+       const iptc_rule_t* rule = NULL;
+       int r = 0;
+
+       // Iterate over all rules
+       for (rule = iptc_first_rule(chain, handle); rule; rule = iptc_next_rule(rule, handle)) {
+               r = iptables_iterate_matches(ctx, source, rule);
+               if (r < 0)
+                       return r;
+       }
+
+       return 0;
+}
+
+static int iptables_iterate_table(td_ctx* ctx, td_source* source, const char* table) {
+       iptc_handle_t* handle = NULL;
+       const char* chain = NULL;
+       int r;
+
+       // Create a new handle
+       handle = iptc_init(table);
+       if (!handle) {
+               ERROR(ctx, "Failed to open iptables table '%s': %s\n", iptc_strerror(errno));
+               r = -errno;
+               goto ERROR;
+       }
+
+       // Iterate through all chains
+       for (chain = iptc_first_chain(handle); chain; chain = iptc_next_chain(handle)) {
+               r = iptables_iterate_chain(ctx, source, handle, chain);
+               if (r < 0)
+                       goto ERROR;
+       }
+
+ERROR:
+       if (handle)
+               iptc_free(handle);
+
+       return r;
+
+}
+
+static int iptables_heartbeat(td_ctx* ctx, td_source* source) {
+       int r = 0;
+
+       const char* tables[] = {
+               "filter", "mangle", "nat", "raw", NULL,
+       };
+
+       // Walk through all known tables
+       for (const char** table = tables; *table; table++) {
+               r = iptables_iterate_table(ctx, source, *table);
+               if (r < 0)
+                       return r;
+       }
+
+       return 0;
+}
+
+const td_source_impl iptables_source = {
+       .name = "iptables",
+
+       // RRD Data Sources
+       .rrd_dss = {
+               { "packets", "DERIVE", 0, -1, },
+               { "bytes",   "DERIVE", 0, -1, },
+               { NULL },
+       },
+
+       // Methods
+       .heartbeat = iptables_heartbeat,
+};
diff --git a/src/daemon/sources/iptables.h b/src/daemon/sources/iptables.h
new file mode 100644 (file)
index 0000000..5854451
--- /dev/null
@@ -0,0 +1,28 @@
+/*#############################################################################
+#                                                                             #
+# 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_IPTABLES_H
+#define TELEMETRY_SOURCE_IPTABLES_H
+
+#include "../source.h"
+
+extern const td_source_impl iptables_source;
+
+#endif /* TELEMETRY_SOURCE_IPTABLES_H */