diff --git a/meson.build b/meson.build index dddb7766159..52850311b55 100644 --- a/meson.build +++ b/meson.build @@ -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'], diff --git a/meson_options.txt b/meson_options.txt index cd4b556283d..464f388e22d 100644 --- a/meson_options.txt +++ b/meson_options.txt @@ -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') diff --git a/src/basic/build.c b/src/basic/build.c index ad9d3b1c4bd..b9341b184d6 100644 --- a/src/basic/build.c +++ b/src/basic/build.c @@ -126,12 +126,6 @@ const char* const systemd_features = " -IDN" #endif -#if HAVE_LIBIPTC - " +IPTC" -#else - " -IPTC" -#endif - #if HAVE_KMOD " +KMOD" #else diff --git a/src/core/kmod-setup.c b/src/core/kmod-setup.c index 12ce5a86e4a..1f694b29d94 100644 --- a/src/core/kmod-setup.c +++ b/src/core/kmod-setup.c @@ -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 index 1e5b59f0ddb..00000000000 --- a/src/shared/firewall-util-iptables.c +++ /dev/null @@ -1,383 +0,0 @@ -/* SPDX-License-Identifier: LGPL-2.1-or-later */ - -#include -#include -#include -#include -#include -#include - -#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; -} diff --git a/src/shared/firewall-util-private.h b/src/shared/firewall-util-private.h index 7e965494c8d..70c66789ac7 100644 --- a/src/shared/firewall-util-private.h +++ b/src/shared/firewall-util-private.h @@ -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 diff --git a/src/shared/firewall-util.c b/src/shared/firewall-util.c index c8dfad5d336..d4c0e4febfe 100644 --- a/src/shared/firewall-util.c +++ b/src/shared/firewall-util.c @@ -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: diff --git a/src/shared/meson.build b/src/shared/meson.build index 59ce0ec2b33..ef59f265589 100644 --- a/src/shared/meson.build +++ b/src/shared/meson.build @@ -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, diff --git a/src/test/test-firewall-util.c b/src/test/test-firewall-util.c index 1a2121d0849..d36de6bf16d 100644 --- a/src/test/test-firewall-util.c +++ b/src/test/test-firewall-util.c @@ -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; }