diff options
-rw-r--r-- | include/net/netfilter/nf_tables.h | 4 | ||||
-rw-r--r-- | include/uapi/linux/netfilter/nf_tables.h | 2 | ||||
-rw-r--r-- | net/netfilter/nf_tables_api.c | 21 |
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 | */ |
295 | enum nft_set_attributes { | 296 | enum 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 | ||
2328 | static const struct nla_policy nft_set_desc_policy[NFTA_SET_DESC_MAX + 1] = { | 2330 | 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, | |||
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 | ||