Message ID | 20210601220629.18307-2-pablo@netfilter.org |
---|---|
State | New |
Headers | show |
Series | Netfilter updates for net-next | expand |
Hello: This series was applied to netdev/net-next.git (refs/heads/master): On Wed, 2 Jun 2021 00:06:14 +0200 you wrote: > From: Phil Sutter <phil@nwl.cc> > > Chunks are SCTP header extensions similar in implementation to IPv6 > extension headers or TCP options. Reusing exthdr expression to find and > extract field values from them is therefore pretty straightforward. > > For now, this supports extracting data from chunks at a fixed offset > (and length) only - chunks themselves are an extensible data structure; > in order to make all fields available, a nested extension search is > needed. > > [...] Here is the summary with links: - [net-next,01/16] netfilter: nft_exthdr: Support SCTP chunks https://git.kernel.org/netdev/net-next/c/133dc203d77d - [net-next,02/16] netfilter: nft_set_pipapo_avx2: Skip LDMXCSR, we don't need a valid MXCSR state https://git.kernel.org/netdev/net-next/c/a58db7ad80e8 - [net-next,03/16] netfilter: add and use nft_set_do_lookup helper https://git.kernel.org/netdev/net-next/c/0974cff3eb66 - [net-next,04/16] netfilter: nf_tables: prefer direct calls for set lookups https://git.kernel.org/netdev/net-next/c/f227925e53c3 - [net-next,05/16] netfilter: Remove leading spaces in Kconfig https://git.kernel.org/netdev/net-next/c/06f029930264 - [net-next,06/16] netfilter: x_tables: improve limit_mt scalability https://git.kernel.org/netdev/net-next/c/07df3fc90a03 - [net-next,07/16] netfilter: xt_CT: Remove redundant assignment to ret https://git.kernel.org/netdev/net-next/c/02d85142670b - [net-next,08/16] netfilter: use nfnetlink_unicast() https://git.kernel.org/netdev/net-next/c/e0241ae6ac59 - [net-next,09/16] netfilter: x_tables: reduce xt_action_param by 8 byte https://git.kernel.org/netdev/net-next/c/586d5a8bcede - [net-next,10/16] netfilter: reduce size of nf_hook_state on 32bit platforms https://git.kernel.org/netdev/net-next/c/6802db48fc27 - [net-next,11/16] netfilter: nf_tables: add and use nft_sk helper https://git.kernel.org/netdev/net-next/c/85554eb981e5 - [net-next,12/16] netfilter: nf_tables: add and use nft_thoff helper https://git.kernel.org/netdev/net-next/c/2d7b4ace0754 - [net-next,13/16] netfilter: nf_tables: remove unused arg in nft_set_pktinfo_unspec() https://git.kernel.org/netdev/net-next/c/f06ad944b6a9 - [net-next,14/16] netfilter: nf_tables: remove xt_action_param from nft_pktinfo https://git.kernel.org/netdev/net-next/c/897389de4828 - [net-next,15/16] netfilter: nft_set_pipapo_avx2: fix up description warnings https://git.kernel.org/netdev/net-next/c/89258f8e4148 - [net-next,16/16] netfilter: fix clang-12 fmt string warnings https://git.kernel.org/netdev/net-next/c/8a1c08ad19b6 You are awesome, thank you! -- Deet-doot-dot, I am a bot. https://korg.docs.kernel.org/patchwork/pwbot.html
diff --git a/include/uapi/linux/netfilter/nf_tables.h b/include/uapi/linux/netfilter/nf_tables.h index 1fb4ca18ffbb..19715e2679d1 100644 --- a/include/uapi/linux/netfilter/nf_tables.h +++ b/include/uapi/linux/netfilter/nf_tables.h @@ -813,11 +813,13 @@ enum nft_exthdr_flags { * @NFT_EXTHDR_OP_IPV6: match against ipv6 extension headers * @NFT_EXTHDR_OP_TCP: match against tcp options * @NFT_EXTHDR_OP_IPV4: match against ipv4 options + * @NFT_EXTHDR_OP_SCTP: match against sctp chunks */ enum nft_exthdr_op { NFT_EXTHDR_OP_IPV6, NFT_EXTHDR_OP_TCPOPT, NFT_EXTHDR_OP_IPV4, + NFT_EXTHDR_OP_SCTP, __NFT_EXTHDR_OP_MAX }; #define NFT_EXTHDR_OP_MAX (__NFT_EXTHDR_OP_MAX - 1) diff --git a/net/netfilter/nft_exthdr.c b/net/netfilter/nft_exthdr.c index f64f0017e9a5..4d0b8e1c40c0 100644 --- a/net/netfilter/nft_exthdr.c +++ b/net/netfilter/nft_exthdr.c @@ -10,8 +10,10 @@ #include <linux/netlink.h> #include <linux/netfilter.h> #include <linux/netfilter/nf_tables.h> +#include <linux/sctp.h> #include <net/netfilter/nf_tables_core.h> #include <net/netfilter/nf_tables.h> +#include <net/sctp/sctp.h> #include <net/tcp.h> struct nft_exthdr { @@ -300,6 +302,43 @@ static void nft_exthdr_tcp_set_eval(const struct nft_expr *expr, } } +static void nft_exthdr_sctp_eval(const struct nft_expr *expr, + struct nft_regs *regs, + const struct nft_pktinfo *pkt) +{ + unsigned int offset = pkt->xt.thoff + sizeof(struct sctphdr); + struct nft_exthdr *priv = nft_expr_priv(expr); + u32 *dest = ®s->data[priv->dreg]; + const struct sctp_chunkhdr *sch; + struct sctp_chunkhdr _sch; + + do { + sch = skb_header_pointer(pkt->skb, offset, sizeof(_sch), &_sch); + if (!sch || !sch->length) + break; + + if (sch->type == priv->type) { + if (priv->flags & NFT_EXTHDR_F_PRESENT) { + nft_reg_store8(dest, true); + return; + } + if (priv->offset + priv->len > ntohs(sch->length) || + offset + ntohs(sch->length) > pkt->skb->len) + break; + + dest[priv->len / NFT_REG32_SIZE] = 0; + memcpy(dest, (char *)sch + priv->offset, priv->len); + return; + } + offset += SCTP_PAD4(ntohs(sch->length)); + } while (offset < pkt->skb->len); + + if (priv->flags & NFT_EXTHDR_F_PRESENT) + nft_reg_store8(dest, false); + else + regs->verdict.code = NFT_BREAK; +} + static const struct nla_policy nft_exthdr_policy[NFTA_EXTHDR_MAX + 1] = { [NFTA_EXTHDR_DREG] = { .type = NLA_U32 }, [NFTA_EXTHDR_TYPE] = { .type = NLA_U8 }, @@ -499,6 +538,14 @@ static const struct nft_expr_ops nft_exthdr_tcp_set_ops = { .dump = nft_exthdr_dump_set, }; +static const struct nft_expr_ops nft_exthdr_sctp_ops = { + .type = &nft_exthdr_type, + .size = NFT_EXPR_SIZE(sizeof(struct nft_exthdr)), + .eval = nft_exthdr_sctp_eval, + .init = nft_exthdr_init, + .dump = nft_exthdr_dump, +}; + static const struct nft_expr_ops * nft_exthdr_select_ops(const struct nft_ctx *ctx, const struct nlattr * const tb[]) @@ -529,6 +576,10 @@ nft_exthdr_select_ops(const struct nft_ctx *ctx, return &nft_exthdr_ipv4_ops; } break; + case NFT_EXTHDR_OP_SCTP: + if (tb[NFTA_EXTHDR_DREG]) + return &nft_exthdr_sctp_ops; + break; } return ERR_PTR(-EOPNOTSUPP);