1 /* SPDX-License-Identifier: LGPL-2.1-or-later */
7 #include "alloc-util.h"
8 #include "firewall-util.h"
9 #include "firewall-util-private.h"
11 #include "netlink-util.h"
12 #include "string-table.h"
14 static const char * const firewall_backend_table
[_FW_BACKEND_MAX
] = {
15 [FW_BACKEND_NONE
] = "none",
17 [FW_BACKEND_IPTABLES
] = "iptables",
19 [FW_BACKEND_NFTABLES
] = "nftables",
22 DEFINE_STRING_TABLE_LOOKUP_TO_STRING(firewall_backend
, FirewallBackend
);
24 static void firewall_backend_probe(FirewallContext
*ctx
, bool init_tables
) {
29 if (ctx
->backend
!= _FW_BACKEND_INVALID
)
32 e
= secure_getenv("SYSTEMD_FIREWALL_BACKEND");
34 if (streq(e
, "nftables"))
35 ctx
->backend
= FW_BACKEND_NFTABLES
;
36 else if (streq(e
, "iptables"))
38 ctx
->backend
= FW_BACKEND_IPTABLES
;
40 log_debug("Unsupported firewall backend requested, ignoring: %s", e
);
43 log_debug("Unrecognized $SYSTEMD_FIREWALL_BACKEND value, ignoring: %s", e
);
46 if (ctx
->backend
== _FW_BACKEND_INVALID
) {
48 if (fw_nftables_init_full(ctx
, init_tables
) >= 0)
49 ctx
->backend
= FW_BACKEND_NFTABLES
;
52 ctx
->backend
= FW_BACKEND_IPTABLES
;
54 ctx
->backend
= FW_BACKEND_NONE
;
58 if (ctx
->backend
!= FW_BACKEND_NONE
)
59 log_debug("Using %s as firewall backend.", firewall_backend_to_string(ctx
->backend
));
61 log_debug("No firewall backend found.");
64 int fw_ctx_new_full(FirewallContext
**ret
, bool init_tables
) {
65 _cleanup_free_ FirewallContext
*ctx
= NULL
;
67 ctx
= new(FirewallContext
, 1);
71 *ctx
= (FirewallContext
) {
72 .backend
= _FW_BACKEND_INVALID
,
75 firewall_backend_probe(ctx
, init_tables
);
81 int fw_ctx_new(FirewallContext
**ret
) {
82 return fw_ctx_new_full(ret
, /* init_tables= */ true);
85 FirewallContext
*fw_ctx_free(FirewallContext
*ctx
) {
89 fw_nftables_exit(ctx
);
94 size_t fw_ctx_get_reply_callback_count(FirewallContext
*ctx
) {
95 if (!ctx
|| !ctx
->nfnl
)
98 return netlink_get_reply_callback_count(ctx
->nfnl
);
101 int fw_add_masquerade(
102 FirewallContext
**ctx
,
105 const union in_addr_union
*source
,
106 unsigned source_prefixlen
) {
118 switch ((*ctx
)->backend
) {
120 case FW_BACKEND_IPTABLES
:
121 return fw_iptables_add_masquerade(add
, af
, source
, source_prefixlen
);
123 case FW_BACKEND_NFTABLES
:
124 return fw_nftables_add_masquerade(*ctx
, add
, af
, source
, source_prefixlen
);
130 int fw_add_local_dnat(
131 FirewallContext
**ctx
,
136 const union in_addr_union
*remote
,
137 uint16_t remote_port
,
138 const union in_addr_union
*previous_remote
) {
150 switch ((*ctx
)->backend
) {
152 case FW_BACKEND_IPTABLES
:
153 return fw_iptables_add_local_dnat(add
, af
, protocol
, local_port
, remote
, remote_port
, previous_remote
);
155 case FW_BACKEND_NFTABLES
:
156 return fw_nftables_add_local_dnat(*ctx
, add
, af
, protocol
, local_port
, remote
, remote_port
, previous_remote
);