mirror of
https://github.com/systemd/systemd-stable.git
synced 2025-01-12 09:17:44 +03:00
firewall-util-nft: various cleanups
- add missing assertions, - align enum elements, - use cleanup attribute, and so on.
This commit is contained in:
parent
8547260579
commit
295942cb46
@ -24,13 +24,27 @@
|
||||
#include "time-util.h"
|
||||
|
||||
#define NFT_SYSTEMD_DNAT_MAP_NAME "map_port_ipport"
|
||||
#define NFT_SYSTEMD_TABLE_NAME "io.systemd.nat"
|
||||
#define NFT_SYSTEMD_TABLE_NAME "io.systemd.nat"
|
||||
#define NFT_SYSTEMD_MASQ_SET_NAME "masq_saddr"
|
||||
|
||||
#define NFNL_DEFAULT_TIMEOUT_USECS (1ULL * USEC_PER_SEC)
|
||||
|
||||
#define UDP_DPORT_OFFSET 2
|
||||
|
||||
static sd_netlink_message **netlink_message_unref_many(sd_netlink_message **m) {
|
||||
if (!m)
|
||||
return NULL;
|
||||
|
||||
/* This does not free array. The end of the array must be NULL. */
|
||||
|
||||
for (sd_netlink_message **p = m; *p; p++)
|
||||
*p = sd_netlink_message_unref(*p);
|
||||
|
||||
return m;
|
||||
}
|
||||
|
||||
DEFINE_TRIVIAL_CLEANUP_FUNC(sd_netlink_message**, netlink_message_unref_many);
|
||||
|
||||
static int nfnl_netlink_sendv(
|
||||
sd_netlink *nfnl,
|
||||
sd_netlink_message *messages[static 1],
|
||||
@ -63,6 +77,9 @@ static int nfnl_netlink_sendv(
|
||||
static int nfnl_add_open_expr_container(sd_netlink_message *m, const char *name) {
|
||||
int r;
|
||||
|
||||
assert(m);
|
||||
assert(name);
|
||||
|
||||
r = sd_netlink_message_open_array(m, NFTA_LIST_ELEM);
|
||||
if (r < 0)
|
||||
return r;
|
||||
@ -74,11 +91,16 @@ static int nfnl_add_open_expr_container(sd_netlink_message *m, const char *name)
|
||||
return sd_netlink_message_open_container_union(m, NFTA_EXPR_DATA, name);
|
||||
}
|
||||
|
||||
static int nfnl_add_expr_fib(sd_netlink_message *m, uint32_t nft_fib_flags,
|
||||
enum nft_fib_result result,
|
||||
enum nft_registers dreg) {
|
||||
static int nfnl_add_expr_fib(
|
||||
sd_netlink_message *m,
|
||||
uint32_t nft_fib_flags,
|
||||
enum nft_fib_result result,
|
||||
enum nft_registers dreg) {
|
||||
|
||||
int r;
|
||||
|
||||
assert(m);
|
||||
|
||||
r = nfnl_add_open_expr_container(m, "fib");
|
||||
if (r < 0)
|
||||
return r;
|
||||
@ -86,9 +108,11 @@ static int nfnl_add_expr_fib(sd_netlink_message *m, uint32_t nft_fib_flags,
|
||||
r = sd_netlink_message_append_u32(m, NFTA_FIB_FLAGS, htobe32(nft_fib_flags));
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
r = sd_netlink_message_append_u32(m, NFTA_FIB_RESULT, htobe32(result));
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
r = sd_netlink_message_append_u32(m, NFTA_FIB_DREG, htobe32(dreg));
|
||||
if (r < 0)
|
||||
return r;
|
||||
@ -100,10 +124,15 @@ static int nfnl_add_expr_fib(sd_netlink_message *m, uint32_t nft_fib_flags,
|
||||
return sd_netlink_message_close_container(m); /* NFTA_LIST_ELEM */
|
||||
}
|
||||
|
||||
static int nfnl_add_expr_meta(sd_netlink_message *m, enum nft_meta_keys key,
|
||||
enum nft_registers dreg) {
|
||||
static int nfnl_add_expr_meta(
|
||||
sd_netlink_message *m,
|
||||
enum nft_meta_keys key,
|
||||
enum nft_registers dreg) {
|
||||
|
||||
int r;
|
||||
|
||||
assert(m);
|
||||
|
||||
r = nfnl_add_open_expr_container(m, "meta");
|
||||
if (r < 0)
|
||||
return r;
|
||||
@ -123,10 +152,17 @@ static int nfnl_add_expr_meta(sd_netlink_message *m, enum nft_meta_keys key,
|
||||
return sd_netlink_message_close_container(m); /* NFTA_LIST_ELEM */
|
||||
}
|
||||
|
||||
static int nfnl_add_expr_payload(sd_netlink_message *m, enum nft_payload_bases pb,
|
||||
uint32_t offset, uint32_t len, enum nft_registers dreg) {
|
||||
static int nfnl_add_expr_payload(
|
||||
sd_netlink_message *m,
|
||||
enum nft_payload_bases pb,
|
||||
uint32_t offset,
|
||||
uint32_t len,
|
||||
enum nft_registers dreg) {
|
||||
|
||||
int r;
|
||||
|
||||
assert(m);
|
||||
|
||||
r = nfnl_add_open_expr_container(m, "payload");
|
||||
if (r < 0)
|
||||
return r;
|
||||
@ -134,12 +170,15 @@ static int nfnl_add_expr_payload(sd_netlink_message *m, enum nft_payload_bases p
|
||||
r = sd_netlink_message_append_u32(m, NFTA_PAYLOAD_DREG, htobe32(dreg));
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
r = sd_netlink_message_append_u32(m, NFTA_PAYLOAD_BASE, htobe32(pb));
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
r = sd_netlink_message_append_u32(m, NFTA_PAYLOAD_OFFSET, htobe32(offset));
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
r = sd_netlink_message_append_u32(m, NFTA_PAYLOAD_LEN, htobe32(len));
|
||||
if (r < 0)
|
||||
return r;
|
||||
@ -147,13 +186,20 @@ static int nfnl_add_expr_payload(sd_netlink_message *m, enum nft_payload_bases p
|
||||
r = sd_netlink_message_close_container(m); /* NFTA_EXPR_DATA */
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
return sd_netlink_message_close_container(m); /* NFTA_LIST_ELEM */
|
||||
}
|
||||
|
||||
static int nfnl_add_expr_lookup_set_data(sd_netlink_message *m, const char *set_name,
|
||||
enum nft_registers sreg) {
|
||||
static int nfnl_add_expr_lookup_set_data(
|
||||
sd_netlink_message *m,
|
||||
const char *set_name,
|
||||
enum nft_registers sreg) {
|
||||
|
||||
int r;
|
||||
|
||||
assert(m);
|
||||
assert(set_name);
|
||||
|
||||
r = nfnl_add_open_expr_container(m, "lookup");
|
||||
if (r < 0)
|
||||
return r;
|
||||
@ -165,10 +211,16 @@ static int nfnl_add_expr_lookup_set_data(sd_netlink_message *m, const char *set_
|
||||
return sd_netlink_message_append_u32(m, NFTA_LOOKUP_SREG, htobe32(sreg));
|
||||
}
|
||||
|
||||
static int nfnl_add_expr_lookup_set(sd_netlink_message *m, const char *set_name,
|
||||
enum nft_registers sreg) {
|
||||
static int nfnl_add_expr_lookup_set(
|
||||
sd_netlink_message *m,
|
||||
const char *set_name,
|
||||
enum nft_registers sreg) {
|
||||
|
||||
int r;
|
||||
|
||||
assert(m);
|
||||
assert(set_name);
|
||||
|
||||
r = nfnl_add_expr_lookup_set_data(m, set_name, sreg);
|
||||
if (r < 0)
|
||||
return r;
|
||||
@ -176,13 +228,21 @@ static int nfnl_add_expr_lookup_set(sd_netlink_message *m, const char *set_name,
|
||||
r = sd_netlink_message_close_container(m); /* NFTA_EXPR_DATA */
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
return sd_netlink_message_close_container(m); /* NFTA_LIST_ELEM */
|
||||
}
|
||||
|
||||
static int nfnl_add_expr_lookup_map(sd_netlink_message *m, const char *set_name,
|
||||
enum nft_registers sreg, enum nft_registers dreg) {
|
||||
static int nfnl_add_expr_lookup_map(
|
||||
sd_netlink_message *m,
|
||||
const char *set_name,
|
||||
enum nft_registers sreg,
|
||||
enum nft_registers dreg) {
|
||||
|
||||
int r;
|
||||
|
||||
assert(m);
|
||||
assert(set_name);
|
||||
|
||||
r = nfnl_add_expr_lookup_set_data(m, set_name, sreg);
|
||||
if (r < 0)
|
||||
return r;
|
||||
@ -198,12 +258,21 @@ static int nfnl_add_expr_lookup_map(sd_netlink_message *m, const char *set_name,
|
||||
return sd_netlink_message_close_container(m); /* NFTA_LIST_ELEM */
|
||||
}
|
||||
|
||||
static int nfnl_add_expr_data(sd_netlink_message *m, int attr, const void *data, uint32_t dlen) {
|
||||
static int nfnl_add_expr_data(
|
||||
sd_netlink_message *m,
|
||||
int attr,
|
||||
const void *data,
|
||||
uint32_t dlen) {
|
||||
|
||||
int r;
|
||||
|
||||
assert(m);
|
||||
assert(data);
|
||||
|
||||
r = sd_netlink_message_open_container(m, attr);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
r = sd_netlink_message_append_data(m, NFTA_DATA_VALUE, data, dlen);
|
||||
if (r < 0)
|
||||
return r;
|
||||
@ -211,14 +280,18 @@ static int nfnl_add_expr_data(sd_netlink_message *m, int attr, const void *data,
|
||||
return sd_netlink_message_close_container(m); /* attr */
|
||||
}
|
||||
|
||||
static int nfnl_add_expr_cmp_data(sd_netlink_message *m, const void *data, uint32_t dlen) {
|
||||
return nfnl_add_expr_data(m, NFTA_CMP_DATA, data, dlen);
|
||||
}
|
||||
static int nfnl_add_expr_cmp(
|
||||
sd_netlink_message *m,
|
||||
enum nft_cmp_ops cmp_op,
|
||||
enum nft_registers sreg,
|
||||
const void *data,
|
||||
uint32_t dlen) {
|
||||
|
||||
static int nfnl_add_expr_cmp(sd_netlink_message *m, enum nft_cmp_ops cmp_op,
|
||||
enum nft_registers sreg, const void *data, uint32_t dlen) {
|
||||
int r;
|
||||
|
||||
assert(m);
|
||||
assert(data);
|
||||
|
||||
r = nfnl_add_open_expr_container(m, "cmp");
|
||||
if (r < 0)
|
||||
return r;
|
||||
@ -226,27 +299,36 @@ static int nfnl_add_expr_cmp(sd_netlink_message *m, enum nft_cmp_ops cmp_op,
|
||||
r = sd_netlink_message_append_u32(m, NFTA_CMP_OP, htobe32(cmp_op));
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
r = sd_netlink_message_append_u32(m, NFTA_CMP_SREG, htobe32(sreg));
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
r = nfnl_add_expr_cmp_data(m, data, dlen);
|
||||
r = nfnl_add_expr_data(m, NFTA_CMP_DATA, data, dlen);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
r = sd_netlink_message_close_container(m); /* NFTA_EXPR_DATA */
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
return sd_netlink_message_close_container(m); /* NFTA_LIST_ELEM */
|
||||
}
|
||||
|
||||
static int nfnl_add_expr_bitwise(sd_netlink_message *m,
|
||||
enum nft_registers sreg,
|
||||
enum nft_registers dreg,
|
||||
const void *and,
|
||||
const void *xor, uint32_t len) {
|
||||
static int nfnl_add_expr_bitwise(
|
||||
sd_netlink_message *m,
|
||||
enum nft_registers sreg,
|
||||
enum nft_registers dreg,
|
||||
const void *and,
|
||||
const void *xor,
|
||||
uint32_t len) {
|
||||
|
||||
int r;
|
||||
|
||||
assert(m);
|
||||
assert(and);
|
||||
assert(xor);
|
||||
|
||||
r = nfnl_add_open_expr_container(m, "bitwise");
|
||||
if (r < 0)
|
||||
return r;
|
||||
@ -254,9 +336,11 @@ static int nfnl_add_expr_bitwise(sd_netlink_message *m,
|
||||
r = sd_netlink_message_append_u32(m, NFTA_BITWISE_SREG, htobe32(sreg));
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
r = sd_netlink_message_append_u32(m, NFTA_BITWISE_DREG, htobe32(dreg));
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
r = sd_netlink_message_append_u32(m, NFTA_BITWISE_LEN, htobe32(len));
|
||||
if (r < 0)
|
||||
return r;
|
||||
@ -272,15 +356,20 @@ static int nfnl_add_expr_bitwise(sd_netlink_message *m,
|
||||
r = sd_netlink_message_close_container(m); /* NFTA_EXPR_DATA */
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
return sd_netlink_message_close_container(m); /* NFTA_LIST_ELEM */
|
||||
}
|
||||
|
||||
static int nfnl_add_expr_dnat(sd_netlink_message *m,
|
||||
int family,
|
||||
enum nft_registers areg,
|
||||
enum nft_registers preg) {
|
||||
static int nfnl_add_expr_dnat(
|
||||
sd_netlink_message *m,
|
||||
int family,
|
||||
enum nft_registers areg,
|
||||
enum nft_registers preg) {
|
||||
|
||||
int r;
|
||||
|
||||
assert(m);
|
||||
|
||||
r = nfnl_add_open_expr_container(m, "nat");
|
||||
if (r < 0)
|
||||
return r;
|
||||
@ -296,9 +385,11 @@ static int nfnl_add_expr_dnat(sd_netlink_message *m,
|
||||
r = sd_netlink_message_append_u32(m, NFTA_NAT_REG_ADDR_MIN, htobe32(areg));
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
r = sd_netlink_message_append_u32(m, NFTA_NAT_REG_PROTO_MIN, htobe32(preg));
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
r = sd_netlink_message_close_container(m);
|
||||
if (r < 0)
|
||||
return r;
|
||||
@ -320,13 +411,22 @@ static int nfnl_add_expr_masq(sd_netlink_message *m) {
|
||||
return sd_netlink_message_close_container(m); /* NFTA_LIST_ELEM */
|
||||
}
|
||||
|
||||
static int sd_nfnl_message_new_masq_rule(sd_netlink *nfnl, sd_netlink_message **ret, int family,
|
||||
const char *chain) {
|
||||
static int sd_nfnl_message_new_masq_rule(
|
||||
sd_netlink *nfnl,
|
||||
sd_netlink_message **ret,
|
||||
int family,
|
||||
const char *chain) {
|
||||
|
||||
_cleanup_(sd_netlink_message_unrefp) sd_netlink_message *m = NULL;
|
||||
int r;
|
||||
|
||||
/* -t nat -A POSTROUTING -p protocol -s source/pflen -o out_interface -d destination/pflen -j MASQUERADE */
|
||||
|
||||
assert(nfnl);
|
||||
assert(ret);
|
||||
assert(IN_SET(family, AF_INET, AF_INET6));
|
||||
assert(chain);
|
||||
|
||||
r = sd_nfnl_nft_message_new_rule(nfnl, &m, family, NFT_SYSTEMD_TABLE_NAME, chain);
|
||||
if (r < 0)
|
||||
return r;
|
||||
@ -358,12 +458,17 @@ static int sd_nfnl_message_new_masq_rule(sd_netlink *nfnl, sd_netlink_message **
|
||||
r = sd_netlink_message_close_container(m); /* NFTA_RULE_EXPRESSIONS */
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
*ret = TAKE_PTR(m);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int sd_nfnl_message_new_dnat_rule_pre(sd_netlink *nfnl, sd_netlink_message **ret, int family,
|
||||
const char *chain) {
|
||||
static int sd_nfnl_message_new_dnat_rule_pre(
|
||||
sd_netlink *nfnl,
|
||||
sd_netlink_message **ret,
|
||||
int family,
|
||||
const char *chain) {
|
||||
|
||||
_cleanup_(sd_netlink_message_unrefp) sd_netlink_message *m = NULL;
|
||||
enum nft_registers proto_reg;
|
||||
uint32_t local = RTN_LOCAL;
|
||||
@ -372,6 +477,11 @@ static int sd_nfnl_message_new_dnat_rule_pre(sd_netlink *nfnl, sd_netlink_messag
|
||||
/* -t nat -A PREROUTING -p protocol --dport local_port -i in_interface -s source/pflen
|
||||
* -d destination/pflen -j DNAT --to-destination remote_addr:remote_port */
|
||||
|
||||
assert(nfnl);
|
||||
assert(ret);
|
||||
assert(IN_SET(family, AF_INET, AF_INET6));
|
||||
assert(chain);
|
||||
|
||||
r = sd_nfnl_nft_message_new_rule(nfnl, &m, family, NFT_SYSTEMD_TABLE_NAME, chain);
|
||||
if (r < 0)
|
||||
return r;
|
||||
@ -401,8 +511,7 @@ static int sd_nfnl_message_new_dnat_rule_pre(sd_netlink *nfnl, sd_netlink_messag
|
||||
return r;
|
||||
|
||||
/* 3rd statement: lookup 'l4proto . dport', e.g. 'tcp . 22' as key and
|
||||
* store address and port for the dnat mapping in REG1/REG2.
|
||||
*/
|
||||
* store address and port for the dnat mapping in REG1/REG2. */
|
||||
r = nfnl_add_expr_lookup_map(m, NFT_SYSTEMD_DNAT_MAP_NAME, NFT_REG32_01, NFT_REG32_01);
|
||||
if (r < 0)
|
||||
return r;
|
||||
@ -415,18 +524,27 @@ static int sd_nfnl_message_new_dnat_rule_pre(sd_netlink *nfnl, sd_netlink_messag
|
||||
r = sd_netlink_message_close_container(m); /* NFTA_RULE_EXPRESSIONS */
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
*ret = TAKE_PTR(m);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int sd_nfnl_message_new_dnat_rule_out(sd_netlink *nfnl, sd_netlink_message **ret,
|
||||
int family, const char *chain) {
|
||||
static const uint32_t zero = 0, one = 1;
|
||||
static int sd_nfnl_message_new_dnat_rule_out(
|
||||
sd_netlink *nfnl,
|
||||
sd_netlink_message **ret,
|
||||
int family,
|
||||
const char *chain) {
|
||||
|
||||
static const uint32_t zero = 0, one = 1;
|
||||
_cleanup_(sd_netlink_message_unrefp) sd_netlink_message *m = NULL;
|
||||
enum nft_registers proto_reg;
|
||||
int r;
|
||||
|
||||
assert(nfnl);
|
||||
assert(ret);
|
||||
assert(IN_SET(family, AF_INET, AF_INET6));
|
||||
assert(chain);
|
||||
|
||||
r = sd_nfnl_nft_message_new_rule(nfnl, &m, family, NFT_SYSTEMD_TABLE_NAME, chain);
|
||||
if (r < 0)
|
||||
return r;
|
||||
@ -488,8 +606,7 @@ static int sd_nfnl_message_new_dnat_rule_out(sd_netlink *nfnl, sd_netlink_messag
|
||||
* the new destination ip and port number.
|
||||
*
|
||||
* reg1 and reg2 are clobbered and will then contain the new
|
||||
* address/port number.
|
||||
*/
|
||||
* address/port number. */
|
||||
r = nfnl_add_expr_lookup_map(m, NFT_SYSTEMD_DNAT_MAP_NAME, NFT_REG32_01, NFT_REG32_01);
|
||||
if (r < 0)
|
||||
return r;
|
||||
@ -504,18 +621,29 @@ static int sd_nfnl_message_new_dnat_rule_out(sd_netlink *nfnl, sd_netlink_messag
|
||||
r = sd_netlink_message_close_container(m); /* NFTA_RULE_EXPRESSIONS */
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
*ret = TAKE_PTR(m);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int nft_new_set(struct sd_netlink *nfnl,
|
||||
sd_netlink_message **ret,
|
||||
int family, const char *set_name,
|
||||
uint32_t set_id,
|
||||
uint32_t flags, uint32_t type, uint32_t klen) {
|
||||
static int nft_new_set(
|
||||
struct sd_netlink *nfnl,
|
||||
sd_netlink_message **ret,
|
||||
int family,
|
||||
const char *set_name,
|
||||
uint32_t set_id,
|
||||
uint32_t flags,
|
||||
uint32_t type,
|
||||
uint32_t klen) {
|
||||
|
||||
_cleanup_(sd_netlink_message_unrefp) sd_netlink_message *m = NULL;
|
||||
int r;
|
||||
|
||||
assert(nfnl);
|
||||
assert(ret);
|
||||
assert(IN_SET(family, AF_INET, AF_INET6));
|
||||
assert(set_name);
|
||||
|
||||
r = sd_nfnl_nft_message_new_set(nfnl, &m, family, NFT_SYSTEMD_TABLE_NAME, set_name, set_id, klen);
|
||||
if (r < 0)
|
||||
return r;
|
||||
@ -534,13 +662,26 @@ static int nft_new_set(struct sd_netlink *nfnl,
|
||||
return r;
|
||||
}
|
||||
|
||||
static int nft_new_map(struct sd_netlink *nfnl,
|
||||
sd_netlink_message **ret,
|
||||
int family, const char *set_name, uint32_t set_id,
|
||||
uint32_t flags, uint32_t type, uint32_t klen, uint32_t dtype, uint32_t dlen) {
|
||||
static int nft_new_map(
|
||||
struct sd_netlink *nfnl,
|
||||
sd_netlink_message **ret,
|
||||
int family,
|
||||
const char *set_name,
|
||||
uint32_t set_id,
|
||||
uint32_t flags,
|
||||
uint32_t type,
|
||||
uint32_t klen,
|
||||
uint32_t dtype,
|
||||
uint32_t dlen) {
|
||||
|
||||
_cleanup_(sd_netlink_message_unrefp) sd_netlink_message *m = NULL;
|
||||
int r;
|
||||
|
||||
assert(nfnl);
|
||||
assert(ret);
|
||||
assert(IN_SET(family, AF_INET, AF_INET6));
|
||||
assert(set_name);
|
||||
|
||||
r = nft_new_set(nfnl, &m, family, set_name, set_id, flags | NFT_SET_MAP, type, klen);
|
||||
if (r < 0)
|
||||
return r;
|
||||
@ -552,17 +693,31 @@ static int nft_new_map(struct sd_netlink *nfnl,
|
||||
r = sd_netlink_message_append_u32(m, NFTA_SET_DATA_LEN, htobe32(dlen));
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
*ret = TAKE_PTR(m);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int nft_add_element(sd_netlink *nfnl, sd_netlink_message **ret,
|
||||
int family, const char *set_name,
|
||||
const void *key, uint32_t klen,
|
||||
const void *data, uint32_t dlen) {
|
||||
static int nft_add_element(
|
||||
sd_netlink *nfnl,
|
||||
sd_netlink_message **ret,
|
||||
int family,
|
||||
const char *set_name,
|
||||
const void *key,
|
||||
uint32_t klen,
|
||||
const void *data,
|
||||
uint32_t dlen) {
|
||||
|
||||
_cleanup_(sd_netlink_message_unrefp) sd_netlink_message *m = NULL;
|
||||
int r;
|
||||
|
||||
assert(nfnl);
|
||||
assert(ret);
|
||||
assert(IN_SET(family, AF_INET, AF_INET6));
|
||||
assert(set_name);
|
||||
assert(key);
|
||||
assert(data);
|
||||
|
||||
/*
|
||||
* Ideally there would be an API that provides:
|
||||
*
|
||||
@ -588,17 +743,31 @@ static int nft_add_element(sd_netlink *nfnl, sd_netlink_message **ret,
|
||||
r = sd_nfnl_nft_message_add_setelem_end(m);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
*ret = TAKE_PTR(m);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int nft_del_element(sd_netlink *nfnl,
|
||||
sd_netlink_message **ret, int family, const char *set_name,
|
||||
const void *key, uint32_t klen,
|
||||
const void *data, uint32_t dlen) {
|
||||
static int nft_del_element(
|
||||
sd_netlink *nfnl,
|
||||
sd_netlink_message **ret,
|
||||
int family,
|
||||
const char *set_name,
|
||||
const void *key,
|
||||
uint32_t klen,
|
||||
const void *data,
|
||||
uint32_t dlen) {
|
||||
|
||||
_cleanup_(sd_netlink_message_unrefp) sd_netlink_message *m = NULL;
|
||||
int r;
|
||||
|
||||
assert(nfnl);
|
||||
assert(ret);
|
||||
assert(IN_SET(family, AF_INET, AF_INET6));
|
||||
assert(set_name);
|
||||
assert(key);
|
||||
assert(data);
|
||||
|
||||
r = sd_nfnl_nft_message_del_setelems_begin(nfnl, &m, family, NFT_SYSTEMD_TABLE_NAME, set_name);
|
||||
if (r < 0)
|
||||
return r;
|
||||
@ -610,6 +779,7 @@ static int nft_del_element(sd_netlink *nfnl,
|
||||
r = sd_nfnl_nft_message_add_setelem_end(m);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
*ret = TAKE_PTR(m);
|
||||
return 0;
|
||||
}
|
||||
@ -617,15 +787,14 @@ static int nft_del_element(sd_netlink *nfnl,
|
||||
/* This is needed so 'nft' userspace tool can properly format the contents
|
||||
* of the set/map when someone uses 'nft' to inspect their content.
|
||||
*
|
||||
* The values cannot be changed, they are part of the nft tool type identifier ABI.
|
||||
*/
|
||||
* The values cannot be changed, they are part of the nft tool type identifier ABI. */
|
||||
#define TYPE_BITS 6
|
||||
|
||||
enum nft_key_types {
|
||||
TYPE_IPADDR = 7,
|
||||
TYPE_IP6ADDR = 8,
|
||||
TYPE_IPADDR = 7,
|
||||
TYPE_IP6ADDR = 8,
|
||||
TYPE_INET_PROTOCOL = 12,
|
||||
TYPE_INET_SERVICE = 13,
|
||||
TYPE_INET_SERVICE = 13,
|
||||
};
|
||||
|
||||
static uint32_t concat_types2(enum nft_key_types a, enum nft_key_types b) {
|
||||
@ -637,51 +806,42 @@ static uint32_t concat_types2(enum nft_key_types a, enum nft_key_types b) {
|
||||
return type;
|
||||
}
|
||||
|
||||
/* enough space to hold netlink messages for table skeleton */
|
||||
#define NFT_INIT_MSGS 16
|
||||
static int fw_nftables_init_family(sd_netlink *nfnl, int family) {
|
||||
sd_netlink_message *batch[NFT_INIT_MSGS] = {};
|
||||
size_t msgcnt = 0, i, ip_type_size;
|
||||
sd_netlink_message *messages[12] = {};
|
||||
_unused_ _cleanup_(netlink_message_unref_manyp) sd_netlink_message **unref = messages;
|
||||
size_t msgcnt = 0, ip_type_size;
|
||||
uint32_t set_id = 0;
|
||||
int ip_type, r;
|
||||
|
||||
assert(nfnl);
|
||||
assert(IN_SET(family, AF_INET, AF_INET6));
|
||||
|
||||
r = sd_nfnl_message_batch_begin(nfnl, &batch[msgcnt]);
|
||||
r = sd_nfnl_message_batch_begin(nfnl, &messages[msgcnt++]);
|
||||
if (r < 0)
|
||||
goto out_unref;
|
||||
return r;
|
||||
|
||||
msgcnt++;
|
||||
assert(msgcnt < NFT_INIT_MSGS);
|
||||
/* Set F_EXCL so table add fails if the table already exists. */
|
||||
r = sd_nfnl_nft_message_new_table(nfnl, &batch[msgcnt], family, NFT_SYSTEMD_TABLE_NAME);
|
||||
r = sd_nfnl_nft_message_new_table(nfnl, &messages[msgcnt++], family, NFT_SYSTEMD_TABLE_NAME);
|
||||
if (r < 0)
|
||||
goto out_unref;
|
||||
return r;
|
||||
|
||||
msgcnt++;
|
||||
assert(msgcnt < NFT_INIT_MSGS);
|
||||
|
||||
r = sd_nfnl_nft_message_new_basechain(nfnl, &batch[msgcnt], family, NFT_SYSTEMD_TABLE_NAME,
|
||||
r = sd_nfnl_nft_message_new_basechain(nfnl, &messages[msgcnt++], family, NFT_SYSTEMD_TABLE_NAME,
|
||||
"prerouting", "nat",
|
||||
NF_INET_PRE_ROUTING, NF_IP_PRI_NAT_DST + 1);
|
||||
if (r < 0)
|
||||
goto out_unref;
|
||||
return r;
|
||||
|
||||
msgcnt++;
|
||||
assert(msgcnt < NFT_INIT_MSGS);
|
||||
r = sd_nfnl_nft_message_new_basechain(nfnl, &batch[msgcnt], family, NFT_SYSTEMD_TABLE_NAME,
|
||||
r = sd_nfnl_nft_message_new_basechain(nfnl, &messages[msgcnt++], family, NFT_SYSTEMD_TABLE_NAME,
|
||||
"output", "nat",
|
||||
NF_INET_LOCAL_OUT, NF_IP_PRI_NAT_DST + 1);
|
||||
if (r < 0)
|
||||
goto out_unref;
|
||||
return r;
|
||||
|
||||
msgcnt++;
|
||||
assert(msgcnt < NFT_INIT_MSGS);
|
||||
r = sd_nfnl_nft_message_new_basechain(nfnl, &batch[msgcnt], family, NFT_SYSTEMD_TABLE_NAME,
|
||||
r = sd_nfnl_nft_message_new_basechain(nfnl, &messages[msgcnt++], family, NFT_SYSTEMD_TABLE_NAME,
|
||||
"postrouting", "nat",
|
||||
NF_INET_POST_ROUTING, NF_IP_PRI_NAT_SRC + 1);
|
||||
if (r < 0)
|
||||
goto out_unref;
|
||||
return r;
|
||||
|
||||
if (family == AF_INET) {
|
||||
ip_type_size = sizeof(uint32_t);
|
||||
@ -691,12 +851,10 @@ static int fw_nftables_init_family(sd_netlink *nfnl, int family) {
|
||||
ip_type_size = sizeof(struct in6_addr);
|
||||
ip_type = TYPE_IP6ADDR;
|
||||
}
|
||||
msgcnt++;
|
||||
assert(msgcnt < NFT_INIT_MSGS);
|
||||
/* set to store ip address ranges we should masquerade for */
|
||||
r = nft_new_set(nfnl, &batch[msgcnt], family, NFT_SYSTEMD_MASQ_SET_NAME, ++set_id, NFT_SET_INTERVAL, ip_type, ip_type_size);
|
||||
r = nft_new_set(nfnl, &messages[msgcnt++], family, NFT_SYSTEMD_MASQ_SET_NAME, ++set_id, NFT_SET_INTERVAL, ip_type, ip_type_size);
|
||||
if (r < 0)
|
||||
goto out_unref;
|
||||
return r;
|
||||
|
||||
/*
|
||||
* map to store ip address:port pair to dnat to. elements in concatenation
|
||||
@ -705,54 +863,43 @@ static int fw_nftables_init_family(sd_netlink *nfnl, int family) {
|
||||
* Example: ip protocol . tcp daddr is sizeof(uint32_t) + sizeof(uint32_t), not
|
||||
* sizeof(uint8_t) + sizeof(uint16_t).
|
||||
*/
|
||||
msgcnt++;
|
||||
assert(msgcnt < NFT_INIT_MSGS);
|
||||
r = nft_new_map(nfnl, &batch[msgcnt], family, NFT_SYSTEMD_DNAT_MAP_NAME, ++set_id, 0,
|
||||
r = nft_new_map(nfnl, &messages[msgcnt++], family, NFT_SYSTEMD_DNAT_MAP_NAME, ++set_id, 0,
|
||||
concat_types2(TYPE_INET_PROTOCOL, TYPE_INET_SERVICE), sizeof(uint32_t) * 2,
|
||||
concat_types2(ip_type, TYPE_INET_SERVICE), ip_type_size + sizeof(uint32_t));
|
||||
if (r < 0)
|
||||
goto out_unref;
|
||||
return r;
|
||||
|
||||
msgcnt++;
|
||||
assert(msgcnt < NFT_INIT_MSGS);
|
||||
r = sd_nfnl_message_new_dnat_rule_pre(nfnl, &batch[msgcnt], family, "prerouting");
|
||||
r = sd_nfnl_message_new_dnat_rule_pre(nfnl, &messages[msgcnt++], family, "prerouting");
|
||||
if (r < 0)
|
||||
goto out_unref;
|
||||
return r;
|
||||
|
||||
msgcnt++;
|
||||
assert(msgcnt < NFT_INIT_MSGS);
|
||||
r = sd_nfnl_message_new_dnat_rule_out(nfnl, &batch[msgcnt], family, "output");
|
||||
r = sd_nfnl_message_new_dnat_rule_out(nfnl, &messages[msgcnt++], family, "output");
|
||||
if (r < 0)
|
||||
goto out_unref;
|
||||
return r;
|
||||
|
||||
msgcnt++;
|
||||
r = sd_nfnl_message_new_masq_rule(nfnl, &batch[msgcnt], family, "postrouting");
|
||||
r = sd_nfnl_message_new_masq_rule(nfnl, &messages[msgcnt++], family, "postrouting");
|
||||
if (r < 0)
|
||||
goto out_unref;
|
||||
return r;
|
||||
|
||||
msgcnt++;
|
||||
assert(msgcnt < NFT_INIT_MSGS);
|
||||
r = sd_nfnl_message_batch_end(nfnl, &batch[msgcnt]);
|
||||
r = sd_nfnl_message_batch_end(nfnl, &messages[msgcnt++]);
|
||||
if (r < 0)
|
||||
goto out_unref;
|
||||
return r;
|
||||
|
||||
msgcnt++;
|
||||
assert(msgcnt <= NFT_INIT_MSGS);
|
||||
r = nfnl_netlink_sendv(nfnl, batch, msgcnt);
|
||||
if (r == -EEXIST)
|
||||
r = 0;
|
||||
assert(msgcnt < ELEMENTSOF(messages));
|
||||
r = nfnl_netlink_sendv(nfnl, messages, msgcnt);
|
||||
if (r < 0 && r != -EEXIST)
|
||||
return r;
|
||||
|
||||
out_unref:
|
||||
for (i = 0; i < msgcnt; i++)
|
||||
sd_netlink_message_unref(batch[i]);
|
||||
|
||||
return r;
|
||||
return 0;
|
||||
}
|
||||
|
||||
int fw_nftables_init(FirewallContext *ctx) {
|
||||
_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;
|
||||
@ -772,17 +919,24 @@ int fw_nftables_init(FirewallContext *ctx) {
|
||||
}
|
||||
|
||||
void fw_nftables_exit(FirewallContext *ctx) {
|
||||
assert(ctx);
|
||||
|
||||
ctx->nfnl = sd_netlink_unref(ctx->nfnl);
|
||||
}
|
||||
|
||||
static int nft_message_add_setelem_iprange(sd_netlink_message *m,
|
||||
const union in_addr_union *source,
|
||||
unsigned int prefixlen) {
|
||||
static int nft_message_add_setelem_iprange(
|
||||
sd_netlink_message *m,
|
||||
const union in_addr_union *source,
|
||||
unsigned int prefixlen) {
|
||||
|
||||
uint32_t mask, start, end;
|
||||
unsigned int nplen;
|
||||
int r;
|
||||
|
||||
assert(m);
|
||||
assert(source);
|
||||
assert(prefixlen <= 32);
|
||||
|
||||
nplen = 32 - prefixlen;
|
||||
|
||||
mask = (1U << nplen) - 1U;
|
||||
@ -810,11 +964,7 @@ static int nft_message_add_setelem_iprange(sd_netlink_message *m,
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
r = sd_nfnl_nft_message_add_setelem_end(m);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
return 0;
|
||||
return sd_nfnl_nft_message_add_setelem_end(m);
|
||||
}
|
||||
|
||||
static int nft_message_add_setelem_ip6range(
|
||||
@ -825,6 +975,9 @@ static int nft_message_add_setelem_ip6range(
|
||||
union in_addr_union start, end;
|
||||
int r;
|
||||
|
||||
assert(m);
|
||||
assert(source);
|
||||
|
||||
r = in_addr_prefix_range(AF_INET6, source, prefixlen, &start, &end);
|
||||
if (r < 0)
|
||||
return r;
|
||||
@ -848,56 +1001,55 @@ static int nft_message_add_setelem_ip6range(
|
||||
return sd_nfnl_nft_message_add_setelem_end(m);
|
||||
}
|
||||
|
||||
#define NFT_MASQ_MSGS 3
|
||||
|
||||
static int fw_nftables_add_masquerade_internal(
|
||||
FirewallContext *ctx,
|
||||
sd_netlink *nfnl,
|
||||
bool add,
|
||||
int af,
|
||||
const union in_addr_union *source,
|
||||
unsigned int source_prefixlen) {
|
||||
|
||||
sd_netlink_message *transaction[NFT_MASQ_MSGS] = {};
|
||||
size_t tsize;
|
||||
sd_netlink_message *messages[4] = {};
|
||||
_unused_ _cleanup_(netlink_message_unref_manyp) sd_netlink_message **unref = messages;
|
||||
size_t msgcnt = 0;
|
||||
int r;
|
||||
|
||||
assert(nfnl);
|
||||
assert(IN_SET(af, AF_INET, AF_INET6));
|
||||
|
||||
if (!source || source_prefixlen == 0)
|
||||
return -EINVAL;
|
||||
|
||||
if (af == AF_INET6 && source_prefixlen < 8)
|
||||
return -EINVAL;
|
||||
|
||||
r = sd_nfnl_message_batch_begin(ctx->nfnl, &transaction[0]);
|
||||
r = sd_nfnl_message_batch_begin(nfnl, &messages[msgcnt++]);
|
||||
if (r < 0)
|
||||
return r;
|
||||
tsize = 1;
|
||||
|
||||
if (add)
|
||||
r = sd_nfnl_nft_message_new_setelems_begin(ctx->nfnl, &transaction[tsize], af, NFT_SYSTEMD_TABLE_NAME, NFT_SYSTEMD_MASQ_SET_NAME);
|
||||
r = sd_nfnl_nft_message_new_setelems_begin(nfnl, &messages[msgcnt++], af, NFT_SYSTEMD_TABLE_NAME, NFT_SYSTEMD_MASQ_SET_NAME);
|
||||
else
|
||||
r = sd_nfnl_nft_message_del_setelems_begin(ctx->nfnl, &transaction[tsize], af, NFT_SYSTEMD_TABLE_NAME, NFT_SYSTEMD_MASQ_SET_NAME);
|
||||
r = sd_nfnl_nft_message_del_setelems_begin(nfnl, &messages[msgcnt++], af, NFT_SYSTEMD_TABLE_NAME, NFT_SYSTEMD_MASQ_SET_NAME);
|
||||
if (r < 0)
|
||||
goto out_unref;
|
||||
return r;
|
||||
|
||||
if (af == AF_INET)
|
||||
r = nft_message_add_setelem_iprange(transaction[tsize], source, source_prefixlen);
|
||||
r = nft_message_add_setelem_iprange(messages[msgcnt-1], source, source_prefixlen);
|
||||
else
|
||||
r = nft_message_add_setelem_ip6range(transaction[tsize], source, source_prefixlen);
|
||||
if (r < 0)
|
||||
goto out_unref;
|
||||
|
||||
++tsize;
|
||||
assert(tsize < NFT_MASQ_MSGS);
|
||||
r = sd_nfnl_message_batch_end(ctx->nfnl, &transaction[tsize]);
|
||||
r = nft_message_add_setelem_ip6range(messages[msgcnt-1], source, source_prefixlen);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
++tsize;
|
||||
r = nfnl_netlink_sendv(ctx->nfnl, transaction, tsize);
|
||||
r = sd_nfnl_message_batch_end(nfnl, &messages[msgcnt++]);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
out_unref:
|
||||
while (tsize > 0)
|
||||
sd_netlink_message_unref(transaction[--tsize]);
|
||||
return r < 0 ? r : 0;
|
||||
assert(msgcnt < ELEMENTSOF(messages));
|
||||
r = nfnl_netlink_sendv(nfnl, messages, msgcnt);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int fw_nftables_add_masquerade(
|
||||
@ -909,10 +1061,14 @@ int fw_nftables_add_masquerade(
|
||||
|
||||
int r;
|
||||
|
||||
assert(ctx);
|
||||
assert(ctx->nfnl);
|
||||
assert(IN_SET(af, AF_INET, AF_INET6));
|
||||
|
||||
if (!socket_ipv6_is_supported() && af == AF_INET6)
|
||||
return -EOPNOTSUPP;
|
||||
|
||||
r = fw_nftables_add_masquerade_internal(ctx, add, af, source, source_prefixlen);
|
||||
r = fw_nftables_add_masquerade_internal(ctx->nfnl, add, af, source, source_prefixlen);
|
||||
if (r != -ENOENT)
|
||||
return r;
|
||||
|
||||
@ -937,13 +1093,11 @@ int fw_nftables_add_masquerade(
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
return fw_nftables_add_masquerade_internal(ctx, add, af, source, source_prefixlen);
|
||||
return fw_nftables_add_masquerade_internal(ctx->nfnl, add, af, source, source_prefixlen);
|
||||
}
|
||||
|
||||
#define NFT_DNAT_MSGS 4
|
||||
|
||||
static int fw_nftables_add_local_dnat_internal(
|
||||
FirewallContext *ctx,
|
||||
sd_netlink *nfnl,
|
||||
bool add,
|
||||
int af,
|
||||
int protocol,
|
||||
@ -952,13 +1106,16 @@ static int fw_nftables_add_local_dnat_internal(
|
||||
uint16_t remote_port,
|
||||
const union in_addr_union *previous_remote) {
|
||||
|
||||
sd_netlink_message *transaction[NFT_DNAT_MSGS] = {};
|
||||
sd_netlink_message *messages[5] = {};
|
||||
_unused_ _cleanup_(netlink_message_unref_manyp) sd_netlink_message **unref = messages;
|
||||
static bool ipv6_supported = true;
|
||||
uint32_t data[5], key[2], dlen;
|
||||
size_t tsize;
|
||||
size_t msgcnt = 0;
|
||||
int r;
|
||||
|
||||
assert(nfnl);
|
||||
assert(add || !previous_remote);
|
||||
assert(IN_SET(af, AF_INET, AF_INET6));
|
||||
|
||||
if (!ipv6_supported && af == AF_INET6)
|
||||
return -EOPNOTSUPP;
|
||||
@ -987,11 +1144,10 @@ static int fw_nftables_add_local_dnat_internal(
|
||||
data[4] = htobe16(remote_port);
|
||||
}
|
||||
|
||||
r = sd_nfnl_message_batch_begin(ctx->nfnl, &transaction[0]);
|
||||
r = sd_nfnl_message_batch_begin(nfnl, &messages[msgcnt++]);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
tsize = 1;
|
||||
/* If a previous remote is set, remove its entry */
|
||||
if (add && previous_remote && !in_addr_equal(af, previous_remote, remote)) {
|
||||
if (af == AF_INET)
|
||||
@ -999,11 +1155,9 @@ static int fw_nftables_add_local_dnat_internal(
|
||||
else
|
||||
memcpy(data, &previous_remote->in6, sizeof(previous_remote->in6));
|
||||
|
||||
r = nft_del_element(ctx->nfnl, &transaction[tsize], af, NFT_SYSTEMD_DNAT_MAP_NAME, key, sizeof(key), data, dlen);
|
||||
r = nft_del_element(nfnl, &messages[msgcnt++], af, NFT_SYSTEMD_DNAT_MAP_NAME, key, sizeof(key), data, dlen);
|
||||
if (r < 0)
|
||||
goto out_unref;
|
||||
|
||||
tsize++;
|
||||
return r;
|
||||
}
|
||||
|
||||
if (af == AF_INET)
|
||||
@ -1011,39 +1165,31 @@ static int fw_nftables_add_local_dnat_internal(
|
||||
else
|
||||
memcpy(data, &remote->in6, sizeof(remote->in6));
|
||||
|
||||
assert(tsize < NFT_DNAT_MSGS);
|
||||
if (add)
|
||||
r = nft_add_element(ctx->nfnl, &transaction[tsize], af, NFT_SYSTEMD_DNAT_MAP_NAME, key, sizeof(key), data, dlen);
|
||||
r = nft_add_element(nfnl, &messages[msgcnt++], af, NFT_SYSTEMD_DNAT_MAP_NAME, key, sizeof(key), data, dlen);
|
||||
else
|
||||
r = nft_del_element(ctx->nfnl, &transaction[tsize], af, NFT_SYSTEMD_DNAT_MAP_NAME, key, sizeof(key), data, dlen);
|
||||
r = nft_del_element(nfnl, &messages[msgcnt++], af, NFT_SYSTEMD_DNAT_MAP_NAME, key, sizeof(key), data, dlen);
|
||||
if (r < 0)
|
||||
goto out_unref;
|
||||
return r;
|
||||
|
||||
tsize++;
|
||||
assert(tsize < NFT_DNAT_MSGS);
|
||||
|
||||
r = sd_nfnl_message_batch_end(ctx->nfnl, &transaction[tsize]);
|
||||
r = sd_nfnl_message_batch_end(nfnl, &messages[msgcnt++]);
|
||||
if (r < 0)
|
||||
goto out_unref;
|
||||
return r;
|
||||
|
||||
tsize++;
|
||||
assert(tsize <= NFT_DNAT_MSGS);
|
||||
|
||||
r = nfnl_netlink_sendv(ctx->nfnl, transaction, tsize);
|
||||
assert(msgcnt < ELEMENTSOF(messages));
|
||||
r = nfnl_netlink_sendv(nfnl, messages, msgcnt);
|
||||
if (r == -EOVERFLOW && af == AF_INET6) {
|
||||
/* The current implementation of DNAT in systemd requires kernel's
|
||||
* fdb9c405e35bdc6e305b9b4e20ebc141ed14fc81 (v5.8), and the older kernel returns
|
||||
* -EOVERFLOW. Let's treat the error as -EOPNOTSUPP. */
|
||||
log_debug_errno(r, "The current implementation of IPv6 DNAT in systemd requires kernel 5.8 or newer, ignoring: %m");
|
||||
ipv6_supported = false;
|
||||
r = -EOPNOTSUPP;
|
||||
return -EOPNOTSUPP;
|
||||
}
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
out_unref:
|
||||
while (tsize > 0)
|
||||
sd_netlink_message_unref(transaction[--tsize]);
|
||||
|
||||
return r < 0 ? r : 0;
|
||||
return 0;
|
||||
}
|
||||
|
||||
int fw_nftables_add_local_dnat(
|
||||
@ -1058,10 +1204,14 @@ int fw_nftables_add_local_dnat(
|
||||
|
||||
int r;
|
||||
|
||||
assert(ctx);
|
||||
assert(ctx->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, add, af, protocol, local_port, remote, remote_port, previous_remote);
|
||||
r = fw_nftables_add_local_dnat_internal(ctx->nfnl, add, af, protocol, local_port, remote, remote_port, previous_remote);
|
||||
if (r != -ENOENT)
|
||||
return r;
|
||||
|
||||
@ -1071,5 +1221,5 @@ int fw_nftables_add_local_dnat(
|
||||
return r;
|
||||
|
||||
/* table created anew; previous address already gone */
|
||||
return fw_nftables_add_local_dnat_internal(ctx, add, af, protocol, local_port, remote, remote_port, NULL);
|
||||
return fw_nftables_add_local_dnat_internal(ctx->nfnl, add, af, protocol, local_port, remote, remote_port, NULL);
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user