xlate raw "nft ... ttl eq 1" and so on to the ttl/hl matches. Signed-off-by: Florian Westphal <fw@xxxxxxxxx> --- iptables/nft-ipv4.c | 3 ++ iptables/nft-ipv6.c | 3 ++ iptables/nft-shared.c | 68 +++++++++++++++++++++++++++++++++++++++++++ iptables/nft-shared.h | 2 ++ 4 files changed, 76 insertions(+) diff --git a/iptables/nft-ipv4.c b/iptables/nft-ipv4.c index 59c4a41f1a05..1865d1515296 100644 --- a/iptables/nft-ipv4.c +++ b/iptables/nft-ipv4.c @@ -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; diff --git a/iptables/nft-ipv6.c b/iptables/nft-ipv6.c index 9a29d18bc215..0ab1f9719344 100644 --- a/iptables/nft-ipv6.c +++ b/iptables/nft-ipv6.c @@ -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; diff --git a/iptables/nft-shared.c b/iptables/nft-shared.c index 79c93fe82c60..71e2f18dab92 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; +} diff --git a/iptables/nft-shared.h b/iptables/nft-shared.h index b04049047116..0718dc23e8b7 100644 --- a/iptables/nft-shared.h +++ b/iptables/nft-shared.h @@ -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)) -- 2.37.3