summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorPhil Sutter <phil@nwl.cc>2023-01-31 19:55:57 +0100
committerPhil Sutter <phil@nwl.cc>2023-08-10 13:44:12 +0200
commit2a6eee89083c837ac429b0e5aba33bdcaeb51a57 (patch)
tree58d444fd7ec52e20f8da9f1506e573c323f78785
parentbb7d5fde80ccb4672dcf9644b4ccf1bffc0919fd (diff)
nft-ruleparse: Introduce nft_create_target()
Like nft_create_match(), this is a small wrapper around the typical target extension lookup and (standard) init code. To use it from nft_parse_target() and nft_parse_log(), introduce an inner variant which accepts the target payload size as parameter. The call to rule_parse_ops::target callback was problematic with standard target, because the callbacks initialized iptables_command_state::jumpto with the target name, "standard" in that case. Perform its tasks in nft_create_target(), keep it only for bridge family's special handling of watcher "targets". Signed-off-by: Phil Sutter <phil@nwl.cc>
-rw-r--r--iptables/nft-ruleparse-arp.c1
-rw-r--r--iptables/nft-ruleparse-bridge.c5
-rw-r--r--iptables/nft-ruleparse-ipv4.c1
-rw-r--r--iptables/nft-ruleparse-ipv6.c1
-rw-r--r--iptables/nft-ruleparse.c126
-rw-r--r--iptables/nft-ruleparse.h5
6 files changed, 52 insertions, 87 deletions
diff --git a/iptables/nft-ruleparse-arp.c b/iptables/nft-ruleparse-arp.c
index b68fb06d..d80ca922 100644
--- a/iptables/nft-ruleparse-arp.c
+++ b/iptables/nft-ruleparse-arp.c
@@ -164,5 +164,4 @@ static void nft_arp_parse_payload(struct nft_xt_ctx *ctx,
struct nft_ruleparse_ops nft_ruleparse_ops_arp = {
.meta = nft_arp_parse_meta,
.payload = nft_arp_parse_payload,
- .target = nft_ipv46_parse_target,
};
diff --git a/iptables/nft-ruleparse-bridge.c b/iptables/nft-ruleparse-bridge.c
index 50fb9283..c6cc9af5 100644
--- a/iptables/nft-ruleparse-bridge.c
+++ b/iptables/nft-ruleparse-bridge.c
@@ -406,11 +406,10 @@ static void nft_bridge_parse_target(struct xtables_target *t,
if (strcmp(t->name, "log") == 0 ||
strcmp(t->name, "nflog") == 0) {
parse_watcher(t, &cs->match_list, false);
+ cs->jumpto = NULL;
+ cs->target = NULL;
return;
}
-
- cs->target = t;
- cs->jumpto = t->name;
}
struct nft_ruleparse_ops nft_ruleparse_ops_bridge = {
diff --git a/iptables/nft-ruleparse-ipv4.c b/iptables/nft-ruleparse-ipv4.c
index c87e159c..491cbf42 100644
--- a/iptables/nft-ruleparse-ipv4.c
+++ b/iptables/nft-ruleparse-ipv4.c
@@ -131,5 +131,4 @@ static void nft_ipv4_parse_payload(struct nft_xt_ctx *ctx,
struct nft_ruleparse_ops nft_ruleparse_ops_ipv4 = {
.meta = nft_ipv4_parse_meta,
.payload = nft_ipv4_parse_payload,
- .target = nft_ipv46_parse_target,
};
diff --git a/iptables/nft-ruleparse-ipv6.c b/iptables/nft-ruleparse-ipv6.c
index af55420b..7581b863 100644
--- a/iptables/nft-ruleparse-ipv6.c
+++ b/iptables/nft-ruleparse-ipv6.c
@@ -108,5 +108,4 @@ static void nft_ipv6_parse_payload(struct nft_xt_ctx *ctx,
struct nft_ruleparse_ops nft_ruleparse_ops_ipv6 = {
.meta = nft_ipv6_parse_meta,
.payload = nft_ipv6_parse_payload,
- .target = nft_ipv46_parse_target,
};
diff --git a/iptables/nft-ruleparse.c b/iptables/nft-ruleparse.c
index edbbfa40..a5eb6d09 100644
--- a/iptables/nft-ruleparse.c
+++ b/iptables/nft-ruleparse.c
@@ -84,6 +84,40 @@ nft_create_match(struct nft_xt_ctx *ctx,
return match->m->data;
}
+static void *
+__nft_create_target(struct nft_xt_ctx *ctx, const char *name, size_t tgsize)
+{
+ struct xtables_target *target;
+ size_t size;
+
+ target = xtables_find_target(name, XTF_TRY_LOAD);
+ if (!target)
+ return NULL;
+
+ size = XT_ALIGN(sizeof(*target->t)) + tgsize ?: target->size;
+
+ target->t = xtables_calloc(1, size);
+ target->t->u.target_size = size;
+ target->t->u.user.revision = target->revision;
+ strcpy(target->t->u.user.name, name);
+
+ xs_init_target(target);
+
+ ctx->cs->jumpto = name;
+ ctx->cs->target = target;
+
+ if (ctx->h->ops->rule_parse->target)
+ ctx->h->ops->rule_parse->target(target, ctx->cs);
+
+ return target->t->data;
+}
+
+void *
+nft_create_target(struct nft_xt_ctx *ctx, const char *name)
+{
+ return __nft_create_target(ctx, name, 0);
+}
+
static void nft_parse_counter(struct nftnl_expr *e, struct xt_counters *counters)
{
counters->pcnt = nftnl_expr_get_u64(e, NFTNL_EXPR_CTR_PACKETS);
@@ -123,11 +157,8 @@ static bool nft_parse_meta_set_common(struct nft_xt_ctx* ctx,
static void nft_parse_meta_set(struct nft_xt_ctx *ctx,
struct nftnl_expr *e)
{
- struct xtables_target *target;
struct nft_xt_ctx_reg *sreg;
enum nft_registers sregnum;
- struct xt_entry_target *t;
- unsigned int size;
const char *targname;
sregnum = nftnl_expr_get_u32(e, NFTNL_EXPR_META_SREG);
@@ -153,22 +184,8 @@ static void nft_parse_meta_set(struct nft_xt_ctx *ctx,
return;
}
- target = xtables_find_target(targname, XTF_TRY_LOAD);
- if (target == NULL) {
+ if (!nft_create_target(ctx, targname))
ctx->errmsg = "target TRACE not found";
- return;
- }
-
- size = XT_ALIGN(sizeof(struct xt_entry_target)) + target->size;
-
- t = xtables_calloc(1, size);
- t->u.target_size = size;
- t->u.user.revision = target->revision;
- strcpy(t->u.user.name, targname);
-
- target->t = t;
-
- ctx->h->ops->rule_parse->target(target, ctx->cs);
}
static void nft_parse_meta(struct nft_xt_ctx *ctx, struct nftnl_expr *e)
@@ -515,8 +532,6 @@ static void nft_parse_immediate(struct nft_xt_ctx *ctx, struct nftnl_expr *e)
{
const char *chain = nftnl_expr_get_str(e, NFTNL_EXPR_IMM_CHAIN);
struct iptables_command_state *cs = ctx->cs;
- struct xt_entry_target *t;
- uint32_t size;
int verdict;
if (nftnl_expr_is_set(e, NFTNL_EXPR_IMM_DATA)) {
@@ -566,18 +581,8 @@ static void nft_parse_immediate(struct nft_xt_ctx *ctx, struct nftnl_expr *e)
return;
}
- cs->target = xtables_find_target(cs->jumpto, XTF_TRY_LOAD);
- if (!cs->target) {
+ if (!nft_create_target(ctx, cs->jumpto))
ctx->errmsg = "verdict extension not found";
- return;
- }
-
- size = XT_ALIGN(sizeof(struct xt_entry_target)) + cs->target->size;
- t = xtables_calloc(1, size);
- t->u.target_size = size;
- t->u.user.revision = cs->target->revision;
- strcpy(t->u.user.name, cs->jumpto);
- cs->target->t = t;
}
static void nft_parse_match(struct nft_xt_ctx *ctx, struct nftnl_expr *e)
@@ -624,27 +629,13 @@ static void nft_parse_target(struct nft_xt_ctx *ctx, struct nftnl_expr *e)
uint32_t tg_len;
const char *targname = nftnl_expr_get_str(e, NFTNL_EXPR_TG_NAME);
const void *targinfo = nftnl_expr_get(e, NFTNL_EXPR_TG_INFO, &tg_len);
- struct xtables_target *target;
- struct xt_entry_target *t;
- size_t size;
+ void *data;
- target = xtables_find_target(targname, XTF_TRY_LOAD);
- if (target == NULL) {
+ data = __nft_create_target(ctx, targname, tg_len);
+ if (!data)
ctx->errmsg = "target extension not found";
- return;
- }
-
- size = XT_ALIGN(sizeof(struct xt_entry_target)) + tg_len;
-
- t = xtables_calloc(1, size);
- memcpy(&t->data, targinfo, tg_len);
- t->u.target_size = size;
- t->u.user.revision = nftnl_expr_get_u32(e, NFTNL_EXPR_TG_REV);
- strcpy(t->u.user.name, target->name);
-
- target->t = t;
-
- ctx->h->ops->rule_parse->target(target, ctx->cs);
+ else
+ memcpy(data, targinfo, tg_len);
}
static void nft_parse_limit(struct nft_xt_ctx *ctx, struct nftnl_expr *e)
@@ -684,9 +675,6 @@ static void nft_parse_lookup(struct nft_xt_ctx *ctx, struct nft_handle *h,
static void nft_parse_log(struct nft_xt_ctx *ctx, struct nftnl_expr *e)
{
- struct xtables_target *target;
- struct xt_entry_target *t;
- size_t target_size;
/*
* In order to handle the longer log-prefix supported by nft, instead of
* using struct xt_nflog_info, we use a struct with a compatible layout, but
@@ -703,6 +691,8 @@ static void nft_parse_log(struct nft_xt_ctx *ctx, struct nftnl_expr *e)
.group = nftnl_expr_get_u16(e, NFTNL_EXPR_LOG_GROUP),
.threshold = nftnl_expr_get_u16(e, NFTNL_EXPR_LOG_QTHRESHOLD),
};
+ void *data;
+
if (nftnl_expr_is_set(e, NFTNL_EXPR_LOG_SNAPLEN)) {
info.len = nftnl_expr_get_u32(e, NFTNL_EXPR_LOG_SNAPLEN);
info.flags = XT_NFLOG_F_COPY_LEN;
@@ -711,25 +701,12 @@ static void nft_parse_log(struct nft_xt_ctx *ctx, struct nftnl_expr *e)
snprintf(info.prefix, sizeof(info.prefix), "%s",
nftnl_expr_get_str(e, NFTNL_EXPR_LOG_PREFIX));
- target = xtables_find_target("NFLOG", XTF_TRY_LOAD);
- if (target == NULL) {
+ data = __nft_create_target(ctx, "NFLOG",
+ XT_ALIGN(sizeof(struct xt_nflog_info_nft)));
+ if (!data)
ctx->errmsg = "NFLOG target extension not found";
- return;
- }
-
- target_size = XT_ALIGN(sizeof(struct xt_entry_target)) +
- XT_ALIGN(sizeof(struct xt_nflog_info_nft));
-
- t = xtables_calloc(1, target_size);
- t->u.target_size = target_size;
- strcpy(t->u.user.name, target->name);
- t->u.user.revision = target->revision;
-
- target->t = t;
-
- memcpy(&target->t->data, &info, sizeof(info));
-
- ctx->h->ops->rule_parse->target(target, ctx->cs);
+ else
+ memcpy(data, &info, sizeof(info));
}
static void nft_parse_udp_range(struct nft_xt_ctx *ctx,
@@ -1137,13 +1114,6 @@ int parse_meta(struct nft_xt_ctx *ctx, struct nftnl_expr *e, uint8_t key,
return 0;
}
-void nft_ipv46_parse_target(struct xtables_target *t,
- struct iptables_command_state *cs)
-{
- cs->target = t;
- cs->jumpto = t->name;
-}
-
int nft_parse_hl(struct nft_xt_ctx *ctx, struct nftnl_expr *e,
struct iptables_command_state *cs)
{
diff --git a/iptables/nft-ruleparse.h b/iptables/nft-ruleparse.h
index fd083c08..25ce05d2 100644
--- a/iptables/nft-ruleparse.h
+++ b/iptables/nft-ruleparse.h
@@ -117,6 +117,8 @@ extern struct nft_ruleparse_ops nft_ruleparse_ops_ipv6;
void *nft_create_match(struct nft_xt_ctx *ctx,
struct iptables_command_state *cs,
const char *name, bool reuse);
+void *nft_create_target(struct nft_xt_ctx *ctx, const char *name);
+
bool nft_rule_to_iptables_command_state(struct nft_handle *h,
const struct nftnl_rule *r,
@@ -129,9 +131,6 @@ int parse_meta(struct nft_xt_ctx *ctx, struct nftnl_expr *e, uint8_t key,
char *iniface, unsigned char *iniface_mask, char *outiface,
unsigned char *outiface_mask, uint8_t *invflags);
-void nft_ipv46_parse_target(struct xtables_target *t,
- struct iptables_command_state *cs);
-
int nft_parse_hl(struct nft_xt_ctx *ctx, struct nftnl_expr *e,
struct iptables_command_state *cs);