From 55944e5e40b1be2afc4855d8d2baf4b73d1876b5 Mon Sep 17 00:00:00 2001 From: Daniel Baumann Date: Wed, 10 Apr 2024 22:49:52 +0200 Subject: Adding upstream version 255.4. Signed-off-by: Daniel Baumann --- src/shared/firewall-util.c | 160 +++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 160 insertions(+) create mode 100644 src/shared/firewall-util.c (limited to 'src/shared/firewall-util.c') diff --git a/src/shared/firewall-util.c b/src/shared/firewall-util.c new file mode 100644 index 0000000..e96b24a --- /dev/null +++ b/src/shared/firewall-util.c @@ -0,0 +1,160 @@ +/* SPDX-License-Identifier: LGPL-2.1-or-later */ + +#include +#include +#include + +#include "alloc-util.h" +#include "firewall-util.h" +#include "firewall-util-private.h" +#include "log.h" +#include "netlink-util.h" +#include "string-table.h" + +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", +}; + +DEFINE_STRING_TABLE_LOOKUP_TO_STRING(firewall_backend, FirewallBackend); + +static void firewall_backend_probe(FirewallContext *ctx, bool init_tables) { + const char *e; + + assert(ctx); + + if (ctx->backend != _FW_BACKEND_INVALID) + return; + + e = secure_getenv("SYSTEMD_FIREWALL_BACKEND"); + 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); + } + + if (ctx->backend == _FW_BACKEND_INVALID) { + + 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) + log_debug("Using %s as firewall backend.", firewall_backend_to_string(ctx->backend)); + else + log_debug("No firewall backend found."); +} + +int fw_ctx_new_full(FirewallContext **ret, bool init_tables) { + _cleanup_free_ FirewallContext *ctx = NULL; + + ctx = new(FirewallContext, 1); + if (!ctx) + return -ENOMEM; + + *ctx = (FirewallContext) { + .backend = _FW_BACKEND_INVALID, + }; + + firewall_backend_probe(ctx, init_tables); + + *ret = TAKE_PTR(ctx); + return 0; +} + +int fw_ctx_new(FirewallContext **ret) { + return fw_ctx_new_full(ret, /* init_tables= */ true); +} + +FirewallContext *fw_ctx_free(FirewallContext *ctx) { + if (!ctx) + return NULL; + + fw_nftables_exit(ctx); + + return mfree(ctx); +} + +size_t fw_ctx_get_reply_callback_count(FirewallContext *ctx) { + if (!ctx || !ctx->nfnl) + return 0; + + return netlink_get_reply_callback_count(ctx->nfnl); +} + +int fw_add_masquerade( + FirewallContext **ctx, + bool add, + int af, + const union in_addr_union *source, + unsigned source_prefixlen) { + + int r; + + assert(ctx); + + if (!*ctx) { + r = fw_ctx_new(ctx); + if (r < 0) + return r; + } + + 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: + return -EOPNOTSUPP; + } +} + +int fw_add_local_dnat( + FirewallContext **ctx, + 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 r; + + assert(ctx); + + if (!*ctx) { + r = fw_ctx_new(ctx); + if (r < 0) + return r; + } + + 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: + return -EOPNOTSUPP; + } +} -- cgit v1.2.3