]> git.ipfire.org Git - thirdparty/systemd.git/commitdiff
firewall-util: remove iptables backend
authorYu Watanabe <watanabe.yu+github@gmail.com>
Sun, 17 Aug 2025 18:37:07 +0000 (03:37 +0900)
committerYu Watanabe <watanabe.yu+github@gmail.com>
Fri, 19 Sep 2025 06:33:15 +0000 (15:33 +0900)
As already announced by 5c68c51045c27d77b7afc211df7304a958d8cf24,
let's remove iptables backend of firewall-util through libiptc.

meson.build
meson_options.txt
src/basic/build.c
src/core/kmod-setup.c
src/shared/firewall-util-iptables.c [deleted file]
src/shared/firewall-util-private.h
src/shared/firewall-util.c
src/shared/meson.build
src/test/test-firewall-util.c

index dddb7766159405d2d6cf4c3aae032f6fe9f12dab..52850311b553279793bf5f0144596287fd17a7c3 100644 (file)
@@ -1305,11 +1305,6 @@ endif
 conf.set10('HAVE_LIBIDN', not have and libidn.found())
 conf.set10('HAVE_LIBIDN2', have)
 
-libiptc = dependency('libiptc',
-                     required : get_option('libiptc'))
-conf.set10('HAVE_LIBIPTC', libiptc.found())
-libiptc_cflags = libiptc.partial_dependency(includes: true, compile_args: true)
-
 libqrencode = dependency('libqrencode',
                          version : '>= 3',
                          required : get_option('qrencode'))
