Use meta mark + bitwise + cmp instead of nft_compat mark match. Signed-off-by: Pablo Neira Ayuso <pablo@xxxxxxxxxxxxx> --- iptables/nft-shared.c | 36 ++++++++++++++++++++++++++++++++++++ iptables/nft.c | 23 +++++++++++++++++++++++ 2 files changed, 59 insertions(+) diff --git a/iptables/nft-shared.c b/iptables/nft-shared.c index 5b13b29c9844..54a911801639 100644 --- a/iptables/nft-shared.c +++ b/iptables/nft-shared.c @@ -24,6 +24,7 @@ #include <linux/netfilter/xt_comment.h> #include <linux/netfilter/xt_limit.h> #include <linux/netfilter/xt_NFLOG.h> +#include <linux/netfilter/xt_mark.h> #include <libmnl/libmnl.h> #include <libnftnl/rule.h> @@ -261,6 +262,38 @@ static void parse_ifname(const char *name, unsigned int len, char *dst, unsigned memset(mask, 0xff, len - 2); } +static struct xtables_match * +nft_create_match(struct nft_xt_ctx *ctx, + struct iptables_command_state *cs, + const char *name); + +static int parse_meta_mark(struct nft_xt_ctx *ctx, struct nftnl_expr *e) +{ + struct xt_mark_mtinfo1 *mark; + struct xtables_match *match; + uint32_t value; + + match = nft_create_match(ctx, ctx->cs, "mark"); + if (!match) + return -1; + + mark = (void*)match->m->data; + + if (nftnl_expr_get_u32(e, NFTNL_EXPR_CMP_OP) == NFT_CMP_NEQ) + mark->invert = 1; + + value = nftnl_expr_get_u32(e, NFTNL_EXPR_CMP_DATA); + mark->mark = value; + if (ctx->flags & NFT_XT_CTX_BITWISE) { + memcpy(&mark->mask, &ctx->bitwise.mask, sizeof(mark->mask)); + ctx->flags &= ~NFT_XT_CTX_BITWISE; + } else { + mark->mask = 0xffffffff; + } + + return 0; +} + 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) @@ -304,6 +337,9 @@ int parse_meta(struct nft_xt_ctx *ctx, struct nftnl_expr *e, uint8_t key, parse_ifname(ifname, len, outiface, outiface_mask); break; + case NFT_META_MARK: + parse_meta_mark(ctx, e); + break; default: return -1; } diff --git a/iptables/nft.c b/iptables/nft.c index 6883662fa28d..a629aeff98b0 100644 --- a/iptables/nft.c +++ b/iptables/nft.c @@ -40,6 +40,7 @@ #include <linux/netfilter/xt_limit.h> #include <linux/netfilter/xt_NFLOG.h> +#include <linux/netfilter/xt_mark.h> #include <libmnl/libmnl.h> #include <libnftnl/gen.h> @@ -1406,6 +1407,26 @@ static int add_nft_tcp(struct nftnl_rule *r, struct xt_entry_match *m) tcp->dpts, tcp->invflags & XT_TCP_INV_DSTPT); } +static int add_nft_mark(struct nft_handle *h, struct nftnl_rule *r, + struct xt_entry_match *m) +{ + struct xt_mark_mtinfo1 *mark = (void *)m->data; + int op; + + add_meta(r, NFT_META_MARK); + if (mark->mask != 0xffffffff) + add_bitwise(r, (uint8_t *)&mark->mask, sizeof(uint32_t)); + + if (mark->invert) + op = NFT_CMP_NEQ; + else + op = NFT_CMP_EQ; + + add_cmp_u32(r, mark->mark, op); + + return 0; +} + int add_match(struct nft_handle *h, struct nftnl_rule *r, struct xt_entry_match *m) { @@ -1420,6 +1441,8 @@ int add_match(struct nft_handle *h, return add_nft_udp(r, m); else if (!strcmp(m->u.user.name, "tcp")) return add_nft_tcp(r, m); + else if (!strcmp(m->u.user.name, "mark")) + return add_nft_mark(h, r, m); expr = nftnl_expr_alloc("match"); if (expr == NULL) -- 2.30.2