aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--include/net/netfilter/nf_tables.h4
-rw-r--r--include/uapi/linux/netfilter/nf_tables.h2
-rw-r--r--net/netfilter/nf_tables_api.c21
3 files changed, 26 insertions, 1 deletions
diff --git a/include/net/netfilter/nf_tables.h b/include/net/netfilter/nf_tables.h
index 0191fbb33a2f..f6b1daf2e698 100644
--- a/include/net/netfilter/nf_tables.h
+++ b/include/net/netfilter/nf_tables.h
@@ -291,6 +291,8 @@ void nft_unregister_set(struct nft_set_ops *ops);
291 * @timeout: default timeout value in msecs 291 * @timeout: default timeout value in msecs
292 * @gc_int: garbage collection interval in msecs 292 * @gc_int: garbage collection interval in msecs
293 * @policy: set parameterization (see enum nft_set_policies) 293 * @policy: set parameterization (see enum nft_set_policies)
294 * @udlen: user data length
295 * @udata: user data
294 * @ops: set ops 296 * @ops: set ops
295 * @pnet: network namespace 297 * @pnet: network namespace
296 * @flags: set flags 298 * @flags: set flags
@@ -310,6 +312,8 @@ struct nft_set {
310 u64 timeout; 312 u64 timeout;
311 u32 gc_int; 313 u32 gc_int;
312 u16 policy; 314 u16 policy;
315 u16 udlen;
316 unsigned char *udata;
313 /* runtime data below here */ 317 /* runtime data below here */
314 const struct nft_set_ops *ops ____cacheline_aligned; 318 const struct nft_set_ops *ops ____cacheline_aligned;
315 possible_net_t pnet; 319 possible_net_t pnet;
diff --git a/include/uapi/linux/netfilter/nf_tables.h b/include/uapi/linux/netfilter/nf_tables.h
index 731288a039f6..03c28a402c63 100644
--- a/include/uapi/linux/netfilter/nf_tables.h
+++ b/include/uapi/linux/netfilter/nf_tables.h
@@ -291,6 +291,7 @@ enum nft_set_desc_attributes {
291 * @NFTA_SET_ID: uniquely identifies a set in a transaction (NLA_U32) 291 * @NFTA_SET_ID: uniquely identifies a set in a transaction (NLA_U32)
292 * @NFTA_SET_TIMEOUT: default timeout value (NLA_U64) 292 * @NFTA_SET_TIMEOUT: default timeout value (NLA_U64)
293 * @NFTA_SET_GC_INTERVAL: garbage collection interval (NLA_U32) 293 * @NFTA_SET_GC_INTERVAL: garbage collection interval (NLA_U32)
294 * @NFTA_SET_USERDATA: user data (NLA_BINARY)
294 */ 295 */
295enum nft_set_attributes { 296enum nft_set_attributes {
296 NFTA_SET_UNSPEC, 297 NFTA_SET_UNSPEC,
@@ -306,6 +307,7 @@ enum nft_set_attributes {
306 NFTA_SET_ID, 307 NFTA_SET_ID,
307 NFTA_SET_TIMEOUT, 308 NFTA_SET_TIMEOUT,
308 NFTA_SET_GC_INTERVAL, 309 NFTA_SET_GC_INTERVAL,
310 NFTA_SET_USERDATA,
309 __NFTA_SET_MAX 311 __NFTA_SET_MAX
310}; 312};
311#define NFTA_SET_MAX (__NFTA_SET_MAX - 1) 313#define NFTA_SET_MAX (__NFTA_SET_MAX - 1)
diff --git a/net/netfilter/nf_tables_api.c b/net/netfilter/nf_tables_api.c
index f5c397158e29..2011977cd79d 100644
--- a/net/netfilter/nf_tables_api.c
+++ b/net/netfilter/nf_tables_api.c
@@ -2323,6 +2323,8 @@ static const struct nla_policy nft_set_policy[NFTA_SET_MAX + 1] = {
2323 [NFTA_SET_ID] = { .type = NLA_U32 }, 2323 [NFTA_SET_ID] = { .type = NLA_U32 },
2324 [NFTA_SET_TIMEOUT] = { .type = NLA_U64 }, 2324 [NFTA_SET_TIMEOUT] = { .type = NLA_U64 },
2325 [NFTA_SET_GC_INTERVAL] = { .type = NLA_U32 }, 2325 [NFTA_SET_GC_INTERVAL] = { .type = NLA_U32 },
2326 [NFTA_SET_USERDATA] = { .type = NLA_BINARY,
2327 .len = NFT_USERDATA_MAXLEN },
2326}; 2328};
2327 2329
2328static const struct nla_policy nft_set_desc_policy[NFTA_SET_DESC_MAX + 1] = { 2330static 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,
2482 goto nla_put_failure; 2484 goto nla_put_failure;
2483 } 2485 }
2484 2486
2487 if (nla_put(skb, NFTA_SET_USERDATA, set->udlen, set->udata))
2488 goto nla_put_failure;
2489
2485 desc = nla_nest_start(skb, NFTA_SET_DESC); 2490 desc = nla_nest_start(skb, NFTA_SET_DESC);
2486 if (desc == NULL) 2491 if (desc == NULL)
2487 goto nla_put_failure; 2492 goto nla_put_failure;
@@ -2691,6 +2696,8 @@ static int nf_tables_newset(struct net *net, struct sock *nlsk,
2691 u64 timeout; 2696 u64 timeout;
2692 u32 ktype, dtype, flags, policy, gc_int; 2697 u32 ktype, dtype, flags, policy, gc_int;
2693 struct nft_set_desc desc; 2698 struct nft_set_desc desc;
2699 unsigned char *udata;
2700 u16 udlen;
2694 int err; 2701 int err;
2695 2702
2696 if (nla[NFTA_SET_TABLE] == NULL || 2703 if (nla[NFTA_SET_TABLE] == NULL ||
@@ -2803,12 +2810,16 @@ static int nf_tables_newset(struct net *net, struct sock *nlsk,
2803 if (IS_ERR(ops)) 2810 if (IS_ERR(ops))
2804 return PTR_ERR(ops); 2811 return PTR_ERR(ops);
2805 2812
2813 udlen = 0;
2814 if (nla[NFTA_SET_USERDATA])
2815 udlen = nla_len(nla[NFTA_SET_USERDATA]);
2816
2806 size = 0; 2817 size = 0;
2807 if (ops->privsize != NULL) 2818 if (ops->privsize != NULL)
2808 size = ops->privsize(nla); 2819 size = ops->privsize(nla);
2809 2820
2810 err = -ENOMEM; 2821 err = -ENOMEM;
2811 set = kzalloc(sizeof(*set) + size, GFP_KERNEL); 2822 set = kzalloc(sizeof(*set) + size + udlen, GFP_KERNEL);
2812 if (set == NULL) 2823 if (set == NULL)
2813 goto err1; 2824 goto err1;
2814 2825
@@ -2817,6 +2828,12 @@ static int nf_tables_newset(struct net *net, struct sock *nlsk,
2817 if (err < 0) 2828 if (err < 0)
2818 goto err2; 2829 goto err2;
2819 2830
2831 udata = NULL;
2832 if (udlen) {
2833 udata = set->data + size;
2834 nla_memcpy(udata, nla[NFTA_SET_USERDATA], udlen);
2835 }
2836
2820 INIT_LIST_HEAD(&set->bindings); 2837 INIT_LIST_HEAD(&set->bindings);
2821 write_pnet(&set->pnet, net); 2838 write_pnet(&set->pnet, net);
2822 set->ops = ops; 2839 set->ops = ops;
@@ -2827,6 +2844,8 @@ static int nf_tables_newset(struct net *net, struct sock *nlsk,
2827 set->flags = flags; 2844 set->flags = flags;
2828 set->size = desc.size; 2845 set->size = desc.size;
2829 set->policy = policy; 2846 set->policy = policy;
2847 set->udlen = udlen;
2848 set->udata = udata;
2830 set->timeout = timeout; 2849 set->timeout = timeout;
2831 set->gc_int = gc_int; 2850 set->gc_int = gc_int;
2832 2851