From: Michael Tremer Date: Thu, 23 Oct 2025 09:37:48 +0000 (+0000) Subject: sources: Add iptables X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=fa40a9ee364e287c873ff51dbce659314b02cf3b;p=telemetry.git sources: Add iptables Signed-off-by: Michael Tremer --- diff --git a/Jenkinsfile b/Jenkinsfile index 61434f4..f7faa81 100644 --- a/Jenkinsfile +++ b/Jenkinsfile @@ -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 \ diff --git a/Makefile.am b/Makefile.am index 33ef466..0bd0691 100644 --- a/Makefile.am +++ b/Makefile.am @@ -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) diff --git a/configure.ac b/configure.ac index f06c209..2a0ae0a 100644 --- a/configure.ac +++ b/configure.ac @@ -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} ]) diff --git a/src/daemon/sources.c b/src/daemon/sources.c index 9e3c8fe..f5a33c6 100644 --- a/src/daemon/sources.c +++ b/src/daemon/sources.c @@ -46,6 +46,11 @@ #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 index 0000000..5ca37e5 --- /dev/null +++ b/src/daemon/sources/iptables.c @@ -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 . # +# # +#############################################################################*/ + +#include + +#include +#include + +#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 index 0000000..5854451 --- /dev/null +++ b/src/daemon/sources/iptables.h @@ -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 . # +# # +#############################################################################*/ + +#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 */