1 /* SPDX-License-Identifier: LGPL-2.1-or-later */
2
3 #include <errno.h>
4 #include <stddef.h>
5 #include <string.h>
6
7 #include "alloc-util.h"
8 #include "firewall-util.h"
9 #include "firewall-util-private.h"
10 #include "log.h"
11 #include "string-table.h"
12
13 static const char * const firewall_backend_table[_FW_BACKEND_MAX] = {
14 [FW_BACKEND_NONE] = "none",
15 #if HAVE_LIBIPTC
16 [FW_BACKEND_IPTABLES] = "iptables",
17 #endif
18 [FW_BACKEND_NFTABLES] = "nftables",
19 };
20
21 DEFINE_STRING_TABLE_LOOKUP_TO_STRING(firewall_backend, FirewallBackend);
22
firewall_backend_probe(FirewallContext * ctx)23 static void firewall_backend_probe(FirewallContext *ctx) {
24 assert(ctx);
25
26 if (ctx->backend != _FW_BACKEND_INVALID)
27 return;
28
29 if (fw_nftables_init(ctx) >= 0)
30 ctx->backend = FW_BACKEND_NFTABLES;
31 else
32 #if HAVE_LIBIPTC
33 ctx->backend = FW_BACKEND_IPTABLES;
34 #else
35 ctx->backend = FW_BACKEND_NONE;
36 #endif
37
38 if (ctx->backend != FW_BACKEND_NONE)
39 log_debug("Using %s as firewall backend.", firewall_backend_to_string(ctx->backend));
40 else
41 log_debug("No firewall backend found.");
42 }
43
fw_ctx_new(FirewallContext ** ret)44 int fw_ctx_new(FirewallContext **ret) {
45 _cleanup_free_ FirewallContext *ctx = NULL;
46
47 ctx = new(FirewallContext, 1);
48 if (!ctx)
49 return -ENOMEM;
50
51 *ctx = (FirewallContext) {
52 .backend = _FW_BACKEND_INVALID,
53 };
54
55 firewall_backend_probe(ctx);
56
57 *ret = TAKE_PTR(ctx);
58 return 0;
59 }
60
fw_ctx_free(FirewallContext * ctx)61 FirewallContext *fw_ctx_free(FirewallContext *ctx) {
62 if (!ctx)
63 return NULL;
64
65 fw_nftables_exit(ctx);
66
67 return mfree(ctx);
68 }
69
fw_add_masquerade(FirewallContext ** ctx,bool add,int af,const union in_addr_union * source,unsigned source_prefixlen)70 int fw_add_masquerade(
71 FirewallContext **ctx,
72 bool add,
73 int af,
74 const union in_addr_union *source,
75 unsigned source_prefixlen) {
76
77 int r;
78
79 assert(ctx);
80
81 if (!*ctx) {
82 r = fw_ctx_new(ctx);
83 if (r < 0)
84 return r;
85 }
86
87 switch ((*ctx)->backend) {
88 #if HAVE_LIBIPTC
89 case FW_BACKEND_IPTABLES:
90 return fw_iptables_add_masquerade(add, af, source, source_prefixlen);
91 #endif
92 case FW_BACKEND_NFTABLES:
93 return fw_nftables_add_masquerade(*ctx, add, af, source, source_prefixlen);
94 default:
95 return -EOPNOTSUPP;
96 }
97 }
98
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)99 int fw_add_local_dnat(
100 FirewallContext **ctx,
101 bool add,
102 int af,
103 int protocol,
104 uint16_t local_port,
105 const union in_addr_union *remote,
106 uint16_t remote_port,
107 const union in_addr_union *previous_remote) {
108
109 int r;
110
111 assert(ctx);
112
113 if (!*ctx) {
114 r = fw_ctx_new(ctx);
115 if (r < 0)
116 return r;
117 }
118
119 switch ((*ctx)->backend) {
120 #if HAVE_LIBIPTC
121 case FW_BACKEND_IPTABLES:
122 return fw_iptables_add_local_dnat(add, af, protocol, local_port, remote, remote_port, previous_remote);
123 #endif
124 case FW_BACKEND_NFTABLES:
125 return fw_nftables_add_local_dnat(*ctx, add, af, protocol, local_port, remote, remote_port, previous_remote);
126 default:
127 return -EOPNOTSUPP;
128 }
129 }
130