netfilter: nf_tables: Add new attributes into nft_set to store user data.

User data is stored at after 'nft_set_ops' private data into 'data[]'
flexible array. The field 'udata' points to user data and 'udlen' stores
its length.

Add new flag NFTA_SET_USERDATA.

Signed-off-by: Carlos Falgueras García <carlosfg@riseup.net>
Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
This commit is contained in:
Carlos Falgueras García 2016-01-05 14:03:32 +01:00 committed by Pablo Neira Ayuso
parent eb075954e9
commit e6d8ecac9e
3 changed files with 26 additions and 1 deletions

View File

@ -291,6 +291,8 @@ void nft_unregister_set(struct nft_set_ops *ops);
* @timeout: default timeout value in msecs * @timeout: default timeout value in msecs
* @gc_int: garbage collection interval in msecs * @gc_int: garbage collection interval in msecs
* @policy: set parameterization (see enum nft_set_policies) * @policy: set parameterization (see enum nft_set_policies)
* @udlen: user data length
* @udata: user data
* @ops: set ops * @ops: set ops
* @pnet: network namespace * @pnet: network namespace
* @flags: set flags * @flags: set flags
@ -310,6 +312,8 @@ struct nft_set {
u64 timeout; u64 timeout;
u32 gc_int; u32 gc_int;
u16 policy; u16 policy;
u16 udlen;
unsigned char *udata;
/* runtime data below here */ /* runtime data below here */
const struct nft_set_ops *ops ____cacheline_aligned; const struct nft_set_ops *ops ____cacheline_aligned;
possible_net_t pnet; possible_net_t pnet;

View File

@ -291,6 +291,7 @@ enum nft_set_desc_attributes {
* @NFTA_SET_ID: uniquely identifies a set in a transaction (NLA_U32) * @NFTA_SET_ID: uniquely identifies a set in a transaction (NLA_U32)
* @NFTA_SET_TIMEOUT: default timeout value (NLA_U64) * @NFTA_SET_TIMEOUT: default timeout value (NLA_U64)
* @NFTA_SET_GC_INTERVAL: garbage collection interval (NLA_U32) * @NFTA_SET_GC_INTERVAL: garbage collection interval (NLA_U32)
* @NFTA_SET_USERDATA: user data (NLA_BINARY)
*/ */
enum nft_set_attributes { enum nft_set_attributes {
NFTA_SET_UNSPEC, NFTA_SET_UNSPEC,
@ -306,6 +307,7 @@ enum nft_set_attributes {
NFTA_SET_ID, NFTA_SET_ID,
NFTA_SET_TIMEOUT, NFTA_SET_TIMEOUT,
NFTA_SET_GC_INTERVAL, NFTA_SET_GC_INTERVAL,
NFTA_SET_USERDATA,
__NFTA_SET_MAX __NFTA_SET_MAX
}; };
#define NFTA_SET_MAX (__NFTA_SET_MAX - 1) #define NFTA_SET_MAX (__NFTA_SET_MAX - 1)

View File

@ -2323,6 +2323,8 @@ static const struct nla_policy nft_set_policy[NFTA_SET_MAX + 1] = {
[NFTA_SET_ID] = { .type = NLA_U32 }, [NFTA_SET_ID] = { .type = NLA_U32 },
[NFTA_SET_TIMEOUT] = { .type = NLA_U64 }, [NFTA_SET_TIMEOUT] = { .type = NLA_U64 },
[NFTA_SET_GC_INTERVAL] = { .type = NLA_U32 }, [NFTA_SET_GC_INTERVAL] = { .type = NLA_U32 },
[NFTA_SET_USERDATA] = { .type = NLA_BINARY,
.len = NFT_USERDATA_MAXLEN },
}; };
static const struct nla_policy nft_set_desc_policy[NFTA_SET_DESC_MAX + 1] = { static const struct nla_policy nft_set_desc_policy[NFTA_SET_DESC_MAX + 1] = {
@ -2482,6 +2484,9 @@ static int nf_tables_fill_set(struct sk_buff *skb, const struct nft_ctx *ctx,
goto nla_put_failure; goto nla_put_failure;
} }
if (nla_put(skb, NFTA_SET_USERDATA, set->udlen, set->udata))
goto nla_put_failure;
desc = nla_nest_start(skb, NFTA_SET_DESC); desc = nla_nest_start(skb, NFTA_SET_DESC);
if (desc == NULL) if (desc == NULL)
goto nla_put_failure; goto nla_put_failure;
@ -2691,6 +2696,8 @@ static int nf_tables_newset(struct net *net, struct sock *nlsk,
u64 timeout; u64 timeout;
u32 ktype, dtype, flags, policy, gc_int; u32 ktype, dtype, flags, policy, gc_int;
struct nft_set_desc desc; struct nft_set_desc desc;
unsigned char *udata;
u16 udlen;
int err; int err;
if (nla[NFTA_SET_TABLE] == NULL || if (nla[NFTA_SET_TABLE] == NULL ||
@ -2803,12 +2810,16 @@ static int nf_tables_newset(struct net *net, struct sock *nlsk,
if (IS_ERR(ops)) if (IS_ERR(ops))
return PTR_ERR(ops); return PTR_ERR(ops);
udlen = 0;
if (nla[NFTA_SET_USERDATA])
udlen = nla_len(nla[NFTA_SET_USERDATA]);
size = 0; size = 0;
if (ops->privsize != NULL) if (ops->privsize != NULL)
size = ops->privsize(nla); size = ops->privsize(nla);
err = -ENOMEM; err = -ENOMEM;
set = kzalloc(sizeof(*set) + size, GFP_KERNEL); set = kzalloc(sizeof(*set) + size + udlen, GFP_KERNEL);
if (set == NULL) if (set == NULL)
goto err1; goto err1;
@ -2817,6 +2828,12 @@ static int nf_tables_newset(struct net *net, struct sock *nlsk,
if (err < 0) if (err < 0)
goto err2; goto err2;
udata = NULL;
if (udlen) {
udata = set->data + size;
nla_memcpy(udata, nla[NFTA_SET_USERDATA], udlen);
}
INIT_LIST_HEAD(&set->bindings); INIT_LIST_HEAD(&set->bindings);
write_pnet(&set->pnet, net); write_pnet(&set->pnet, net);
set->ops = ops; set->ops = ops;
@ -2827,6 +2844,8 @@ static int nf_tables_newset(struct net *net, struct sock *nlsk,
set->flags = flags; set->flags = flags;
set->size = desc.size; set->size = desc.size;
set->policy = policy; set->policy = policy;
set->udlen = udlen;
set->udata = udata;
set->timeout = timeout; set->timeout = timeout;
set->gc_int = gc_int; set->gc_int = gc_int;