mirror of
https://github.com/torvalds/linux.git
synced 2024-11-22 12:11:40 +00:00
netfilter: nftables: add set expression flags
The set flag NFT_SET_EXPR provides a hint to the kernel that userspace supports for multiple expressions per set element. In the same direction, NFT_DYNSET_F_EXPR specifies that dynset expression defines multiple expressions per set element. This allows new userspace software with old kernels to bail out with EOPNOTSUPP. This update is similar toef516e8625
("netfilter: nf_tables: reintroduce the NFT_SET_CONCAT flag"). The NFT_SET_EXPR flag needs to be set on when the NFTA_SET_EXPRESSIONS attribute is specified. The NFT_SET_EXPR flag is not set on with NFTA_SET_EXPR to retain backward compatibility in old userspace binaries. Fixes:48b0ae046e
("netfilter: nftables: netlink support for several set element expressions") Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
This commit is contained in:
parent
95cd4bca7b
commit
b4e70d8dd9
@ -293,6 +293,7 @@ enum nft_rule_compat_attributes {
|
||||
* @NFT_SET_EVAL: set can be updated from the evaluation path
|
||||
* @NFT_SET_OBJECT: set contains stateful objects
|
||||
* @NFT_SET_CONCAT: set contains a concatenation
|
||||
* @NFT_SET_EXPR: set contains expressions
|
||||
*/
|
||||
enum nft_set_flags {
|
||||
NFT_SET_ANONYMOUS = 0x1,
|
||||
@ -303,6 +304,7 @@ enum nft_set_flags {
|
||||
NFT_SET_EVAL = 0x20,
|
||||
NFT_SET_OBJECT = 0x40,
|
||||
NFT_SET_CONCAT = 0x80,
|
||||
NFT_SET_EXPR = 0x100,
|
||||
};
|
||||
|
||||
/**
|
||||
@ -706,6 +708,7 @@ enum nft_dynset_ops {
|
||||
|
||||
enum nft_dynset_flags {
|
||||
NFT_DYNSET_F_INV = (1 << 0),
|
||||
NFT_DYNSET_F_EXPR = (1 << 1),
|
||||
};
|
||||
|
||||
/**
|
||||
|
@ -4162,7 +4162,7 @@ static int nf_tables_newset(struct net *net, struct sock *nlsk,
|
||||
if (flags & ~(NFT_SET_ANONYMOUS | NFT_SET_CONSTANT |
|
||||
NFT_SET_INTERVAL | NFT_SET_TIMEOUT |
|
||||
NFT_SET_MAP | NFT_SET_EVAL |
|
||||
NFT_SET_OBJECT | NFT_SET_CONCAT))
|
||||
NFT_SET_OBJECT | NFT_SET_CONCAT | NFT_SET_EXPR))
|
||||
return -EOPNOTSUPP;
|
||||
/* Only one of these operations is supported */
|
||||
if ((flags & (NFT_SET_MAP | NFT_SET_OBJECT)) ==
|
||||
@ -4304,6 +4304,10 @@ static int nf_tables_newset(struct net *net, struct sock *nlsk,
|
||||
struct nlattr *tmp;
|
||||
int left;
|
||||
|
||||
if (!(flags & NFT_SET_EXPR)) {
|
||||
err = -EINVAL;
|
||||
goto err_set_alloc_name;
|
||||
}
|
||||
i = 0;
|
||||
nla_for_each_nested(tmp, nla[NFTA_SET_EXPRESSIONS], left) {
|
||||
if (i == NFT_SET_EXPR_MAX) {
|
||||
|
@ -19,6 +19,7 @@ struct nft_dynset {
|
||||
enum nft_registers sreg_key:8;
|
||||
enum nft_registers sreg_data:8;
|
||||
bool invert;
|
||||
bool expr;
|
||||
u8 num_exprs;
|
||||
u64 timeout;
|
||||
struct nft_expr *expr_array[NFT_SET_EXPR_MAX];
|
||||
@ -175,11 +176,12 @@ static int nft_dynset_init(const struct nft_ctx *ctx,
|
||||
|
||||
if (tb[NFTA_DYNSET_FLAGS]) {
|
||||
u32 flags = ntohl(nla_get_be32(tb[NFTA_DYNSET_FLAGS]));
|
||||
|
||||
if (flags & ~NFT_DYNSET_F_INV)
|
||||
if (flags & ~(NFT_DYNSET_F_INV | NFT_DYNSET_F_EXPR))
|
||||
return -EOPNOTSUPP;
|
||||
if (flags & NFT_DYNSET_F_INV)
|
||||
priv->invert = true;
|
||||
if (flags & NFT_DYNSET_F_EXPR)
|
||||
priv->expr = true;
|
||||
}
|
||||
|
||||
set = nft_set_lookup_global(ctx->net, ctx->table,
|
||||
@ -261,6 +263,9 @@ static int nft_dynset_init(const struct nft_ctx *ctx,
|
||||
struct nlattr *tmp;
|
||||
int left;
|
||||
|
||||
if (!priv->expr)
|
||||
return -EINVAL;
|
||||
|
||||
i = 0;
|
||||
nla_for_each_nested(tmp, tb[NFTA_DYNSET_EXPRESSIONS], left) {
|
||||
if (i == NFT_SET_EXPR_MAX) {
|
||||
|
Loading…
Reference in New Issue
Block a user