]> git.ipfire.org Git - thirdparty/iptables.git/commitdiff
nft: support ttl/hoplimit dissection
authorFlorian Westphal <fw@strlen.de>
Mon, 12 Sep 2022 08:58:44 +0000 (10:58 +0200)
committerFlorian Westphal <fw@strlen.de>
Tue, 13 Sep 2022 12:14:38 +0000 (14:14 +0200)
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>
iptables/nft-ipv4.c
iptables/nft-ipv6.c
iptables/nft-shared.c
iptables/nft-shared.h

index 59c4a41f1a05f607537e990f09f92590ae6fd364..1865d15152960c260b76b1b4b03bc15a1359f838 100644 (file)
@@ -206,6 +206,9 @@ static void nft_ipv4_parse_payload(struct nft_xt_ctx *ctx,
                if (inv)
                        cs->fw.ip.invflags |= IPT_INV_FRAG;
                break;
+       case offsetof(struct iphdr, ttl):
+               nft_parse_hl(ctx, e, cs);
+               break;
        default:
                DEBUGP("unknown payload offset %d\n", ctx->payload.offset);
                break;
index 9a29d18bc215c789338f6932a0928e0373167d4d..0ab1f971934471e68c234959135c14497c67cebe 100644 (file)
@@ -169,6 +169,9 @@ static void nft_ipv6_parse_payload(struct nft_xt_ctx *ctx,
                cs->fw6.ipv6.proto = proto;
                if (inv)
                        cs->fw6.ipv6.invflags |= IP6T_INV_PROTO;
+       case offsetof(struct ip6_hdr, ip6_hlim):
+               nft_parse_hl(ctx, e, cs);
+               break;
        default:
                DEBUGP("unknown payload offset %d\n", ctx->payload.offset);
                break;
index 79c93fe82c602622028898153beb71a07e008beb..71e2f18dab929c683b58dd7cb581cdc3f402860a 100644 (file)
@@ -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;
+}
index b04049047116745f2dc258c7cc33288e25fa9735..0718dc23e8b7785944edd452f0460dc77c023819 100644 (file)
@@ -212,6 +212,8 @@ void xtables_restore_parse(struct nft_handle *h,
 
 void nft_check_xt_legacy(int family, bool is_ipt_save);
 
+int nft_parse_hl(struct nft_xt_ctx *ctx, struct nftnl_expr *e, struct iptables_command_state *cs);
+
 #define min(x, y) ((x) < (y) ? (x) : (y))
 #define max(x, y) ((x) > (y) ? (x) : (y))