firewall-util: drop FirewallContext

After iptables support is dropped, FirewallContext is a trivial
wrapper of sd_netlink. Let's drop it and directly use sd_netlink.
This commit is contained in:
Yu Watanabe
2025-09-19 15:33:17 +09:00
parent 9b75c41cb3
commit 7184f8366f
21 changed files with 189 additions and 396 deletions
+31 -64
View File
@@ -14,7 +14,6 @@
#include "escape.h"
#include "extract-word.h"
#include "firewall-util.h"
#include "firewall-util-private.h"
#include "in-addr-util.h"
#include "log.h"
#include "netlink-internal.h"
@@ -815,43 +814,6 @@ static int fw_nftables_init_family(sd_netlink *nfnl, int family) {
return 0;
}
int fw_nftables_init_full(FirewallContext *ctx, bool init_tables) {
_cleanup_(sd_netlink_unrefp) sd_netlink *nfnl = NULL;
int r;
assert(ctx);
assert(!ctx->nfnl);
r = sd_nfnl_socket_open(&nfnl);
if (r < 0)
return r;
if (init_tables) {
r = fw_nftables_init_family(nfnl, AF_INET);
if (r < 0)
return r;
if (socket_ipv6_is_supported()) {
r = fw_nftables_init_family(nfnl, AF_INET6);
if (r < 0)
return log_error_errno(r, "Failed to init ipv6 NAT: %m");
}
}
ctx->nfnl = TAKE_PTR(nfnl);
return 0;
}
int fw_nftables_init(FirewallContext *ctx) {
return fw_nftables_init_full(ctx, /* init_tables= */ true);
}
void fw_nftables_exit(FirewallContext *ctx) {
assert(ctx);
ctx->nfnl = sd_netlink_unref(ctx->nfnl);
}
static int nft_message_append_setelem_iprange(
sd_netlink_message *m,
const union in_addr_union *source,
@@ -922,7 +884,7 @@ static int nft_message_append_setelem_ip6range(
}
int nft_set_element_modify_iprange(
FirewallContext *ctx,
sd_netlink *nfnl,
bool add,
int nfproto,
int af,
@@ -934,7 +896,7 @@ int nft_set_element_modify_iprange(
_cleanup_(sd_netlink_message_unrefp) sd_netlink_message *m = NULL;
int r;
assert(ctx->nfnl);
assert(nfnl);
assert(IN_SET(af, AF_INET, AF_INET6));
assert(nfproto_is_valid(nfproto));
assert(table);
@@ -946,7 +908,7 @@ int nft_set_element_modify_iprange(
if (af == AF_INET6 && source_prefixlen < 8)
return -EINVAL;
r = sd_nfnl_nft_message_new_setelems(ctx->nfnl, &m, add, nfproto, table, set);
r = sd_nfnl_nft_message_new_setelems(nfnl, &m, add, nfproto, table, set);
if (r < 0)
return r;
@@ -957,11 +919,11 @@ int nft_set_element_modify_iprange(
if (r < 0)
return r;
return sd_nfnl_call_batch(ctx->nfnl, &m, 1, NFNL_DEFAULT_TIMEOUT_USECS, NULL);
return sd_nfnl_call_batch(nfnl, &m, 1, NFNL_DEFAULT_TIMEOUT_USECS, NULL);
}
int nft_set_element_modify_ip(
FirewallContext *ctx,
sd_netlink *nfnl,
bool add,
int nfproto,
int af,
@@ -972,7 +934,7 @@ int nft_set_element_modify_ip(
_cleanup_(sd_netlink_message_unrefp) sd_netlink_message *m = NULL;
int r;
assert(ctx->nfnl);
assert(nfnl);
assert(IN_SET(af, AF_INET, AF_INET6));
assert(nfproto_is_valid(nfproto));
assert(table);
@@ -981,7 +943,7 @@ int nft_set_element_modify_ip(
if (!source)
return -EINVAL;
r = sd_nfnl_nft_message_new_setelems(ctx->nfnl, &m, add, nfproto, table, set);
r = sd_nfnl_nft_message_new_setelems(nfnl, &m, add, nfproto, table, set);
if (r < 0)
return r;
@@ -997,28 +959,35 @@ int nft_set_element_modify_ip(
if (r < 0)
return r;
return sd_nfnl_call_batch(ctx->nfnl, &m, 1, NFNL_DEFAULT_TIMEOUT_USECS, NULL);
return sd_nfnl_call_batch(nfnl, &m, 1, NFNL_DEFAULT_TIMEOUT_USECS, NULL);
}
int nft_set_element_modify_any(FirewallContext *ctx, bool add, int nfproto, const char *table, const char *set, const void *element, size_t element_size) {
int nft_set_element_modify_any(
sd_netlink *nfnl,
bool add,
int nfproto,
const char *table,
const char *set,
const void *element,
size_t element_size) {
_cleanup_(sd_netlink_message_unrefp) sd_netlink_message *m = NULL;
int r;
assert(ctx);
assert(ctx->nfnl);
assert(nfnl);
assert(nfproto_is_valid(nfproto));
assert(table);
assert(set);
assert(element);
if (add)
r = nft_add_element(ctx->nfnl, &m, nfproto, table, set, element, element_size, NULL, 0);
r = nft_add_element(nfnl, &m, nfproto, table, set, element, element_size, NULL, 0);
else
r = nft_del_element(ctx->nfnl, &m, nfproto, table, set, element, element_size, NULL, 0);
r = nft_del_element(nfnl, &m, nfproto, table, set, element, element_size, NULL, 0);
if (r < 0)
return r;
return sd_nfnl_call_batch(ctx->nfnl, &m, 1, NFNL_DEFAULT_TIMEOUT_USECS, NULL);
return sd_nfnl_call_batch(nfnl, &m, 1, NFNL_DEFAULT_TIMEOUT_USECS, NULL);
}
static int af_to_nfproto(int af) {
@@ -1035,7 +1004,7 @@ static int af_to_nfproto(int af) {
}
int fw_nftables_add_masquerade(
FirewallContext *ctx,
sd_netlink *nfnl,
bool add,
int af,
const union in_addr_union *source,
@@ -1043,14 +1012,13 @@ int fw_nftables_add_masquerade(
int r;
assert(ctx);
assert(ctx->nfnl);
assert(nfnl);
assert(IN_SET(af, AF_INET, AF_INET6));
if (!socket_ipv6_is_supported() && af == AF_INET6)
return -EOPNOTSUPP;
r = nft_set_element_modify_iprange(ctx, add, af_to_nfproto(af), af, nft_table_name(), NFT_SYSTEMD_MASQ_SET_NAME,
r = nft_set_element_modify_iprange(nfnl, add, af_to_nfproto(af), af, nft_table_name(), NFT_SYSTEMD_MASQ_SET_NAME,
source, source_prefixlen);
if (r != -ENOENT)
return r;
@@ -1072,11 +1040,11 @@ int fw_nftables_add_masquerade(
* of extending the kernel to allow tables to be owned by stystemd-networkd and making them
* non-deleteable except by the 'owning process'. */
r = fw_nftables_init_family(ctx->nfnl, af);
r = fw_nftables_init_family(nfnl, af);
if (r < 0)
return r;
return nft_set_element_modify_iprange(ctx, add, af_to_nfproto(af), af, nft_table_name(), NFT_SYSTEMD_MASQ_SET_NAME,
return nft_set_element_modify_iprange(nfnl, add, af_to_nfproto(af), af, nft_table_name(), NFT_SYSTEMD_MASQ_SET_NAME,
source, source_prefixlen);
}
@@ -1172,7 +1140,7 @@ static int fw_nftables_add_local_dnat_internal(
}
int fw_nftables_add_local_dnat(
FirewallContext *ctx,
sd_netlink *nfnl,
bool add,
int af,
int protocol,
@@ -1183,24 +1151,23 @@ int fw_nftables_add_local_dnat(
int r;
assert(ctx);
assert(ctx->nfnl);
assert(nfnl);
assert(IN_SET(af, AF_INET, AF_INET6));
if (!socket_ipv6_is_supported() && af == AF_INET6)
return -EOPNOTSUPP;
r = fw_nftables_add_local_dnat_internal(ctx->nfnl, add, af, protocol, local_port, remote, remote_port, previous_remote);
r = fw_nftables_add_local_dnat_internal(nfnl, add, af, protocol, local_port, remote, remote_port, previous_remote);
if (r != -ENOENT)
return r;
/* See comment in fw_nftables_add_masquerade(). */
r = fw_nftables_init_family(ctx->nfnl, af);
r = fw_nftables_init_family(nfnl, af);
if (r < 0)
return r;
/* table created anew; previous address already gone */
return fw_nftables_add_local_dnat_internal(ctx->nfnl, add, af, protocol, local_port, remote, remote_port, NULL);
return fw_nftables_add_local_dnat_internal(nfnl, add, af, protocol, local_port, remote, remote_port, NULL);
}
static const char *const nfproto_table[] = {
-40
View File
@@ -1,40 +0,0 @@
/* SPDX-License-Identifier: LGPL-2.1-or-later */
#pragma once
#include "firewall-util.h"
#include "forward.h"
typedef enum FirewallBackend {
FW_BACKEND_NONE,
FW_BACKEND_NFTABLES,
_FW_BACKEND_MAX,
_FW_BACKEND_INVALID = -EINVAL,
} FirewallBackend;
struct FirewallContext {
FirewallBackend backend;
sd_netlink *nfnl;
};
const char* firewall_backend_to_string(FirewallBackend b) _const_;
int fw_nftables_init(FirewallContext *ctx);
int fw_nftables_init_full(FirewallContext *ctx, bool init_tables);
void fw_nftables_exit(FirewallContext *ctx);
int fw_nftables_add_masquerade(
FirewallContext *ctx,
bool add,
int af,
const union in_addr_union *source,
unsigned source_prefixlen);
int fw_nftables_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);
-139
View File
@@ -1,139 +0,0 @@
/* SPDX-License-Identifier: LGPL-2.1-or-later */
#include <stdlib.h>
#include <string.h>
#include "alloc-util.h"
#include "firewall-util.h"
#include "firewall-util-private.h"
#include "log.h"
#include "netlink-util.h"
#include "string-table.h"
#include "string-util.h"
static const char * const firewall_backend_table[_FW_BACKEND_MAX] = {
[FW_BACKEND_NONE] = "none",
[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
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
ctx->backend = FW_BACKEND_NONE;
}
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) {
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) {
case FW_BACKEND_NFTABLES:
return fw_nftables_add_local_dnat(*ctx, add, af, protocol, local_port, remote, remote_port, previous_remote);
default:
return -EOPNOTSUPP;
}
}
+7 -17
View File
@@ -4,25 +4,15 @@
#include "conf-parser-forward.h"
#include "forward.h"
typedef struct FirewallContext FirewallContext;
int fw_ctx_new(FirewallContext **ret);
int fw_ctx_new_full(FirewallContext **ret, bool init_tables);
FirewallContext *fw_ctx_free(FirewallContext *ctx);
DEFINE_TRIVIAL_CLEANUP_FUNC(FirewallContext *, fw_ctx_free);
size_t fw_ctx_get_reply_callback_count(FirewallContext *ctx);
int fw_add_masquerade(
FirewallContext **ctx,
int fw_nftables_add_masquerade(
sd_netlink *nfnl,
bool add,
int af,
const union in_addr_union *source,
unsigned source_prefixlen);
int fw_add_local_dnat(
FirewallContext **ctx,
int fw_nftables_add_local_dnat(
sd_netlink *nfnl,
bool add,
int af,
int protocol,
@@ -64,7 +54,7 @@ const char* nft_set_source_to_string(int i) _const_;
int nft_set_source_from_string(const char *s) _pure_;
int nft_set_element_modify_iprange(
FirewallContext *ctx,
sd_netlink *nfnl,
bool add,
int nfproto,
int af,
@@ -74,7 +64,7 @@ int nft_set_element_modify_iprange(
unsigned source_prefixlen);
int nft_set_element_modify_ip(
FirewallContext *ctx,
sd_netlink *nfnl,
bool add,
int nfproto,
int af,
@@ -83,7 +73,7 @@ int nft_set_element_modify_ip(
const union in_addr_union *source);
int nft_set_element_modify_any(
FirewallContext *ctx,
sd_netlink *nfnl,
bool add,
int nfproto,
const char *table,
-1
View File
@@ -77,7 +77,6 @@ shared_sources = files(
'fido2-util.c',
'find-esp.c',
'firewall-util-nft.c',
'firewall-util.c',
'fork-notify.c',
'format-table.c',
'fstab-util.c',