@@ -3052,7 +3047,6 @@ foreach tuple : [
         ['libfido2'],
         ['libidn'],
         ['libidn2'],
-        ['libiptc'],
         ['microhttpd'],
         ['openssl'],
         ['p11kit'],
index cd4b556283d66f28d92749d86cd68e1e705a04e1..464f388e22d9da7cb0b9406c80ca999c92c3f981 100644 (file)
@@ -432,7 +432,7 @@ option('libidn2', type : 'feature', deprecated : { 'true' : 'enabled', 'false' :
        description : 'libidn2 support')
 option('libidn', type : 'feature', deprecated : { 'true' : 'enabled', 'false' : 'disabled' },
        description : 'libidn support')
-option('libiptc', type : 'feature', deprecated : { 'true' : 'enabled', 'false' : 'disabled' },
+option('libiptc', type : 'feature', deprecated : true,
        description : 'libiptc support')
 option('qrencode', type : 'feature', deprecated : { 'true' : 'enabled', 'false' : 'disabled' },
        description : 'libqrencode support')
index ad9d3b1c4bdca29910f4527da7f2e17cd5a06681..b9341b184d69b4e51ae0c531fb75929513b31daf 100644 (file)
@@ -126,12 +126,6 @@ const char* const systemd_features =
         " -IDN"
 #endif
 
-#if HAVE_LIBIPTC
-        " +IPTC"
-#else
-        " -IPTC"
-#endif
-
 #if HAVE_KMOD
         " +KMOD"
 #else
index 12ce5a86e4a84bed51fe84601e6460b1c7858f8b..1f694b29d943eb940739ceb6491289e9570a5735 100644 (file)
@@ -115,10 +115,6 @@ int kmod_setup(void) {
                 /* This should never be a module */
                 { "unix",                       "/proc/net/unix",            true,  true,  NULL               },
 
-#if HAVE_LIBIPTC
-                /* netfilter is needed by networkd, nspawn among others, and cannot be autoloaded */
-                { "ip_tables",                  "/proc/net/ip_tables_names", false, false, NULL               },
-#endif
                 /* virtio_rng would be loaded by udev later, but real entropy might be needed very early */
                 { "virtio_rng",                 NULL,                        false, false, has_virtio_rng     },
 
diff --git a/src/shared/firewall-util-iptables.c b/src/shared/firewall-util-iptables.c
deleted file mode 100644 (file)
index 1e5b59f..0000000
+++ /dev/null
@@ -1,383 +0,0 @@
-/* SPDX-License-Identifier: LGPL-2.1-or-later */
-
-#include <endian.h>
-#include <libiptc/libiptc.h>
-#include <linux/netfilter/nf_nat.h>
-#include <linux/netfilter/xt_addrtype.h>
-#include <linux/netfilter_ipv4/ip_tables.h>
-#include <string.h>
-
-#include "alloc-util.h"
-#include "dlfcn-util.h"
-#include "firewall-util-private.h"
-#include "in-addr-util.h"
-#include "log.h"
-#include "socket-util.h"
-
-static DLSYM_PROTOTYPE(iptc_check_entry) = NULL;
-static DLSYM_PROTOTYPE(iptc_commit) = NULL;
-static DLSYM_PROTOTYPE(iptc_delete_entry) = NULL;
-static DLSYM_PROTOTYPE(iptc_free) = NULL;
-static DLSYM_PROTOTYPE(iptc_init) = NULL;
-static DLSYM_PROTOTYPE(iptc_insert_entry) = NULL;
-static DLSYM_PROTOTYPE(iptc_strerror) = NULL;
-
-static void *iptc_dl = NULL;
-
-DEFINE_TRIVIAL_CLEANUP_FUNC_FULL(struct xtc_handle*, sym_iptc_free, NULL);
-
-static int entry_fill_basics(
-                struct ipt_entry *entry,
-                int protocol,
-                const char *in_interface,
-                const union in_addr_union *source,
-                unsigned source_prefixlen,
-                const char *out_interface,
-                const union in_addr_union *destination,
-                unsigned destination_prefixlen) {
-
-        assert(entry);
-
-        if (out_interface && !ifname_valid(out_interface))
-                return -EINVAL;
-        if (in_interface && !ifname_valid(in_interface))
-                return -EINVAL;
-
-        entry->ip.proto = protocol;
-
-        if (in_interface) {
-                size_t l;
-
-                l = strlen(in_interface);
-                assert(l < sizeof entry->ip.iniface);
-                assert(l < sizeof entry->ip.iniface_mask);
-
-                strcpy(entry->ip.iniface, in_interface);
-                memset(entry->ip.iniface_mask, 0xFF, l + 1);
-        }
-        if (source) {
-                entry->ip.src = source->in;
-                in4_addr_prefixlen_to_netmask(&entry->ip.smsk, source_prefixlen);
-        }
-
-        if (out_interface) {
-                size_t l = strlen(out_interface);
-                assert(l < sizeof entry->ip.outiface);
-                assert(l < sizeof entry->ip.outiface_mask);
-
-                strcpy(entry->ip.outiface, out_interface);
-                memset(entry->ip.outiface_mask, 0xFF, l + 1);
-        }
-        if (destination) {
-                entry->ip.dst = destination->in;
-                in4_addr_prefixlen_to_netmask(&entry->ip.dmsk, destination_prefixlen);
-        }
-
-        return 0;
-}
-
-int fw_iptables_add_masquerade(
-                bool add,
-                int af,
-                const union in_addr_union *source,
-                unsigned source_prefixlen) {
-
-        static const xt_chainlabel chain = "POSTROUTING";
-        _cleanup_(sym_iptc_freep) struct xtc_handle *h = NULL;
-        struct ipt_entry *entry, *mask;
-        struct ipt_entry_target *t;
-        size_t sz;
-        struct nf_nat_ipv4_multi_range_compat *mr;
-        int r, protocol = 0;
-        const char *out_interface = NULL;
-        const union in_addr_union *destination = NULL;
-        unsigned destination_prefixlen = 0;
-
-        if (af != AF_INET)
-                return -EOPNOTSUPP;
-
-        if (!source || source_prefixlen == 0)
-                return -EINVAL;
-
-        r = fw_iptables_init_nat(&h);
-        if (r < 0)
-                return r;
-
-        sz = XT_ALIGN(sizeof(struct ipt_entry)) +
-             XT_ALIGN(sizeof(struct ipt_entry_target)) +
-             XT_ALIGN(sizeof(struct nf_nat_ipv4_multi_range_compat));
-
-        /* Put together the entry we want to add or remove */
-        entry = alloca0(sz);
-        entry->next_offset = sz;
-        entry->target_offset = XT_ALIGN(sizeof(struct ipt_entry));
-        r = entry_fill_basics(entry, protocol, NULL, source, source_prefixlen, out_interface, destination, destination_prefixlen);
-        if (r < 0)
-                return r;
-
-        /* Fill in target part */
-        t = ipt_get_target(entry);
-        t->u.target_size =
-                XT_ALIGN(sizeof(struct ipt_entry_target)) +
-                XT_ALIGN(sizeof(struct nf_nat_ipv4_multi_range_compat));
-        strncpy(t->u.user.name, "MASQUERADE", sizeof(t->u.user.name));
-        mr = (struct nf_nat_ipv4_multi_range_compat*) t->data;
-        mr->rangesize = 1;
-
-        /* Create a search mask entry */
-        mask = alloca_safe(sz);
-        memset(mask, 0xFF, sz);
-
-        if (add) {
-                if (sym_iptc_check_entry(chain, entry, (unsigned char*) mask, h))
-                        return 0;
-                if (errno != ENOENT) /* if other error than not existing yet, fail */
-                        return -errno;
-
-                if (!sym_iptc_insert_entry(chain, entry, 0, h))
-                        return -errno;
-        } else {
-                if (!sym_iptc_delete_entry(chain, entry, (unsigned char*) mask, h)) {
-                        if (errno == ENOENT) /* if it's already gone, all is good! */
-                                return 0;
-
-                        return -errno;
-                }
-        }
-
-        if (!sym_iptc_commit(h))
-                return -errno;
-
-        return 0;
-}
-
-int fw_iptables_add_local_dnat(
-                bool add,
-                int af,
-                int protocol,
-                uint16_t local_port,
-                const union in_addr_union *remote,
-                uint16_t remote_port,
-                const union in_addr_union *previous_remote) {
-
-        static const xt_chainlabel chain_pre = "PREROUTING", chain_output = "OUTPUT";
-        _cleanup_(sym_iptc_freep) struct xtc_handle *h = NULL;
-        struct ipt_entry *entry, *mask;
-        struct ipt_entry_target *t;
-        struct ipt_entry_match *m;
-        struct xt_addrtype_info_v1 *at;
-        struct nf_nat_ipv4_multi_range_compat *mr;
-        size_t sz, msz;
-        int r;
-        const char *in_interface = NULL;
-        const union in_addr_union *source = NULL;
-        unsigned source_prefixlen = 0;
-        const union in_addr_union *destination = NULL;
-        unsigned destination_prefixlen = 0;
-
-        assert(add || !previous_remote);
-
-        if (af != AF_INET)
-                return -EOPNOTSUPP;
-
-        if (!IN_SET(protocol, IPPROTO_TCP, IPPROTO_UDP))
-                return -EOPNOTSUPP;
-
-        if (local_port <= 0)
-                return -EINVAL;
-
-        if (remote_port <= 0)
-                return -EINVAL;
-
-        r = fw_iptables_init_nat(&h);
-        if (r < 0)
-                return r;
-
-        sz = XT_ALIGN(sizeof(struct ipt_entry)) +
-             XT_ALIGN(sizeof(struct ipt_entry_match)) +
-             XT_ALIGN(sizeof(struct xt_addrtype_info_v1)) +
-             XT_ALIGN(sizeof(struct ipt_entry_target)) +
-             XT_ALIGN(sizeof(struct nf_nat_ipv4_multi_range_compat));
-
-        if (protocol == IPPROTO_TCP)
-                msz = XT_ALIGN(sizeof(struct ipt_entry_match)) +
-                      XT_ALIGN(sizeof(struct xt_tcp));
-        else
-                msz = XT_ALIGN(sizeof(struct ipt_entry_match)) +
-                      XT_ALIGN(sizeof(struct xt_udp));
-
-        sz += msz;
-
-        /* Fill in basic part */
-        entry = alloca0(sz);
-        entry->next_offset = sz;
-        entry->target_offset =
-                XT_ALIGN(sizeof(struct ipt_entry)) +
-                XT_ALIGN(sizeof(struct ipt_entry_match)) +
-                XT_ALIGN(sizeof(struct xt_addrtype_info_v1)) +
-                msz;
-        r = entry_fill_basics(entry, protocol, in_interface, source, source_prefixlen, NULL, destination, destination_prefixlen);
-        if (r < 0)
-                return r;
-
-        /* Fill in first match */
-        m = (struct ipt_entry_match*) ((uint8_t*) entry + XT_ALIGN(sizeof(struct ipt_entry)));
-        m->u.match_size = msz;
-        if (protocol == IPPROTO_TCP) {
-                struct xt_tcp *tcp;
-
-                strncpy(m->u.user.name, "tcp", sizeof(m->u.user.name));
-                tcp = (struct xt_tcp*) m->data;
-                tcp->dpts[0] = tcp->dpts[1] = local_port;
-                tcp->spts[0] = 0;
-                tcp->spts[1] = 0xFFFF;
-
-        } else {
-                struct xt_udp *udp;
-
-                strncpy(m->u.user.name, "udp", sizeof(m->u.user.name));
-                udp = (struct xt_udp*) m->data;
-                udp->dpts[0] = udp->dpts[1] = local_port;
-                udp->spts[0] = 0;
-                udp->spts[1] = 0xFFFF;
-        }
-
-        /* Fill in second match */
-        m = (struct ipt_entry_match*) ((uint8_t*) entry + XT_ALIGN(sizeof(struct ipt_entry)) + msz);
-        m->u.match_size =
-                XT_ALIGN(sizeof(struct ipt_entry_match)) +
-                XT_ALIGN(sizeof(struct xt_addrtype_info_v1));
-        strncpy(m->u.user.name, "addrtype", sizeof(m->u.user.name));
-        m->u.user.revision = 1;
-        at = (struct xt_addrtype_info_v1*) m->data;
-        at->dest = XT_ADDRTYPE_LOCAL;
-
-        /* Fill in target part */
-        t = ipt_get_target(entry);
-        t->u.target_size =
-                XT_ALIGN(sizeof(struct ipt_entry_target)) +
-                XT_ALIGN(sizeof(struct nf_nat_ipv4_multi_range_compat));
-        strncpy(t->u.user.name, "DNAT", sizeof(t->u.user.name));
-        mr = (struct nf_nat_ipv4_multi_range_compat*) t->data;
-        mr->rangesize = 1;
-        mr->range[0].flags = NF_NAT_RANGE_PROTO_SPECIFIED|NF_NAT_RANGE_MAP_IPS;
-        mr->range[0].min_ip = mr->range[0].max_ip = remote->in.s_addr;
-        if (protocol == IPPROTO_TCP)
-                mr->range[0].min.tcp.port = mr->range[0].max.tcp.port = htobe16(remote_port);
-        else
-                mr->range[0].min.udp.port = mr->range[0].max.udp.port = htobe16(remote_port);
-
-        mask = alloca0(sz);
-        memset(mask, 0xFF, sz);
-
-        if (add) {
-                /* Add the PREROUTING rule, if it is missing so far */
-                if (!sym_iptc_check_entry(chain_pre, entry, (unsigned char*) mask, h)) {
-                        if (errno != ENOENT)
-                                return -EINVAL;
-
-                        if (!sym_iptc_insert_entry(chain_pre, entry, 0, h))
-                                return -errno;
-                }
-
-                /* If a previous remote is set, remove its entry */
-                if (previous_remote && previous_remote->in.s_addr != remote->in.s_addr) {
-                        mr->range[0].min_ip = mr->range[0].max_ip = previous_remote->in.s_addr;
-
-                        if (!sym_iptc_delete_entry(chain_pre, entry, (unsigned char*) mask, h)) {
-                                if (errno != ENOENT)
-                                        return -errno;
-                        }
-
-                        mr->range[0].min_ip = mr->range[0].max_ip = remote->in.s_addr;
-                }
-
-                /* Add the OUTPUT rule, if it is missing so far */
-                if (!in_interface) {
-
-                        /* Don't apply onto loopback addresses */
-                        if (!destination) {
-                                entry->ip.dst.s_addr = htobe32(0x7F000000);
-                                entry->ip.dmsk.s_addr = htobe32(0xFF000000);
-                                entry->ip.invflags = IPT_INV_DSTIP;
-                        }
-
-                        if (!sym_iptc_check_entry(chain_output, entry, (unsigned char*) mask, h)) {
-                                if (errno != ENOENT)
-                                        return -errno;
-
-                                if (!sym_iptc_insert_entry(chain_output, entry, 0, h))
-                                        return -errno;
-                        }
-
-                        /* If a previous remote is set, remove its entry */
-                        if (previous_remote && previous_remote->in.s_addr != remote->in.s_addr) {
-                                mr->range[0].min_ip = mr->range[0].max_ip = previous_remote->in.s_addr;
-
-                                if (!sym_iptc_delete_entry(chain_output, entry, (unsigned char*) mask, h)) {
-                                        if (errno != ENOENT)
-                                                return -errno;
-                                }
-                        }
-                }
-        } else {
-                if (!sym_iptc_delete_entry(chain_pre, entry, (unsigned char*) mask, h)) {
-                        if (errno != ENOENT)
-                                return -errno;
-                }
-
-                if (!in_interface) {
-                        if (!destination) {
-                                entry->ip.dst.s_addr = htobe32(0x7F000000);
-                                entry->ip.dmsk.s_addr = htobe32(0xFF000000);
-                                entry->ip.invflags = IPT_INV_DSTIP;
-                        }
-
-                        if (!sym_iptc_delete_entry(chain_output, entry, (unsigned char*) mask, h)) {
-                                if (errno != ENOENT)
-                                        return -errno;
-                        }
-                }
-        }
-
-        if (!sym_iptc_commit(h))
-                return -errno;
-
-        return 0;
-}
-
-static int dlopen_iptc(void) {
-        ELF_NOTE_DLOPEN("ip4tc",
-                        "Support for firewall rules with iptables backend",
-                        ELF_NOTE_DLOPEN_PRIORITY_SUGGESTED,
-                        "libip4tc.so.2");
-
-        return dlopen_many_sym_or_warn(
-                        &iptc_dl,
-                        "libip4tc.so.2", LOG_DEBUG,
-                        DLSYM_ARG(iptc_check_entry),
-                        DLSYM_ARG(iptc_commit),
-                        DLSYM_ARG(iptc_delete_entry),
-                        DLSYM_ARG(iptc_free),
-                        DLSYM_ARG(iptc_init),
-                        DLSYM_ARG(iptc_insert_entry),
-                        DLSYM_ARG(iptc_strerror));
-}
-
-int fw_iptables_init_nat(struct xtc_handle **ret) {
-        _cleanup_(sym_iptc_freep) struct xtc_handle *h = NULL;
-        int r;
-
-        r = dlopen_iptc();
-        if (r < 0)
-                return r;
-
-        h = sym_iptc_init("nat");
-        if (!h)
-                return log_debug_errno(errno, "Failed to init \"nat\" table: %s", sym_iptc_strerror(errno));
-
-        if (ret)
-                *ret = TAKE_PTR(h);
-
-        return 0;
-}
index 7e965494c8dbbcee988accda10db0b67ce9e7ec9..70c66789ac7152926217c773b47d16df31d337ee 100644 (file)
@@ -6,9 +6,6 @@
 
 typedef enum FirewallBackend {
         FW_BACKEND_NONE,
-#if HAVE_LIBIPTC
-        FW_BACKEND_IPTABLES,
-#endif
         FW_BACKEND_NFTABLES,
         _FW_BACKEND_MAX,
         _FW_BACKEND_INVALID = -EINVAL,
@@ -41,24 +38,3 @@ int fw_nftables_add_local_dnat(
                 const union in_addr_union *remote,
                 uint16_t remote_port,
                 const union in_addr_union *previous_remote);
-
-#if HAVE_LIBIPTC
-struct xtc_handle;
-
-int fw_iptables_add_masquerade(
-                bool add,
-                int af,
-                const union in_addr_union *source,
-                unsigned source_prefixlen);
-
-int fw_iptables_add_local_dnat(
-                bool add,
-                int af,
-                int protocol,
-                uint16_t local_port,
-                const union in_addr_union *remote,
-                uint16_t remote_port,
-                const union in_addr_union *previous_remote);
-
-int fw_iptables_init_nat(struct xtc_handle **ret);
-#endif
index c8dfad5d3368b9061a66e41056d829ec7d86b979..d4c0e4febfee552122a47548e3f02a612e21a711 100644 (file)
@@ -13,9 +13,6 @@
 
 static const char * const firewall_backend_table[_FW_BACKEND_MAX] = {
         [FW_BACKEND_NONE] = "none",
-#if HAVE_LIBIPTC
-        [FW_BACKEND_IPTABLES] = "iptables",
-#endif
         [FW_BACKEND_NFTABLES] = "nftables",
 };
 
@@ -33,12 +30,6 @@ static void firewall_backend_probe(FirewallContext *ctx, bool init_tables) {
         if (e) {
                 if (streq(e, "nftables"))
                         ctx->backend = FW_BACKEND_NFTABLES;
-                else if (streq(e, "iptables"))
-#if HAVE_LIBIPTC
-                        ctx->backend = FW_BACKEND_IPTABLES;
-#else
-                        log_debug("Unsupported firewall backend requested, ignoring: %s", e);
-#endif
                 else
                         log_debug("Unrecognized $SYSTEMD_FIREWALL_BACKEND value, ignoring: %s", e);
         }
@@ -48,11 +39,7 @@ static void firewall_backend_probe(FirewallContext *ctx, bool init_tables) {
                 if (fw_nftables_init_full(ctx, init_tables) >= 0)
                         ctx->backend = FW_BACKEND_NFTABLES;
                 else
-#if HAVE_LIBIPTC
-                        ctx->backend = FW_BACKEND_IPTABLES;
-#else
                         ctx->backend = FW_BACKEND_NONE;
-#endif
         }
 
         if (ctx->backend != FW_BACKEND_NONE)
@@ -116,10 +103,6 @@ int fw_add_masquerade(
         }
 
         switch ((*ctx)->backend) {
-#if HAVE_LIBIPTC
-        case FW_BACKEND_IPTABLES:
-                return fw_iptables_add_masquerade(add, af, source, source_prefixlen);
-#endif
         case FW_BACKEND_NFTABLES:
                 return fw_nftables_add_masquerade(*ctx, add, af, source, source_prefixlen);
         default:
@@ -148,10 +131,6 @@ int fw_add_local_dnat(
         }
 
         switch ((*ctx)->backend) {
-#if HAVE_LIBIPTC
-        case FW_BACKEND_IPTABLES:
-                return fw_iptables_add_local_dnat(add, af, protocol, local_port, remote, remote_port, previous_remote);
-#endif
         case FW_BACKEND_NFTABLES:
                 return fw_nftables_add_local_dnat(*ctx, add, af, protocol, local_port, remote, remote_port, previous_remote);
         default:
index 59ce0ec2b33ca2378e2d044250570edeca45a44c..ef59f2655893f9029356237161cbbb819819498a 100644 (file)
@@ -249,10 +249,6 @@ if conf.get('ENABLE_UTMP') == 1
         shared_sources += files('utmp-wtmp.c')
 endif
 
-if conf.get('HAVE_LIBIPTC') == 1
-        shared_sources += files('firewall-util-iptables.c')
-endif
-
 if conf.get('HAVE_LIBBPF') == 1
         shared_sources += files('bpf-link.c')
 endif
@@ -323,7 +319,6 @@ libshared_deps = [threads,
                   libcrypt,
                   libdl,
                   libgcrypt_cflags,
-                  libiptc_cflags,
                   libkmod_cflags,
                   liblz4_cflags,
                   libmount,
index 1a2121d0849748f8c047604f97fba33761a29b55..d36de6bf16de63b3b930d6ae2a203350cd152d6b 100644 (file)
@@ -62,13 +62,6 @@ static bool test_v4(FirewallContext *ctx) {
 
         log_info("/* %s(backend=%s) */", __func__, firewall_backend_to_string(ctx->backend));
 
-#if HAVE_LIBIPTC
-        if (ctx->backend == FW_BACKEND_IPTABLES && fw_iptables_init_nat(NULL) < 0) {
-                log_debug("iptables backend is used, but nat table is not enabled, skipping tests");
-                return false;
-        }
-#endif
-
         ASSERT_ERROR(fw_add_masquerade(&ctx, true, AF_INET, NULL, 0), EINVAL);
         ASSERT_ERROR(fw_add_masquerade(&ctx, true, AF_INET, parse_addr("10.1.2.0", &u), 0), EINVAL);
 
@@ -116,12 +109,5 @@ int main(int argc, char *argv[]) {
         if (test_v4(ctx) && ctx->backend == FW_BACKEND_NFTABLES)
                 test_v6(ctx);
 
-#if HAVE_LIBIPTC
-        if (ctx->backend != FW_BACKEND_IPTABLES) {
-                ctx->backend = FW_BACKEND_IPTABLES;
-                test_v4(ctx);
-        }
-#endif
-
         return 0;
 }