summaryrefslogtreecommitdiffstats
path: root/iptables/nft-shared.c
diff options
context:
space:
mode:
authorFlorian Westphal <fw@strlen.de>2022-09-12 10:58:44 +0200
committerFlorian Westphal <fw@strlen.de>2022-09-13 14:14:38 +0200
commitb4fd0f682b53609c747e6dd69cc5024545d4b90c (patch)
tree22ffb65b47917d61393b42d6171dbb96b0ae22ce /iptables/nft-shared.c
parent0da2d1a35bd70d37f72d594927c0649d1dea4f7c (diff)
nft: support ttl/hoplimit dissection
xlate raw "nft ... ttl eq 1" and so on to the ttl/hl matches. Signed-off-by: Florian Westphal <fw@strlen.de> Reviewed-by: Phil Sutter <phil@nwl.cc>
Diffstat (limited to 'iptables/nft-shared.c')
-rw-r--r--iptables/nft-shared.c68
1 files changed, 68 insertions, 0 deletions
diff --git a/iptables/nft-shared.c b/iptables/nft-shared.c
index 79c93fe8..71e2f18d 100644
--- a/iptables/nft-shared.c
+++ b/iptables/nft-shared.c
@@ -27,6 +27,8 @@
#include <linux/netfilter/xt_mark.h>
#include <linux/netfilter/xt_pkttype.h>
+#include <linux/netfilter_ipv6/ip6t_hl.h>
+
#include <libmnl/libmnl.h>
#include <libnftnl/rule.h>
#include <libnftnl/expr.h>
@@ -1449,3 +1451,69 @@ void nft_check_xt_legacy(int family, bool is_ipt_save)
prefix, prefix, is_ipt_save ? "-save" : "");
fclose(fp);
}
+
+int nft_parse_hl(struct nft_xt_ctx *ctx,
+ struct nftnl_expr *e,
+ struct iptables_command_state *cs)
+{
+ struct xtables_match *match;
+ struct ip6t_hl_info *info;
+ uint8_t hl, mode;
+ int op;
+
+ hl = nftnl_expr_get_u8(e, NFTNL_EXPR_CMP_DATA);
+ op = nftnl_expr_get_u32(e, NFTNL_EXPR_CMP_OP);
+
+ switch (op) {
+ case NFT_CMP_NEQ:
+ mode = IP6T_HL_NE;
+ break;
+ case NFT_CMP_EQ:
+ mode = IP6T_HL_EQ;
+ break;
+ case NFT_CMP_LT:
+ mode = IP6T_HL_LT;
+ break;
+ case NFT_CMP_GT:
+ mode = IP6T_HL_GT;
+ break;
+ case NFT_CMP_LTE:
+ mode = IP6T_HL_LT;
+ if (hl == 255)
+ return -1;
+ hl++;
+ break;
+ case NFT_CMP_GTE:
+ mode = IP6T_HL_GT;
+ if (hl == 0)
+ return -1;
+ hl--;
+ break;
+ default:
+ return -1;
+ }
+
+ /* ipt_ttl_info and ip6t_hl_info have same layout,
+ * IPT_TTL_x and IP6T_HL_x are aliases as well, so
+ * just use HL for both ipv4 and ipv6.
+ */
+ switch (ctx->h->family) {
+ case NFPROTO_IPV4:
+ match = nft_create_match(ctx, ctx->cs, "ttl");
+ break;
+ case NFPROTO_IPV6:
+ match = nft_create_match(ctx, ctx->cs, "hl");
+ break;
+ default:
+ return -1;
+ }
+
+ if (!match)
+ return -1;
+
+ info = (void*)match->m->data;
+ info->hop_limit = hl;
+ info->mode = mode;
+
+ return 0;
+}