netfilter: nf_tables: Add new attributes into nft_set to store user data.
authorCarlos Falgueras García <carlosfg@riseup.net>
Tue, 5 Jan 2016 13:03:32 +0000 (14:03 +0100)
committerPablo Neira Ayuso <pablo@netfilter.org>
Fri, 8 Jan 2016 12:25:08 +0000 (13:25 +0100)
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>
include/net/netfilter/nf_tables.h
include/uapi/linux/netfilter/nf_tables.h
net/netfilter/nf_tables_api.c

index 0191fbb..f6b1daf 100644 (file)
@@ -291,6 +291,8 @@ void nft_unregister_set(struct nft_set_ops *ops);
  *     @timeout: default timeout value in msecs
  *     @gc_int: garbage collection interval in msecs
  *     @policy: set parameterization (see enum nft_set_policies)
+ *     @udlen: user data length
+ *     @udata: user data
  *     @ops: set ops
  *     @pnet: network namespace
  *     @flags: set flags
@@ -310,6 +312,8 @@ struct nft_set {
        u64                             timeout;
        u32                             gc_int;
        u16                             policy;
+       u16                             udlen;
+       unsigned char                   *udata;
        /* runtime data below here */
        const struct nft_set_ops        *ops ____cacheline_aligned;
        possible_net_t                  pnet;
index 731288a..03c28a4 100644 (file)
@@ -291,6 +291,7 @@ enum nft_set_desc_attributes {
  * @NFTA_SET_ID: uniquely identifies a set in a transaction (NLA_U32)
  * @NFTA_SET_TIMEOUT: default timeout value (NLA_U64)
  * @NFTA_SET_GC_INTERVAL: garbage collection interval (NLA_U32)
+ * @NFTA_SET_USERDATA: user data (NLA_BINARY)
  */
 enum nft_set_attributes {
        NFTA_SET_UNSPEC,
@@ -306,6 +307,7 @@ enum nft_set_attributes {
        NFTA_SET_ID,
        NFTA_SET_TIMEOUT,
        NFTA_SET_GC_INTERVAL,
+       NFTA_SET_USERDATA,
        __NFTA_SET_MAX
 };
 #define NFTA_SET_MAX           (__NFTA_SET_MAX - 1)
index f5c3971..2011977 100644 (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_TIMEOUT]              = { .type = NLA_U64 },
        [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] = {
@@ -2482,6 +2484,9 @@ static int nf_tables_fill_set(struct sk_buff *skb, const struct nft_ctx *ctx,
                        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);
        if (desc == NULL)
                goto nla_put_failure;
@@ -2691,6 +2696,8 @@ static int nf_tables_newset(struct net *net, struct sock *nlsk,
        u64 timeout;
        u32 ktype, dtype, flags, policy, gc_int;
        struct nft_set_desc desc;
+       unsigned char *udata;
+       u16 udlen;
        int err;
 
        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))
                return PTR_ERR(ops);
 
+       udlen = 0;
+       if (nla[NFTA_SET_USERDATA])
+               udlen = nla_len(nla[NFTA_SET_USERDATA]);
+
        size = 0;
        if (ops->privsize != NULL)
                size = ops->privsize(nla);
 
        err = -ENOMEM;
-       set = kzalloc(sizeof(*set) + size, GFP_KERNEL);
+       set = kzalloc(sizeof(*set) + size + udlen, GFP_KERNEL);
        if (set == NULL)
                goto err1;
 
@@ -2817,6 +2828,12 @@ static int nf_tables_newset(struct net *net, struct sock *nlsk,
        if (err < 0)
                goto err2;
 
+       udata = NULL;
+       if (udlen) {
+               udata = set->data + size;
+               nla_memcpy(udata, nla[NFTA_SET_USERDATA], udlen);
+       }
+
        INIT_LIST_HEAD(&set->bindings);
        write_pnet(&set->pnet, net);
        set->ops   = ops;
@@ -2827,6 +2844,8 @@ static int nf_tables_newset(struct net *net, struct sock *nlsk,
        set->flags = flags;
        set->size  = desc.size;
        set->policy = policy;
+       set->udlen  = udlen;
+       set->udata  = udata;
        set->timeout = timeout;
        set->gc_int = gc_int;