diff options
Diffstat (limited to 'net')
-rw-r--r-- | net/ipv4/netfilter/nf_log_arp.c | 4 | ||||
-rw-r--r-- | net/ipv4/netfilter/nf_log_ipv4.c | 4 | ||||
-rw-r--r-- | net/ipv6/netfilter/ip6_tables.c | 5 | ||||
-rw-r--r-- | net/ipv6/netfilter/nf_log_ipv6.c | 4 | ||||
-rw-r--r-- | net/netfilter/Kconfig | 1 | ||||
-rw-r--r-- | net/netfilter/nf_tables_api.c | 199 | ||||
-rw-r--r-- | net/netfilter/nf_tables_core.c | 18 | ||||
-rw-r--r-- | net/netfilter/nft_hash.c | 183 | ||||
-rw-r--r-- | net/netfilter/nft_log.c | 2 | ||||
-rw-r--r-- | net/netfilter/nft_lookup.c | 6 | ||||
-rw-r--r-- | net/netfilter/nft_meta.c | 2 | ||||
-rw-r--r-- | net/netfilter/nft_rbtree.c | 123 | ||||
-rw-r--r-- | net/netlink/af_netlink.c | 2 |
13 files changed, 332 insertions, 221 deletions
diff --git a/net/ipv4/netfilter/nf_log_arp.c b/net/ipv4/netfilter/nf_log_arp.c index d059182c1466..e7ad950cf9ef 100644 --- a/net/ipv4/netfilter/nf_log_arp.c +++ b/net/ipv4/netfilter/nf_log_arp.c | |||
@@ -10,8 +10,10 @@ | |||
10 | * it under the terms of the GNU General Public License version 2 as | 10 | * it under the terms of the GNU General Public License version 2 as |
11 | * published by the Free Software Foundation. | 11 | * published by the Free Software Foundation. |
12 | */ | 12 | */ |
13 | |||
13 | #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt | 14 | #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt |
14 | 15 | ||
16 | #include <linux/kernel.h> | ||
15 | #include <linux/module.h> | 17 | #include <linux/module.h> |
16 | #include <linux/spinlock.h> | 18 | #include <linux/spinlock.h> |
17 | #include <linux/skbuff.h> | 19 | #include <linux/skbuff.h> |
@@ -27,7 +29,7 @@ static struct nf_loginfo default_loginfo = { | |||
27 | .type = NF_LOG_TYPE_LOG, | 29 | .type = NF_LOG_TYPE_LOG, |
28 | .u = { | 30 | .u = { |
29 | .log = { | 31 | .log = { |
30 | .level = 5, | 32 | .level = LOGLEVEL_NOTICE, |
31 | .logflags = NF_LOG_MASK, | 33 | .logflags = NF_LOG_MASK, |
32 | }, | 34 | }, |
33 | }, | 35 | }, |
diff --git a/net/ipv4/netfilter/nf_log_ipv4.c b/net/ipv4/netfilter/nf_log_ipv4.c index 75101980eeee..076aadda0473 100644 --- a/net/ipv4/netfilter/nf_log_ipv4.c +++ b/net/ipv4/netfilter/nf_log_ipv4.c | |||
@@ -5,8 +5,10 @@ | |||
5 | * it under the terms of the GNU General Public License version 2 as | 5 | * it under the terms of the GNU General Public License version 2 as |
6 | * published by the Free Software Foundation. | 6 | * published by the Free Software Foundation. |
7 | */ | 7 | */ |
8 | |||
8 | #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt | 9 | #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt |
9 | 10 | ||
11 | #include <linux/kernel.h> | ||
10 | #include <linux/module.h> | 12 | #include <linux/module.h> |
11 | #include <linux/spinlock.h> | 13 | #include <linux/spinlock.h> |
12 | #include <linux/skbuff.h> | 14 | #include <linux/skbuff.h> |
@@ -26,7 +28,7 @@ static struct nf_loginfo default_loginfo = { | |||
26 | .type = NF_LOG_TYPE_LOG, | 28 | .type = NF_LOG_TYPE_LOG, |
27 | .u = { | 29 | .u = { |
28 | .log = { | 30 | .log = { |
29 | .level = 5, | 31 | .level = LOGLEVEL_NOTICE, |
30 | .logflags = NF_LOG_MASK, | 32 | .logflags = NF_LOG_MASK, |
31 | }, | 33 | }, |
32 | }, | 34 | }, |
diff --git a/net/ipv6/netfilter/ip6_tables.c b/net/ipv6/netfilter/ip6_tables.c index bb00c6f2a885..83f59dc3cccc 100644 --- a/net/ipv6/netfilter/ip6_tables.c +++ b/net/ipv6/netfilter/ip6_tables.c | |||
@@ -9,7 +9,10 @@ | |||
9 | * it under the terms of the GNU General Public License version 2 as | 9 | * it under the terms of the GNU General Public License version 2 as |
10 | * published by the Free Software Foundation. | 10 | * published by the Free Software Foundation. |
11 | */ | 11 | */ |
12 | |||
12 | #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt | 13 | #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt |
14 | |||
15 | #include <linux/kernel.h> | ||
13 | #include <linux/capability.h> | 16 | #include <linux/capability.h> |
14 | #include <linux/in.h> | 17 | #include <linux/in.h> |
15 | #include <linux/skbuff.h> | 18 | #include <linux/skbuff.h> |
@@ -234,7 +237,7 @@ static struct nf_loginfo trace_loginfo = { | |||
234 | .type = NF_LOG_TYPE_LOG, | 237 | .type = NF_LOG_TYPE_LOG, |
235 | .u = { | 238 | .u = { |
236 | .log = { | 239 | .log = { |
237 | .level = 4, | 240 | .level = LOGLEVEL_WARNING, |
238 | .logflags = NF_LOG_MASK, | 241 | .logflags = NF_LOG_MASK, |
239 | }, | 242 | }, |
240 | }, | 243 | }, |
diff --git a/net/ipv6/netfilter/nf_log_ipv6.c b/net/ipv6/netfilter/nf_log_ipv6.c index ddf07e6f59d7..8dd869642f45 100644 --- a/net/ipv6/netfilter/nf_log_ipv6.c +++ b/net/ipv6/netfilter/nf_log_ipv6.c | |||
@@ -5,8 +5,10 @@ | |||
5 | * it under the terms of the GNU General Public License version 2 as | 5 | * it under the terms of the GNU General Public License version 2 as |
6 | * published by the Free Software Foundation. | 6 | * published by the Free Software Foundation. |
7 | */ | 7 | */ |
8 | |||
8 | #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt | 9 | #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt |
9 | 10 | ||
11 | #include <linux/kernel.h> | ||
10 | #include <linux/module.h> | 12 | #include <linux/module.h> |
11 | #include <linux/spinlock.h> | 13 | #include <linux/spinlock.h> |
12 | #include <linux/skbuff.h> | 14 | #include <linux/skbuff.h> |
@@ -27,7 +29,7 @@ static struct nf_loginfo default_loginfo = { | |||
27 | .type = NF_LOG_TYPE_LOG, | 29 | .type = NF_LOG_TYPE_LOG, |
28 | .u = { | 30 | .u = { |
29 | .log = { | 31 | .log = { |
30 | .level = 5, | 32 | .level = LOGLEVEL_NOTICE, |
31 | .logflags = NF_LOG_MASK, | 33 | .logflags = NF_LOG_MASK, |
32 | }, | 34 | }, |
33 | }, | 35 | }, |
diff --git a/net/netfilter/Kconfig b/net/netfilter/Kconfig index 971cd7526f4b..f70e34a68f70 100644 --- a/net/netfilter/Kconfig +++ b/net/netfilter/Kconfig | |||
@@ -522,7 +522,6 @@ config NFT_NAT | |||
522 | typical Network Address Translation (NAT) packet transformations. | 522 | typical Network Address Translation (NAT) packet transformations. |
523 | 523 | ||
524 | config NFT_QUEUE | 524 | config NFT_QUEUE |
525 | depends on NETFILTER_XTABLES | ||
526 | depends on NETFILTER_NETLINK_QUEUE | 525 | depends on NETFILTER_NETLINK_QUEUE |
527 | tristate "Netfilter nf_tables queue module" | 526 | tristate "Netfilter nf_tables queue module" |
528 | help | 527 | help |
diff --git a/net/netfilter/nf_tables_api.c b/net/netfilter/nf_tables_api.c index 363a39a6c286..5604c2df05d1 100644 --- a/net/netfilter/nf_tables_api.c +++ b/net/netfilter/nf_tables_api.c | |||
@@ -198,36 +198,31 @@ static int nft_delchain(struct nft_ctx *ctx) | |||
198 | static inline bool | 198 | static inline bool |
199 | nft_rule_is_active(struct net *net, const struct nft_rule *rule) | 199 | nft_rule_is_active(struct net *net, const struct nft_rule *rule) |
200 | { | 200 | { |
201 | return (rule->genmask & (1 << net->nft.gencursor)) == 0; | 201 | return (rule->genmask & nft_genmask_cur(net)) == 0; |
202 | } | ||
203 | |||
204 | static inline int gencursor_next(struct net *net) | ||
205 | { | ||
206 | return net->nft.gencursor+1 == 1 ? 1 : 0; | ||
207 | } | 202 | } |
208 | 203 | ||
209 | static inline int | 204 | static inline int |
210 | nft_rule_is_active_next(struct net *net, const struct nft_rule *rule) | 205 | nft_rule_is_active_next(struct net *net, const struct nft_rule *rule) |
211 | { | 206 | { |
212 | return (rule->genmask & (1 << gencursor_next(net))) == 0; | 207 | return (rule->genmask & nft_genmask_next(net)) == 0; |
213 | } | 208 | } |
214 | 209 | ||
215 | static inline void | 210 | static inline void |
216 | nft_rule_activate_next(struct net *net, struct nft_rule *rule) | 211 | nft_rule_activate_next(struct net *net, struct nft_rule *rule) |
217 | { | 212 | { |
218 | /* Now inactive, will be active in the future */ | 213 | /* Now inactive, will be active in the future */ |
219 | rule->genmask = (1 << net->nft.gencursor); | 214 | rule->genmask = nft_genmask_cur(net); |
220 | } | 215 | } |
221 | 216 | ||
222 | static inline void | 217 | static inline void |
223 | nft_rule_deactivate_next(struct net *net, struct nft_rule *rule) | 218 | nft_rule_deactivate_next(struct net *net, struct nft_rule *rule) |
224 | { | 219 | { |
225 | rule->genmask = (1 << gencursor_next(net)); | 220 | rule->genmask = nft_genmask_next(net); |
226 | } | 221 | } |
227 | 222 | ||
228 | static inline void nft_rule_clear(struct net *net, struct nft_rule *rule) | 223 | static inline void nft_rule_clear(struct net *net, struct nft_rule *rule) |
229 | { | 224 | { |
230 | rule->genmask &= ~(1 << gencursor_next(net)); | 225 | rule->genmask &= ~nft_genmask_next(net); |
231 | } | 226 | } |
232 | 227 | ||
233 | static int | 228 | static int |
@@ -1354,6 +1349,7 @@ static int nf_tables_newchain(struct sock *nlsk, struct sk_buff *skb, | |||
1354 | rcu_assign_pointer(basechain->stats, stats); | 1349 | rcu_assign_pointer(basechain->stats, stats); |
1355 | } | 1350 | } |
1356 | 1351 | ||
1352 | write_pnet(&basechain->pnet, net); | ||
1357 | basechain->type = type; | 1353 | basechain->type = type; |
1358 | chain = &basechain->chain; | 1354 | chain = &basechain->chain; |
1359 | 1355 | ||
@@ -1381,7 +1377,6 @@ static int nf_tables_newchain(struct sock *nlsk, struct sk_buff *skb, | |||
1381 | 1377 | ||
1382 | INIT_LIST_HEAD(&chain->rules); | 1378 | INIT_LIST_HEAD(&chain->rules); |
1383 | chain->handle = nf_tables_alloc_handle(table); | 1379 | chain->handle = nf_tables_alloc_handle(table); |
1384 | chain->net = net; | ||
1385 | chain->table = table; | 1380 | chain->table = table; |
1386 | nla_strlcpy(chain->name, name, NFT_CHAIN_MAXNAMELEN); | 1381 | nla_strlcpy(chain->name, name, NFT_CHAIN_MAXNAMELEN); |
1387 | 1382 | ||
@@ -2695,6 +2690,7 @@ static int nf_tables_newset(struct sock *nlsk, struct sk_buff *skb, | |||
2695 | goto err2; | 2690 | goto err2; |
2696 | 2691 | ||
2697 | INIT_LIST_HEAD(&set->bindings); | 2692 | INIT_LIST_HEAD(&set->bindings); |
2693 | write_pnet(&set->pnet, net); | ||
2698 | set->ops = ops; | 2694 | set->ops = ops; |
2699 | set->ktype = ktype; | 2695 | set->ktype = ktype; |
2700 | set->klen = desc.klen; | 2696 | set->klen = desc.klen; |
@@ -2771,10 +2767,11 @@ static int nf_tables_bind_check_setelem(const struct nft_ctx *ctx, | |||
2771 | const struct nft_set_iter *iter, | 2767 | const struct nft_set_iter *iter, |
2772 | const struct nft_set_elem *elem) | 2768 | const struct nft_set_elem *elem) |
2773 | { | 2769 | { |
2770 | const struct nft_set_ext *ext = nft_set_elem_ext(set, elem->priv); | ||
2774 | enum nft_registers dreg; | 2771 | enum nft_registers dreg; |
2775 | 2772 | ||
2776 | dreg = nft_type_to_reg(set->dtype); | 2773 | dreg = nft_type_to_reg(set->dtype); |
2777 | return nft_validate_data_load(ctx, dreg, &elem->data, | 2774 | return nft_validate_data_load(ctx, dreg, nft_set_ext_data(ext), |
2778 | set->dtype == NFT_DATA_VERDICT ? | 2775 | set->dtype == NFT_DATA_VERDICT ? |
2779 | NFT_DATA_VERDICT : NFT_DATA_VALUE); | 2776 | NFT_DATA_VERDICT : NFT_DATA_VALUE); |
2780 | } | 2777 | } |
@@ -2827,6 +2824,22 @@ void nf_tables_unbind_set(const struct nft_ctx *ctx, struct nft_set *set, | |||
2827 | nf_tables_set_destroy(ctx, set); | 2824 | nf_tables_set_destroy(ctx, set); |
2828 | } | 2825 | } |
2829 | 2826 | ||
2827 | const struct nft_set_ext_type nft_set_ext_types[] = { | ||
2828 | [NFT_SET_EXT_KEY] = { | ||
2829 | .len = sizeof(struct nft_data), | ||
2830 | .align = __alignof__(struct nft_data), | ||
2831 | }, | ||
2832 | [NFT_SET_EXT_DATA] = { | ||
2833 | .len = sizeof(struct nft_data), | ||
2834 | .align = __alignof__(struct nft_data), | ||
2835 | }, | ||
2836 | [NFT_SET_EXT_FLAGS] = { | ||
2837 | .len = sizeof(u8), | ||
2838 | .align = __alignof__(u8), | ||
2839 | }, | ||
2840 | }; | ||
2841 | EXPORT_SYMBOL_GPL(nft_set_ext_types); | ||
2842 | |||
2830 | /* | 2843 | /* |
2831 | * Set elements | 2844 | * Set elements |
2832 | */ | 2845 | */ |
@@ -2873,6 +2886,7 @@ static int nf_tables_fill_setelem(struct sk_buff *skb, | |||
2873 | const struct nft_set *set, | 2886 | const struct nft_set *set, |
2874 | const struct nft_set_elem *elem) | 2887 | const struct nft_set_elem *elem) |
2875 | { | 2888 | { |
2889 | const struct nft_set_ext *ext = nft_set_elem_ext(set, elem->priv); | ||
2876 | unsigned char *b = skb_tail_pointer(skb); | 2890 | unsigned char *b = skb_tail_pointer(skb); |
2877 | struct nlattr *nest; | 2891 | struct nlattr *nest; |
2878 | 2892 | ||
@@ -2880,20 +2894,20 @@ static int nf_tables_fill_setelem(struct sk_buff *skb, | |||
2880 | if (nest == NULL) | 2894 | if (nest == NULL) |
2881 | goto nla_put_failure; | 2895 | goto nla_put_failure; |
2882 | 2896 | ||
2883 | if (nft_data_dump(skb, NFTA_SET_ELEM_KEY, &elem->key, NFT_DATA_VALUE, | 2897 | if (nft_data_dump(skb, NFTA_SET_ELEM_KEY, nft_set_ext_key(ext), |
2884 | set->klen) < 0) | 2898 | NFT_DATA_VALUE, set->klen) < 0) |
2885 | goto nla_put_failure; | 2899 | goto nla_put_failure; |
2886 | 2900 | ||
2887 | if (set->flags & NFT_SET_MAP && | 2901 | if (nft_set_ext_exists(ext, NFT_SET_EXT_DATA) && |
2888 | !(elem->flags & NFT_SET_ELEM_INTERVAL_END) && | 2902 | nft_data_dump(skb, NFTA_SET_ELEM_DATA, nft_set_ext_data(ext), |
2889 | nft_data_dump(skb, NFTA_SET_ELEM_DATA, &elem->data, | ||
2890 | set->dtype == NFT_DATA_VERDICT ? NFT_DATA_VERDICT : NFT_DATA_VALUE, | 2903 | set->dtype == NFT_DATA_VERDICT ? NFT_DATA_VERDICT : NFT_DATA_VALUE, |
2891 | set->dlen) < 0) | 2904 | set->dlen) < 0) |
2892 | goto nla_put_failure; | 2905 | goto nla_put_failure; |
2893 | 2906 | ||
2894 | if (elem->flags != 0) | 2907 | if (nft_set_ext_exists(ext, NFT_SET_EXT_FLAGS) && |
2895 | if (nla_put_be32(skb, NFTA_SET_ELEM_FLAGS, htonl(elem->flags))) | 2908 | nla_put_be32(skb, NFTA_SET_ELEM_FLAGS, |
2896 | goto nla_put_failure; | 2909 | htonl(*nft_set_ext_flags(ext)))) |
2910 | goto nla_put_failure; | ||
2897 | 2911 | ||
2898 | nla_nest_end(skb, nest); | 2912 | nla_nest_end(skb, nest); |
2899 | return 0; | 2913 | return 0; |
@@ -3114,15 +3128,54 @@ static struct nft_trans *nft_trans_elem_alloc(struct nft_ctx *ctx, | |||
3114 | return trans; | 3128 | return trans; |
3115 | } | 3129 | } |
3116 | 3130 | ||
3131 | static void *nft_set_elem_init(const struct nft_set *set, | ||
3132 | const struct nft_set_ext_tmpl *tmpl, | ||
3133 | const struct nft_data *key, | ||
3134 | const struct nft_data *data, | ||
3135 | gfp_t gfp) | ||
3136 | { | ||
3137 | struct nft_set_ext *ext; | ||
3138 | void *elem; | ||
3139 | |||
3140 | elem = kzalloc(set->ops->elemsize + tmpl->len, gfp); | ||
3141 | if (elem == NULL) | ||
3142 | return NULL; | ||
3143 | |||
3144 | ext = nft_set_elem_ext(set, elem); | ||
3145 | nft_set_ext_init(ext, tmpl); | ||
3146 | |||
3147 | memcpy(nft_set_ext_key(ext), key, set->klen); | ||
3148 | if (nft_set_ext_exists(ext, NFT_SET_EXT_DATA)) | ||
3149 | memcpy(nft_set_ext_data(ext), data, set->dlen); | ||
3150 | |||
3151 | return elem; | ||
3152 | } | ||
3153 | |||
3154 | void nft_set_elem_destroy(const struct nft_set *set, void *elem) | ||
3155 | { | ||
3156 | struct nft_set_ext *ext = nft_set_elem_ext(set, elem); | ||
3157 | |||
3158 | nft_data_uninit(nft_set_ext_key(ext), NFT_DATA_VALUE); | ||
3159 | if (nft_set_ext_exists(ext, NFT_SET_EXT_DATA)) | ||
3160 | nft_data_uninit(nft_set_ext_data(ext), set->dtype); | ||
3161 | |||
3162 | kfree(elem); | ||
3163 | } | ||
3164 | EXPORT_SYMBOL_GPL(nft_set_elem_destroy); | ||
3165 | |||
3117 | static int nft_add_set_elem(struct nft_ctx *ctx, struct nft_set *set, | 3166 | static int nft_add_set_elem(struct nft_ctx *ctx, struct nft_set *set, |
3118 | const struct nlattr *attr) | 3167 | const struct nlattr *attr) |
3119 | { | 3168 | { |
3120 | struct nlattr *nla[NFTA_SET_ELEM_MAX + 1]; | 3169 | struct nlattr *nla[NFTA_SET_ELEM_MAX + 1]; |
3121 | struct nft_data_desc d1, d2; | 3170 | struct nft_data_desc d1, d2; |
3171 | struct nft_set_ext_tmpl tmpl; | ||
3172 | struct nft_set_ext *ext; | ||
3122 | struct nft_set_elem elem; | 3173 | struct nft_set_elem elem; |
3123 | struct nft_set_binding *binding; | 3174 | struct nft_set_binding *binding; |
3175 | struct nft_data data; | ||
3124 | enum nft_registers dreg; | 3176 | enum nft_registers dreg; |
3125 | struct nft_trans *trans; | 3177 | struct nft_trans *trans; |
3178 | u32 flags; | ||
3126 | int err; | 3179 | int err; |
3127 | 3180 | ||
3128 | if (set->size && set->nelems == set->size) | 3181 | if (set->size && set->nelems == set->size) |
@@ -3136,22 +3189,26 @@ static int nft_add_set_elem(struct nft_ctx *ctx, struct nft_set *set, | |||
3136 | if (nla[NFTA_SET_ELEM_KEY] == NULL) | 3189 | if (nla[NFTA_SET_ELEM_KEY] == NULL) |
3137 | return -EINVAL; | 3190 | return -EINVAL; |
3138 | 3191 | ||
3139 | elem.flags = 0; | 3192 | nft_set_ext_prepare(&tmpl); |
3193 | |||
3194 | flags = 0; | ||
3140 | if (nla[NFTA_SET_ELEM_FLAGS] != NULL) { | 3195 | if (nla[NFTA_SET_ELEM_FLAGS] != NULL) { |
3141 | elem.flags = ntohl(nla_get_be32(nla[NFTA_SET_ELEM_FLAGS])); | 3196 | flags = ntohl(nla_get_be32(nla[NFTA_SET_ELEM_FLAGS])); |
3142 | if (elem.flags & ~NFT_SET_ELEM_INTERVAL_END) | 3197 | if (flags & ~NFT_SET_ELEM_INTERVAL_END) |
3143 | return -EINVAL; | 3198 | return -EINVAL; |
3144 | if (!(set->flags & NFT_SET_INTERVAL) && | 3199 | if (!(set->flags & NFT_SET_INTERVAL) && |
3145 | elem.flags & NFT_SET_ELEM_INTERVAL_END) | 3200 | flags & NFT_SET_ELEM_INTERVAL_END) |
3146 | return -EINVAL; | 3201 | return -EINVAL; |
3202 | if (flags != 0) | ||
3203 | nft_set_ext_add(&tmpl, NFT_SET_EXT_FLAGS); | ||
3147 | } | 3204 | } |
3148 | 3205 | ||
3149 | if (set->flags & NFT_SET_MAP) { | 3206 | if (set->flags & NFT_SET_MAP) { |
3150 | if (nla[NFTA_SET_ELEM_DATA] == NULL && | 3207 | if (nla[NFTA_SET_ELEM_DATA] == NULL && |
3151 | !(elem.flags & NFT_SET_ELEM_INTERVAL_END)) | 3208 | !(flags & NFT_SET_ELEM_INTERVAL_END)) |
3152 | return -EINVAL; | 3209 | return -EINVAL; |
3153 | if (nla[NFTA_SET_ELEM_DATA] != NULL && | 3210 | if (nla[NFTA_SET_ELEM_DATA] != NULL && |
3154 | elem.flags & NFT_SET_ELEM_INTERVAL_END) | 3211 | flags & NFT_SET_ELEM_INTERVAL_END) |
3155 | return -EINVAL; | 3212 | return -EINVAL; |
3156 | } else { | 3213 | } else { |
3157 | if (nla[NFTA_SET_ELEM_DATA] != NULL) | 3214 | if (nla[NFTA_SET_ELEM_DATA] != NULL) |
@@ -3165,12 +3222,10 @@ static int nft_add_set_elem(struct nft_ctx *ctx, struct nft_set *set, | |||
3165 | if (d1.type != NFT_DATA_VALUE || d1.len != set->klen) | 3222 | if (d1.type != NFT_DATA_VALUE || d1.len != set->klen) |
3166 | goto err2; | 3223 | goto err2; |
3167 | 3224 | ||
3168 | err = -EEXIST; | 3225 | nft_set_ext_add(&tmpl, NFT_SET_EXT_KEY); |
3169 | if (set->ops->get(set, &elem) == 0) | ||
3170 | goto err2; | ||
3171 | 3226 | ||
3172 | if (nla[NFTA_SET_ELEM_DATA] != NULL) { | 3227 | if (nla[NFTA_SET_ELEM_DATA] != NULL) { |
3173 | err = nft_data_init(ctx, &elem.data, &d2, nla[NFTA_SET_ELEM_DATA]); | 3228 | err = nft_data_init(ctx, &data, &d2, nla[NFTA_SET_ELEM_DATA]); |
3174 | if (err < 0) | 3229 | if (err < 0) |
3175 | goto err2; | 3230 | goto err2; |
3176 | 3231 | ||
@@ -3187,29 +3242,43 @@ static int nft_add_set_elem(struct nft_ctx *ctx, struct nft_set *set, | |||
3187 | }; | 3242 | }; |
3188 | 3243 | ||
3189 | err = nft_validate_data_load(&bind_ctx, dreg, | 3244 | err = nft_validate_data_load(&bind_ctx, dreg, |
3190 | &elem.data, d2.type); | 3245 | &data, d2.type); |
3191 | if (err < 0) | 3246 | if (err < 0) |
3192 | goto err3; | 3247 | goto err3; |
3193 | } | 3248 | } |
3249 | |||
3250 | nft_set_ext_add(&tmpl, NFT_SET_EXT_DATA); | ||
3194 | } | 3251 | } |
3195 | 3252 | ||
3253 | err = -ENOMEM; | ||
3254 | elem.priv = nft_set_elem_init(set, &tmpl, &elem.key, &data, GFP_KERNEL); | ||
3255 | if (elem.priv == NULL) | ||
3256 | goto err3; | ||
3257 | |||
3258 | ext = nft_set_elem_ext(set, elem.priv); | ||
3259 | if (flags) | ||
3260 | *nft_set_ext_flags(ext) = flags; | ||
3261 | |||
3196 | trans = nft_trans_elem_alloc(ctx, NFT_MSG_NEWSETELEM, set); | 3262 | trans = nft_trans_elem_alloc(ctx, NFT_MSG_NEWSETELEM, set); |
3197 | if (trans == NULL) | 3263 | if (trans == NULL) |
3198 | goto err3; | 3264 | goto err4; |
3199 | 3265 | ||
3266 | ext->genmask = nft_genmask_cur(ctx->net); | ||
3200 | err = set->ops->insert(set, &elem); | 3267 | err = set->ops->insert(set, &elem); |
3201 | if (err < 0) | 3268 | if (err < 0) |
3202 | goto err4; | 3269 | goto err5; |
3203 | 3270 | ||
3204 | nft_trans_elem(trans) = elem; | 3271 | nft_trans_elem(trans) = elem; |
3205 | list_add_tail(&trans->list, &ctx->net->nft.commit_list); | 3272 | list_add_tail(&trans->list, &ctx->net->nft.commit_list); |
3206 | return 0; | 3273 | return 0; |
3207 | 3274 | ||
3208 | err4: | 3275 | err5: |
3209 | kfree(trans); | 3276 | kfree(trans); |
3277 | err4: | ||
3278 | kfree(elem.priv); | ||
3210 | err3: | 3279 | err3: |
3211 | if (nla[NFTA_SET_ELEM_DATA] != NULL) | 3280 | if (nla[NFTA_SET_ELEM_DATA] != NULL) |
3212 | nft_data_uninit(&elem.data, d2.type); | 3281 | nft_data_uninit(&data, d2.type); |
3213 | err2: | 3282 | err2: |
3214 | nft_data_uninit(&elem.key, d1.type); | 3283 | nft_data_uninit(&elem.key, d1.type); |
3215 | err1: | 3284 | err1: |
@@ -3282,19 +3351,24 @@ static int nft_del_setelem(struct nft_ctx *ctx, struct nft_set *set, | |||
3282 | if (desc.type != NFT_DATA_VALUE || desc.len != set->klen) | 3351 | if (desc.type != NFT_DATA_VALUE || desc.len != set->klen) |
3283 | goto err2; | 3352 | goto err2; |
3284 | 3353 | ||
3285 | err = set->ops->get(set, &elem); | ||
3286 | if (err < 0) | ||
3287 | goto err2; | ||
3288 | |||
3289 | trans = nft_trans_elem_alloc(ctx, NFT_MSG_DELSETELEM, set); | 3354 | trans = nft_trans_elem_alloc(ctx, NFT_MSG_DELSETELEM, set); |
3290 | if (trans == NULL) { | 3355 | if (trans == NULL) { |
3291 | err = -ENOMEM; | 3356 | err = -ENOMEM; |
3292 | goto err2; | 3357 | goto err2; |
3293 | } | 3358 | } |
3294 | 3359 | ||
3360 | elem.priv = set->ops->deactivate(set, &elem); | ||
3361 | if (elem.priv == NULL) { | ||
3362 | err = -ENOENT; | ||
3363 | goto err3; | ||
3364 | } | ||
3365 | |||
3295 | nft_trans_elem(trans) = elem; | 3366 | nft_trans_elem(trans) = elem; |
3296 | list_add_tail(&trans->list, &ctx->net->nft.commit_list); | 3367 | list_add_tail(&trans->list, &ctx->net->nft.commit_list); |
3297 | return 0; | 3368 | return 0; |
3369 | |||
3370 | err3: | ||
3371 | kfree(trans); | ||
3298 | err2: | 3372 | err2: |
3299 | nft_data_uninit(&elem.key, desc.type); | 3373 | nft_data_uninit(&elem.key, desc.type); |
3300 | err1: | 3374 | err1: |
@@ -3532,6 +3606,10 @@ static void nf_tables_commit_release(struct nft_trans *trans) | |||
3532 | case NFT_MSG_DELSET: | 3606 | case NFT_MSG_DELSET: |
3533 | nft_set_destroy(nft_trans_set(trans)); | 3607 | nft_set_destroy(nft_trans_set(trans)); |
3534 | break; | 3608 | break; |
3609 | case NFT_MSG_DELSETELEM: | ||
3610 | nft_set_elem_destroy(nft_trans_elem_set(trans), | ||
3611 | nft_trans_elem(trans).priv); | ||
3612 | break; | ||
3535 | } | 3613 | } |
3536 | kfree(trans); | 3614 | kfree(trans); |
3537 | } | 3615 | } |
@@ -3546,7 +3624,7 @@ static int nf_tables_commit(struct sk_buff *skb) | |||
3546 | while (++net->nft.base_seq == 0); | 3624 | while (++net->nft.base_seq == 0); |
3547 | 3625 | ||
3548 | /* A new generation has just started */ | 3626 | /* A new generation has just started */ |
3549 | net->nft.gencursor = gencursor_next(net); | 3627 | net->nft.gencursor = nft_gencursor_next(net); |
3550 | 3628 | ||
3551 | /* Make sure all packets have left the previous generation before | 3629 | /* Make sure all packets have left the previous generation before |
3552 | * purging old rules. | 3630 | * purging old rules. |
@@ -3617,24 +3695,21 @@ static int nf_tables_commit(struct sk_buff *skb) | |||
3617 | NFT_MSG_DELSET, GFP_KERNEL); | 3695 | NFT_MSG_DELSET, GFP_KERNEL); |
3618 | break; | 3696 | break; |
3619 | case NFT_MSG_NEWSETELEM: | 3697 | case NFT_MSG_NEWSETELEM: |
3620 | nf_tables_setelem_notify(&trans->ctx, | 3698 | te = (struct nft_trans_elem *)trans->data; |
3621 | nft_trans_elem_set(trans), | 3699 | |
3622 | &nft_trans_elem(trans), | 3700 | te->set->ops->activate(te->set, &te->elem); |
3701 | nf_tables_setelem_notify(&trans->ctx, te->set, | ||
3702 | &te->elem, | ||
3623 | NFT_MSG_NEWSETELEM, 0); | 3703 | NFT_MSG_NEWSETELEM, 0); |
3624 | nft_trans_destroy(trans); | 3704 | nft_trans_destroy(trans); |
3625 | break; | 3705 | break; |
3626 | case NFT_MSG_DELSETELEM: | 3706 | case NFT_MSG_DELSETELEM: |
3627 | te = (struct nft_trans_elem *)trans->data; | 3707 | te = (struct nft_trans_elem *)trans->data; |
3708 | |||
3628 | nf_tables_setelem_notify(&trans->ctx, te->set, | 3709 | nf_tables_setelem_notify(&trans->ctx, te->set, |
3629 | &te->elem, | 3710 | &te->elem, |
3630 | NFT_MSG_DELSETELEM, 0); | 3711 | NFT_MSG_DELSETELEM, 0); |
3631 | te->set->ops->get(te->set, &te->elem); | ||
3632 | nft_data_uninit(&te->elem.key, NFT_DATA_VALUE); | ||
3633 | if (te->set->flags & NFT_SET_MAP && | ||
3634 | !(te->elem.flags & NFT_SET_ELEM_INTERVAL_END)) | ||
3635 | nft_data_uninit(&te->elem.data, te->set->dtype); | ||
3636 | te->set->ops->remove(te->set, &te->elem); | 3712 | te->set->ops->remove(te->set, &te->elem); |
3637 | nft_trans_destroy(trans); | ||
3638 | break; | 3713 | break; |
3639 | } | 3714 | } |
3640 | } | 3715 | } |
@@ -3666,6 +3741,10 @@ static void nf_tables_abort_release(struct nft_trans *trans) | |||
3666 | case NFT_MSG_NEWSET: | 3741 | case NFT_MSG_NEWSET: |
3667 | nft_set_destroy(nft_trans_set(trans)); | 3742 | nft_set_destroy(nft_trans_set(trans)); |
3668 | break; | 3743 | break; |
3744 | case NFT_MSG_NEWSETELEM: | ||
3745 | nft_set_elem_destroy(nft_trans_elem_set(trans), | ||
3746 | nft_trans_elem(trans).priv); | ||
3747 | break; | ||
3669 | } | 3748 | } |
3670 | kfree(trans); | 3749 | kfree(trans); |
3671 | } | 3750 | } |
@@ -3736,16 +3815,15 @@ static int nf_tables_abort(struct sk_buff *skb) | |||
3736 | case NFT_MSG_NEWSETELEM: | 3815 | case NFT_MSG_NEWSETELEM: |
3737 | nft_trans_elem_set(trans)->nelems--; | 3816 | nft_trans_elem_set(trans)->nelems--; |
3738 | te = (struct nft_trans_elem *)trans->data; | 3817 | te = (struct nft_trans_elem *)trans->data; |
3739 | te->set->ops->get(te->set, &te->elem); | 3818 | |
3740 | nft_data_uninit(&te->elem.key, NFT_DATA_VALUE); | ||
3741 | if (te->set->flags & NFT_SET_MAP && | ||
3742 | !(te->elem.flags & NFT_SET_ELEM_INTERVAL_END)) | ||
3743 | nft_data_uninit(&te->elem.data, te->set->dtype); | ||
3744 | te->set->ops->remove(te->set, &te->elem); | 3819 | te->set->ops->remove(te->set, &te->elem); |
3745 | nft_trans_destroy(trans); | ||
3746 | break; | 3820 | break; |
3747 | case NFT_MSG_DELSETELEM: | 3821 | case NFT_MSG_DELSETELEM: |
3822 | te = (struct nft_trans_elem *)trans->data; | ||
3823 | |||
3748 | nft_trans_elem_set(trans)->nelems++; | 3824 | nft_trans_elem_set(trans)->nelems++; |
3825 | te->set->ops->activate(te->set, &te->elem); | ||
3826 | |||
3749 | nft_trans_destroy(trans); | 3827 | nft_trans_destroy(trans); |
3750 | break; | 3828 | break; |
3751 | } | 3829 | } |
@@ -3820,13 +3898,18 @@ static int nf_tables_loop_check_setelem(const struct nft_ctx *ctx, | |||
3820 | const struct nft_set_iter *iter, | 3898 | const struct nft_set_iter *iter, |
3821 | const struct nft_set_elem *elem) | 3899 | const struct nft_set_elem *elem) |
3822 | { | 3900 | { |
3823 | if (elem->flags & NFT_SET_ELEM_INTERVAL_END) | 3901 | const struct nft_set_ext *ext = nft_set_elem_ext(set, elem->priv); |
3902 | const struct nft_data *data; | ||
3903 | |||
3904 | if (nft_set_ext_exists(ext, NFT_SET_EXT_FLAGS) && | ||
3905 | *nft_set_ext_flags(ext) & NFT_SET_ELEM_INTERVAL_END) | ||
3824 | return 0; | 3906 | return 0; |
3825 | 3907 | ||
3826 | switch (elem->data.verdict) { | 3908 | data = nft_set_ext_data(ext); |
3909 | switch (data->verdict) { | ||
3827 | case NFT_JUMP: | 3910 | case NFT_JUMP: |
3828 | case NFT_GOTO: | 3911 | case NFT_GOTO: |
3829 | return nf_tables_check_loops(ctx, elem->data.chain); | 3912 | return nf_tables_check_loops(ctx, data->chain); |
3830 | default: | 3913 | default: |
3831 | return 0; | 3914 | return 0; |
3832 | } | 3915 | } |
diff --git a/net/netfilter/nf_tables_core.c b/net/netfilter/nf_tables_core.c index 77165bf023f3..ef4dfcbaf149 100644 --- a/net/netfilter/nf_tables_core.c +++ b/net/netfilter/nf_tables_core.c | |||
@@ -8,6 +8,7 @@ | |||
8 | * Development of this code funded by Astaro AG (http://www.astaro.com/) | 8 | * Development of this code funded by Astaro AG (http://www.astaro.com/) |
9 | */ | 9 | */ |
10 | 10 | ||
11 | #include <linux/kernel.h> | ||
11 | #include <linux/module.h> | 12 | #include <linux/module.h> |
12 | #include <linux/init.h> | 13 | #include <linux/init.h> |
13 | #include <linux/list.h> | 14 | #include <linux/list.h> |
@@ -37,7 +38,7 @@ static struct nf_loginfo trace_loginfo = { | |||
37 | .type = NF_LOG_TYPE_LOG, | 38 | .type = NF_LOG_TYPE_LOG, |
38 | .u = { | 39 | .u = { |
39 | .log = { | 40 | .log = { |
40 | .level = 4, | 41 | .level = LOGLEVEL_WARNING, |
41 | .logflags = NF_LOG_MASK, | 42 | .logflags = NF_LOG_MASK, |
42 | }, | 43 | }, |
43 | }, | 44 | }, |
@@ -49,10 +50,10 @@ static void __nft_trace_packet(const struct nft_pktinfo *pkt, | |||
49 | { | 50 | { |
50 | struct net *net = dev_net(pkt->in ? pkt->in : pkt->out); | 51 | struct net *net = dev_net(pkt->in ? pkt->in : pkt->out); |
51 | 52 | ||
52 | nf_log_packet(net, pkt->xt.family, pkt->ops->hooknum, pkt->skb, pkt->in, | 53 | nf_log_trace(net, pkt->xt.family, pkt->ops->hooknum, pkt->skb, pkt->in, |
53 | pkt->out, &trace_loginfo, "TRACE: %s:%s:%s:%u ", | 54 | pkt->out, &trace_loginfo, "TRACE: %s:%s:%s:%u ", |
54 | chain->table->name, chain->name, comments[type], | 55 | chain->table->name, chain->name, comments[type], |
55 | rulenum); | 56 | rulenum); |
56 | } | 57 | } |
57 | 58 | ||
58 | static inline void nft_trace_packet(const struct nft_pktinfo *pkt, | 59 | static inline void nft_trace_packet(const struct nft_pktinfo *pkt, |
@@ -112,6 +113,7 @@ unsigned int | |||
112 | nft_do_chain(struct nft_pktinfo *pkt, const struct nf_hook_ops *ops) | 113 | nft_do_chain(struct nft_pktinfo *pkt, const struct nf_hook_ops *ops) |
113 | { | 114 | { |
114 | const struct nft_chain *chain = ops->priv, *basechain = chain; | 115 | const struct nft_chain *chain = ops->priv, *basechain = chain; |
116 | const struct net *net = read_pnet(&nft_base_chain(basechain)->pnet); | ||
115 | const struct nft_rule *rule; | 117 | const struct nft_rule *rule; |
116 | const struct nft_expr *expr, *last; | 118 | const struct nft_expr *expr, *last; |
117 | struct nft_data data[NFT_REG_MAX + 1]; | 119 | struct nft_data data[NFT_REG_MAX + 1]; |
@@ -119,11 +121,7 @@ nft_do_chain(struct nft_pktinfo *pkt, const struct nf_hook_ops *ops) | |||
119 | struct nft_jumpstack jumpstack[NFT_JUMP_STACK_SIZE]; | 121 | struct nft_jumpstack jumpstack[NFT_JUMP_STACK_SIZE]; |
120 | struct nft_stats *stats; | 122 | struct nft_stats *stats; |
121 | int rulenum; | 123 | int rulenum; |
122 | /* | 124 | unsigned int gencursor = nft_genmask_cur(net); |
123 | * Cache cursor to avoid problems in case that the cursor is updated | ||
124 | * while traversing the ruleset. | ||
125 | */ | ||
126 | unsigned int gencursor = ACCESS_ONCE(chain->net->nft.gencursor); | ||
127 | 125 | ||
128 | do_chain: | 126 | do_chain: |
129 | rulenum = 0; | 127 | rulenum = 0; |
diff --git a/net/netfilter/nft_hash.c b/net/netfilter/nft_hash.c index f9ce2195fd63..c7e1a9d7d46f 100644 --- a/net/netfilter/nft_hash.c +++ b/net/netfilter/nft_hash.c | |||
@@ -23,104 +23,130 @@ | |||
23 | /* We target a hash table size of 4, element hint is 75% of final size */ | 23 | /* We target a hash table size of 4, element hint is 75% of final size */ |
24 | #define NFT_HASH_ELEMENT_HINT 3 | 24 | #define NFT_HASH_ELEMENT_HINT 3 |
25 | 25 | ||
26 | struct nft_hash { | ||
27 | struct rhashtable ht; | ||
28 | }; | ||
29 | |||
26 | struct nft_hash_elem { | 30 | struct nft_hash_elem { |
27 | struct rhash_head node; | 31 | struct rhash_head node; |
28 | struct nft_data key; | 32 | struct nft_set_ext ext; |
29 | struct nft_data data[]; | 33 | }; |
34 | |||
35 | struct nft_hash_cmp_arg { | ||
36 | const struct nft_set *set; | ||
37 | const struct nft_data *key; | ||
38 | u8 genmask; | ||
30 | }; | 39 | }; |
31 | 40 | ||
32 | static const struct rhashtable_params nft_hash_params; | 41 | static const struct rhashtable_params nft_hash_params; |
33 | 42 | ||
34 | static bool nft_hash_lookup(const struct nft_set *set, | 43 | static inline u32 nft_hash_key(const void *data, u32 len, u32 seed) |
35 | const struct nft_data *key, | ||
36 | struct nft_data *data) | ||
37 | { | 44 | { |
38 | struct rhashtable *priv = nft_set_priv(set); | 45 | const struct nft_hash_cmp_arg *arg = data; |
39 | const struct nft_hash_elem *he; | ||
40 | |||
41 | he = rhashtable_lookup_fast(priv, key, nft_hash_params); | ||
42 | if (he && set->flags & NFT_SET_MAP) | ||
43 | nft_data_copy(data, he->data); | ||
44 | 46 | ||
45 | return !!he; | 47 | return jhash(arg->key, len, seed); |
46 | } | 48 | } |
47 | 49 | ||
48 | static int nft_hash_insert(const struct nft_set *set, | 50 | static inline u32 nft_hash_obj(const void *data, u32 len, u32 seed) |
49 | const struct nft_set_elem *elem) | ||
50 | { | 51 | { |
51 | struct rhashtable *priv = nft_set_priv(set); | 52 | const struct nft_hash_elem *he = data; |
52 | struct nft_hash_elem *he; | ||
53 | unsigned int size; | ||
54 | int err; | ||
55 | 53 | ||
56 | if (elem->flags != 0) | 54 | return jhash(nft_set_ext_key(&he->ext), len, seed); |
57 | return -EINVAL; | 55 | } |
58 | 56 | ||
59 | size = sizeof(*he); | 57 | static inline int nft_hash_cmp(struct rhashtable_compare_arg *arg, |
60 | if (set->flags & NFT_SET_MAP) | 58 | const void *ptr) |
61 | size += sizeof(he->data[0]); | 59 | { |
60 | const struct nft_hash_cmp_arg *x = arg->key; | ||
61 | const struct nft_hash_elem *he = ptr; | ||
62 | 62 | ||
63 | he = kzalloc(size, GFP_KERNEL); | 63 | if (nft_data_cmp(nft_set_ext_key(&he->ext), x->key, x->set->klen)) |
64 | if (he == NULL) | 64 | return 1; |
65 | return -ENOMEM; | 65 | if (!nft_set_elem_active(&he->ext, x->genmask)) |
66 | return 1; | ||
67 | return 0; | ||
68 | } | ||
66 | 69 | ||
67 | nft_data_copy(&he->key, &elem->key); | 70 | static bool nft_hash_lookup(const struct nft_set *set, |
68 | if (set->flags & NFT_SET_MAP) | 71 | const struct nft_data *key, |
69 | nft_data_copy(he->data, &elem->data); | 72 | const struct nft_set_ext **ext) |
73 | { | ||
74 | struct nft_hash *priv = nft_set_priv(set); | ||
75 | const struct nft_hash_elem *he; | ||
76 | struct nft_hash_cmp_arg arg = { | ||
77 | .genmask = nft_genmask_cur(read_pnet(&set->pnet)), | ||
78 | .set = set, | ||
79 | .key = key, | ||
80 | }; | ||
70 | 81 | ||
71 | err = rhashtable_insert_fast(priv, &he->node, nft_hash_params); | 82 | he = rhashtable_lookup_fast(&priv->ht, &arg, nft_hash_params); |
72 | if (err) | 83 | if (he != NULL) |
73 | kfree(he); | 84 | *ext = &he->ext; |
74 | 85 | ||
75 | return err; | 86 | return !!he; |
76 | } | 87 | } |
77 | 88 | ||
78 | static void nft_hash_elem_destroy(const struct nft_set *set, | 89 | static int nft_hash_insert(const struct nft_set *set, |
79 | struct nft_hash_elem *he) | 90 | const struct nft_set_elem *elem) |
80 | { | 91 | { |
81 | nft_data_uninit(&he->key, NFT_DATA_VALUE); | 92 | struct nft_hash *priv = nft_set_priv(set); |
82 | if (set->flags & NFT_SET_MAP) | 93 | struct nft_hash_elem *he = elem->priv; |
83 | nft_data_uninit(he->data, set->dtype); | 94 | struct nft_hash_cmp_arg arg = { |
84 | kfree(he); | 95 | .genmask = nft_genmask_next(read_pnet(&set->pnet)), |
96 | .set = set, | ||
97 | .key = &elem->key, | ||
98 | }; | ||
99 | |||
100 | return rhashtable_lookup_insert_key(&priv->ht, &arg, &he->node, | ||
101 | nft_hash_params); | ||
85 | } | 102 | } |
86 | 103 | ||
87 | static void nft_hash_remove(const struct nft_set *set, | 104 | static void nft_hash_activate(const struct nft_set *set, |
88 | const struct nft_set_elem *elem) | 105 | const struct nft_set_elem *elem) |
89 | { | 106 | { |
90 | struct rhashtable *priv = nft_set_priv(set); | 107 | struct nft_hash_elem *he = elem->priv; |
91 | 108 | ||
92 | rhashtable_remove_fast(priv, elem->cookie, nft_hash_params); | 109 | nft_set_elem_change_active(set, &he->ext); |
93 | synchronize_rcu(); | ||
94 | kfree(elem->cookie); | ||
95 | } | 110 | } |
96 | 111 | ||
97 | static int nft_hash_get(const struct nft_set *set, struct nft_set_elem *elem) | 112 | static void *nft_hash_deactivate(const struct nft_set *set, |
113 | const struct nft_set_elem *elem) | ||
98 | { | 114 | { |
99 | struct rhashtable *priv = nft_set_priv(set); | 115 | struct nft_hash *priv = nft_set_priv(set); |
100 | struct nft_hash_elem *he; | 116 | struct nft_hash_elem *he; |
117 | struct nft_hash_cmp_arg arg = { | ||
118 | .genmask = nft_genmask_next(read_pnet(&set->pnet)), | ||
119 | .set = set, | ||
120 | .key = &elem->key, | ||
121 | }; | ||
101 | 122 | ||
102 | he = rhashtable_lookup_fast(priv, &elem->key, nft_hash_params); | 123 | he = rhashtable_lookup_fast(&priv->ht, &arg, nft_hash_params); |
103 | if (!he) | 124 | if (he != NULL) |
104 | return -ENOENT; | 125 | nft_set_elem_change_active(set, &he->ext); |
105 | 126 | ||
106 | elem->cookie = he; | 127 | return he; |
107 | elem->flags = 0; | 128 | } |
108 | if (set->flags & NFT_SET_MAP) | ||
109 | nft_data_copy(&elem->data, he->data); | ||
110 | 129 | ||
111 | return 0; | 130 | static void nft_hash_remove(const struct nft_set *set, |
131 | const struct nft_set_elem *elem) | ||
132 | { | ||
133 | struct nft_hash *priv = nft_set_priv(set); | ||
134 | struct nft_hash_elem *he = elem->priv; | ||
135 | |||
136 | rhashtable_remove_fast(&priv->ht, &he->node, nft_hash_params); | ||
112 | } | 137 | } |
113 | 138 | ||
114 | static void nft_hash_walk(const struct nft_ctx *ctx, const struct nft_set *set, | 139 | static void nft_hash_walk(const struct nft_ctx *ctx, const struct nft_set *set, |
115 | struct nft_set_iter *iter) | 140 | struct nft_set_iter *iter) |
116 | { | 141 | { |
117 | struct rhashtable *priv = nft_set_priv(set); | 142 | struct nft_hash *priv = nft_set_priv(set); |
118 | const struct nft_hash_elem *he; | 143 | struct nft_hash_elem *he; |
119 | struct rhashtable_iter hti; | 144 | struct rhashtable_iter hti; |
120 | struct nft_set_elem elem; | 145 | struct nft_set_elem elem; |
146 | u8 genmask = nft_genmask_cur(read_pnet(&set->pnet)); | ||
121 | int err; | 147 | int err; |
122 | 148 | ||
123 | err = rhashtable_walk_init(priv, &hti); | 149 | err = rhashtable_walk_init(&priv->ht, &hti); |
124 | iter->err = err; | 150 | iter->err = err; |
125 | if (err) | 151 | if (err) |
126 | return; | 152 | return; |
@@ -144,11 +170,10 @@ static void nft_hash_walk(const struct nft_ctx *ctx, const struct nft_set *set, | |||
144 | 170 | ||
145 | if (iter->count < iter->skip) | 171 | if (iter->count < iter->skip) |
146 | goto cont; | 172 | goto cont; |
173 | if (!nft_set_elem_active(&he->ext, genmask)) | ||
174 | goto cont; | ||
147 | 175 | ||
148 | memcpy(&elem.key, &he->key, sizeof(elem.key)); | 176 | elem.priv = he; |
149 | if (set->flags & NFT_SET_MAP) | ||
150 | memcpy(&elem.data, he->data, sizeof(elem.data)); | ||
151 | elem.flags = 0; | ||
152 | 177 | ||
153 | iter->err = iter->fn(ctx, set, iter, &elem); | 178 | iter->err = iter->fn(ctx, set, iter, &elem); |
154 | if (iter->err < 0) | 179 | if (iter->err < 0) |
@@ -165,37 +190,40 @@ out: | |||
165 | 190 | ||
166 | static unsigned int nft_hash_privsize(const struct nlattr * const nla[]) | 191 | static unsigned int nft_hash_privsize(const struct nlattr * const nla[]) |
167 | { | 192 | { |
168 | return sizeof(struct rhashtable); | 193 | return sizeof(struct nft_hash); |
169 | } | 194 | } |
170 | 195 | ||
171 | static const struct rhashtable_params nft_hash_params = { | 196 | static const struct rhashtable_params nft_hash_params = { |
172 | .head_offset = offsetof(struct nft_hash_elem, node), | 197 | .head_offset = offsetof(struct nft_hash_elem, node), |
173 | .key_offset = offsetof(struct nft_hash_elem, key), | 198 | .hashfn = nft_hash_key, |
174 | .hashfn = jhash, | 199 | .obj_hashfn = nft_hash_obj, |
175 | .automatic_shrinking = true, | 200 | .obj_cmpfn = nft_hash_cmp, |
201 | .automatic_shrinking = true, | ||
176 | }; | 202 | }; |
177 | 203 | ||
178 | static int nft_hash_init(const struct nft_set *set, | 204 | static int nft_hash_init(const struct nft_set *set, |
179 | const struct nft_set_desc *desc, | 205 | const struct nft_set_desc *desc, |
180 | const struct nlattr * const tb[]) | 206 | const struct nlattr * const tb[]) |
181 | { | 207 | { |
182 | struct rhashtable *priv = nft_set_priv(set); | 208 | struct nft_hash *priv = nft_set_priv(set); |
183 | struct rhashtable_params params = nft_hash_params; | 209 | struct rhashtable_params params = nft_hash_params; |
184 | 210 | ||
185 | params.nelem_hint = desc->size ?: NFT_HASH_ELEMENT_HINT; | 211 | params.nelem_hint = desc->size ?: NFT_HASH_ELEMENT_HINT; |
186 | params.key_len = set->klen; | 212 | params.key_len = set->klen; |
187 | 213 | ||
188 | return rhashtable_init(priv, ¶ms); | 214 | return rhashtable_init(&priv->ht, ¶ms); |
189 | } | 215 | } |
190 | 216 | ||
191 | static void nft_free_element(void *ptr, void *arg) | 217 | static void nft_hash_elem_destroy(void *ptr, void *arg) |
192 | { | 218 | { |
193 | nft_hash_elem_destroy((const struct nft_set *)arg, ptr); | 219 | nft_set_elem_destroy((const struct nft_set *)arg, ptr); |
194 | } | 220 | } |
195 | 221 | ||
196 | static void nft_hash_destroy(const struct nft_set *set) | 222 | static void nft_hash_destroy(const struct nft_set *set) |
197 | { | 223 | { |
198 | rhashtable_free_and_destroy(nft_set_priv(set), nft_free_element, | 224 | struct nft_hash *priv = nft_set_priv(set); |
225 | |||
226 | rhashtable_free_and_destroy(&priv->ht, nft_hash_elem_destroy, | ||
199 | (void *)set); | 227 | (void *)set); |
200 | } | 228 | } |
201 | 229 | ||
@@ -205,11 +233,8 @@ static bool nft_hash_estimate(const struct nft_set_desc *desc, u32 features, | |||
205 | unsigned int esize; | 233 | unsigned int esize; |
206 | 234 | ||
207 | esize = sizeof(struct nft_hash_elem); | 235 | esize = sizeof(struct nft_hash_elem); |
208 | if (features & NFT_SET_MAP) | ||
209 | esize += FIELD_SIZEOF(struct nft_hash_elem, data[0]); | ||
210 | |||
211 | if (desc->size) { | 236 | if (desc->size) { |
212 | est->size = sizeof(struct rhashtable) + | 237 | est->size = sizeof(struct nft_hash) + |
213 | roundup_pow_of_two(desc->size * 4 / 3) * | 238 | roundup_pow_of_two(desc->size * 4 / 3) * |
214 | sizeof(struct nft_hash_elem *) + | 239 | sizeof(struct nft_hash_elem *) + |
215 | desc->size * esize; | 240 | desc->size * esize; |
@@ -229,11 +254,13 @@ static bool nft_hash_estimate(const struct nft_set_desc *desc, u32 features, | |||
229 | 254 | ||
230 | static struct nft_set_ops nft_hash_ops __read_mostly = { | 255 | static struct nft_set_ops nft_hash_ops __read_mostly = { |
231 | .privsize = nft_hash_privsize, | 256 | .privsize = nft_hash_privsize, |
257 | .elemsize = offsetof(struct nft_hash_elem, ext), | ||
232 | .estimate = nft_hash_estimate, | 258 | .estimate = nft_hash_estimate, |
233 | .init = nft_hash_init, | 259 | .init = nft_hash_init, |
234 | .destroy = nft_hash_destroy, | 260 | .destroy = nft_hash_destroy, |
235 | .get = nft_hash_get, | ||
236 | .insert = nft_hash_insert, | 261 | .insert = nft_hash_insert, |
262 | .activate = nft_hash_activate, | ||
263 | .deactivate = nft_hash_deactivate, | ||
237 | .remove = nft_hash_remove, | 264 | .remove = nft_hash_remove, |
238 | .lookup = nft_hash_lookup, | 265 | .lookup = nft_hash_lookup, |
239 | .walk = nft_hash_walk, | 266 | .walk = nft_hash_walk, |
diff --git a/net/netfilter/nft_log.c b/net/netfilter/nft_log.c index bde05f28cf14..e18af9db2f04 100644 --- a/net/netfilter/nft_log.c +++ b/net/netfilter/nft_log.c | |||
@@ -78,7 +78,7 @@ static int nft_log_init(const struct nft_ctx *ctx, | |||
78 | li->u.log.level = | 78 | li->u.log.level = |
79 | ntohl(nla_get_be32(tb[NFTA_LOG_LEVEL])); | 79 | ntohl(nla_get_be32(tb[NFTA_LOG_LEVEL])); |
80 | } else { | 80 | } else { |
81 | li->u.log.level = 4; | 81 | li->u.log.level = LOGLEVEL_WARNING; |
82 | } | 82 | } |
83 | if (tb[NFTA_LOG_FLAGS] != NULL) { | 83 | if (tb[NFTA_LOG_FLAGS] != NULL) { |
84 | li->u.log.logflags = | 84 | li->u.log.logflags = |
diff --git a/net/netfilter/nft_lookup.c b/net/netfilter/nft_lookup.c index 9615b8b9fb37..a5f30b8760ea 100644 --- a/net/netfilter/nft_lookup.c +++ b/net/netfilter/nft_lookup.c | |||
@@ -31,9 +31,13 @@ static void nft_lookup_eval(const struct nft_expr *expr, | |||
31 | { | 31 | { |
32 | const struct nft_lookup *priv = nft_expr_priv(expr); | 32 | const struct nft_lookup *priv = nft_expr_priv(expr); |
33 | const struct nft_set *set = priv->set; | 33 | const struct nft_set *set = priv->set; |
34 | const struct nft_set_ext *ext; | ||
34 | 35 | ||
35 | if (set->ops->lookup(set, &data[priv->sreg], &data[priv->dreg])) | 36 | if (set->ops->lookup(set, &data[priv->sreg], &ext)) { |
37 | if (set->flags & NFT_SET_MAP) | ||
38 | nft_data_copy(&data[priv->dreg], nft_set_ext_data(ext)); | ||
36 | return; | 39 | return; |
40 | } | ||
37 | data[NFT_REG_VERDICT].verdict = NFT_BREAK; | 41 | data[NFT_REG_VERDICT].verdict = NFT_BREAK; |
38 | } | 42 | } |
39 | 43 | ||
diff --git a/net/netfilter/nft_meta.c b/net/netfilter/nft_meta.c index abe68119a76c..5197874372ec 100644 --- a/net/netfilter/nft_meta.c +++ b/net/netfilter/nft_meta.c | |||
@@ -153,7 +153,7 @@ void nft_meta_get_eval(const struct nft_expr *expr, | |||
153 | } | 153 | } |
154 | break; | 154 | break; |
155 | case NFT_META_CPU: | 155 | case NFT_META_CPU: |
156 | dest->data[0] = smp_processor_id(); | 156 | dest->data[0] = raw_smp_processor_id(); |
157 | break; | 157 | break; |
158 | case NFT_META_IIFGROUP: | 158 | case NFT_META_IIFGROUP: |
159 | if (in == NULL) | 159 | if (in == NULL) |
diff --git a/net/netfilter/nft_rbtree.c b/net/netfilter/nft_rbtree.c index 2c75361077f7..42d0ca45fb9e 100644 --- a/net/netfilter/nft_rbtree.c +++ b/net/netfilter/nft_rbtree.c | |||
@@ -26,18 +26,18 @@ struct nft_rbtree { | |||
26 | 26 | ||
27 | struct nft_rbtree_elem { | 27 | struct nft_rbtree_elem { |
28 | struct rb_node node; | 28 | struct rb_node node; |
29 | u16 flags; | 29 | struct nft_set_ext ext; |
30 | struct nft_data key; | ||
31 | struct nft_data data[]; | ||
32 | }; | 30 | }; |
33 | 31 | ||
32 | |||
34 | static bool nft_rbtree_lookup(const struct nft_set *set, | 33 | static bool nft_rbtree_lookup(const struct nft_set *set, |
35 | const struct nft_data *key, | 34 | const struct nft_data *key, |
36 | struct nft_data *data) | 35 | const struct nft_set_ext **ext) |
37 | { | 36 | { |
38 | const struct nft_rbtree *priv = nft_set_priv(set); | 37 | const struct nft_rbtree *priv = nft_set_priv(set); |
39 | const struct nft_rbtree_elem *rbe, *interval = NULL; | 38 | const struct nft_rbtree_elem *rbe, *interval = NULL; |
40 | const struct rb_node *parent; | 39 | const struct rb_node *parent; |
40 | u8 genmask = nft_genmask_cur(read_pnet(&set->pnet)); | ||
41 | int d; | 41 | int d; |
42 | 42 | ||
43 | spin_lock_bh(&nft_rbtree_lock); | 43 | spin_lock_bh(&nft_rbtree_lock); |
@@ -45,7 +45,7 @@ static bool nft_rbtree_lookup(const struct nft_set *set, | |||
45 | while (parent != NULL) { | 45 | while (parent != NULL) { |
46 | rbe = rb_entry(parent, struct nft_rbtree_elem, node); | 46 | rbe = rb_entry(parent, struct nft_rbtree_elem, node); |
47 | 47 | ||
48 | d = nft_data_cmp(&rbe->key, key, set->klen); | 48 | d = nft_data_cmp(nft_set_ext_key(&rbe->ext), key, set->klen); |
49 | if (d < 0) { | 49 | if (d < 0) { |
50 | parent = parent->rb_left; | 50 | parent = parent->rb_left; |
51 | interval = rbe; | 51 | interval = rbe; |
@@ -53,12 +53,17 @@ static bool nft_rbtree_lookup(const struct nft_set *set, | |||
53 | parent = parent->rb_right; | 53 | parent = parent->rb_right; |
54 | else { | 54 | else { |
55 | found: | 55 | found: |
56 | if (rbe->flags & NFT_SET_ELEM_INTERVAL_END) | 56 | if (!nft_set_elem_active(&rbe->ext, genmask)) { |
57 | parent = parent->rb_left; | ||
58 | continue; | ||
59 | } | ||
60 | if (nft_set_ext_exists(&rbe->ext, NFT_SET_EXT_FLAGS) && | ||
61 | *nft_set_ext_flags(&rbe->ext) & | ||
62 | NFT_SET_ELEM_INTERVAL_END) | ||
57 | goto out; | 63 | goto out; |
58 | if (set->flags & NFT_SET_MAP) | ||
59 | nft_data_copy(data, rbe->data); | ||
60 | |||
61 | spin_unlock_bh(&nft_rbtree_lock); | 64 | spin_unlock_bh(&nft_rbtree_lock); |
65 | |||
66 | *ext = &rbe->ext; | ||
62 | return true; | 67 | return true; |
63 | } | 68 | } |
64 | } | 69 | } |
@@ -72,23 +77,13 @@ out: | |||
72 | return false; | 77 | return false; |
73 | } | 78 | } |
74 | 79 | ||
75 | static void nft_rbtree_elem_destroy(const struct nft_set *set, | ||
76 | struct nft_rbtree_elem *rbe) | ||
77 | { | ||
78 | nft_data_uninit(&rbe->key, NFT_DATA_VALUE); | ||
79 | if (set->flags & NFT_SET_MAP && | ||
80 | !(rbe->flags & NFT_SET_ELEM_INTERVAL_END)) | ||
81 | nft_data_uninit(rbe->data, set->dtype); | ||
82 | |||
83 | kfree(rbe); | ||
84 | } | ||
85 | |||
86 | static int __nft_rbtree_insert(const struct nft_set *set, | 80 | static int __nft_rbtree_insert(const struct nft_set *set, |
87 | struct nft_rbtree_elem *new) | 81 | struct nft_rbtree_elem *new) |
88 | { | 82 | { |
89 | struct nft_rbtree *priv = nft_set_priv(set); | 83 | struct nft_rbtree *priv = nft_set_priv(set); |
90 | struct nft_rbtree_elem *rbe; | 84 | struct nft_rbtree_elem *rbe; |
91 | struct rb_node *parent, **p; | 85 | struct rb_node *parent, **p; |
86 | u8 genmask = nft_genmask_next(read_pnet(&set->pnet)); | ||
92 | int d; | 87 | int d; |
93 | 88 | ||
94 | parent = NULL; | 89 | parent = NULL; |
@@ -96,13 +91,18 @@ static int __nft_rbtree_insert(const struct nft_set *set, | |||
96 | while (*p != NULL) { | 91 | while (*p != NULL) { |
97 | parent = *p; | 92 | parent = *p; |
98 | rbe = rb_entry(parent, struct nft_rbtree_elem, node); | 93 | rbe = rb_entry(parent, struct nft_rbtree_elem, node); |
99 | d = nft_data_cmp(&rbe->key, &new->key, set->klen); | 94 | d = nft_data_cmp(nft_set_ext_key(&rbe->ext), |
95 | nft_set_ext_key(&new->ext), | ||
96 | set->klen); | ||
100 | if (d < 0) | 97 | if (d < 0) |
101 | p = &parent->rb_left; | 98 | p = &parent->rb_left; |
102 | else if (d > 0) | 99 | else if (d > 0) |
103 | p = &parent->rb_right; | 100 | p = &parent->rb_right; |
104 | else | 101 | else { |
105 | return -EEXIST; | 102 | if (nft_set_elem_active(&rbe->ext, genmask)) |
103 | return -EEXIST; | ||
104 | p = &parent->rb_left; | ||
105 | } | ||
106 | } | 106 | } |
107 | rb_link_node(&new->node, parent, p); | 107 | rb_link_node(&new->node, parent, p); |
108 | rb_insert_color(&new->node, &priv->root); | 108 | rb_insert_color(&new->node, &priv->root); |
@@ -112,31 +112,13 @@ static int __nft_rbtree_insert(const struct nft_set *set, | |||
112 | static int nft_rbtree_insert(const struct nft_set *set, | 112 | static int nft_rbtree_insert(const struct nft_set *set, |
113 | const struct nft_set_elem *elem) | 113 | const struct nft_set_elem *elem) |
114 | { | 114 | { |
115 | struct nft_rbtree_elem *rbe; | 115 | struct nft_rbtree_elem *rbe = elem->priv; |
116 | unsigned int size; | ||
117 | int err; | 116 | int err; |
118 | 117 | ||
119 | size = sizeof(*rbe); | ||
120 | if (set->flags & NFT_SET_MAP && | ||
121 | !(elem->flags & NFT_SET_ELEM_INTERVAL_END)) | ||
122 | size += sizeof(rbe->data[0]); | ||
123 | |||
124 | rbe = kzalloc(size, GFP_KERNEL); | ||
125 | if (rbe == NULL) | ||
126 | return -ENOMEM; | ||
127 | |||
128 | rbe->flags = elem->flags; | ||
129 | nft_data_copy(&rbe->key, &elem->key); | ||
130 | if (set->flags & NFT_SET_MAP && | ||
131 | !(rbe->flags & NFT_SET_ELEM_INTERVAL_END)) | ||
132 | nft_data_copy(rbe->data, &elem->data); | ||
133 | |||
134 | spin_lock_bh(&nft_rbtree_lock); | 118 | spin_lock_bh(&nft_rbtree_lock); |
135 | err = __nft_rbtree_insert(set, rbe); | 119 | err = __nft_rbtree_insert(set, rbe); |
136 | if (err < 0) | ||
137 | kfree(rbe); | ||
138 | |||
139 | spin_unlock_bh(&nft_rbtree_lock); | 120 | spin_unlock_bh(&nft_rbtree_lock); |
121 | |||
140 | return err; | 122 | return err; |
141 | } | 123 | } |
142 | 124 | ||
@@ -144,39 +126,49 @@ static void nft_rbtree_remove(const struct nft_set *set, | |||
144 | const struct nft_set_elem *elem) | 126 | const struct nft_set_elem *elem) |
145 | { | 127 | { |
146 | struct nft_rbtree *priv = nft_set_priv(set); | 128 | struct nft_rbtree *priv = nft_set_priv(set); |
147 | struct nft_rbtree_elem *rbe = elem->cookie; | 129 | struct nft_rbtree_elem *rbe = elem->priv; |
148 | 130 | ||
149 | spin_lock_bh(&nft_rbtree_lock); | 131 | spin_lock_bh(&nft_rbtree_lock); |
150 | rb_erase(&rbe->node, &priv->root); | 132 | rb_erase(&rbe->node, &priv->root); |
151 | spin_unlock_bh(&nft_rbtree_lock); | 133 | spin_unlock_bh(&nft_rbtree_lock); |
152 | kfree(rbe); | ||
153 | } | 134 | } |
154 | 135 | ||
155 | static int nft_rbtree_get(const struct nft_set *set, struct nft_set_elem *elem) | 136 | static void nft_rbtree_activate(const struct nft_set *set, |
137 | const struct nft_set_elem *elem) | ||
138 | { | ||
139 | struct nft_rbtree_elem *rbe = elem->priv; | ||
140 | |||
141 | nft_set_elem_change_active(set, &rbe->ext); | ||
142 | } | ||
143 | |||
144 | static void *nft_rbtree_deactivate(const struct nft_set *set, | ||
145 | const struct nft_set_elem *elem) | ||
156 | { | 146 | { |
157 | const struct nft_rbtree *priv = nft_set_priv(set); | 147 | const struct nft_rbtree *priv = nft_set_priv(set); |
158 | const struct rb_node *parent = priv->root.rb_node; | 148 | const struct rb_node *parent = priv->root.rb_node; |
159 | struct nft_rbtree_elem *rbe; | 149 | struct nft_rbtree_elem *rbe; |
150 | u8 genmask = nft_genmask_cur(read_pnet(&set->pnet)); | ||
160 | int d; | 151 | int d; |
161 | 152 | ||
162 | while (parent != NULL) { | 153 | while (parent != NULL) { |
163 | rbe = rb_entry(parent, struct nft_rbtree_elem, node); | 154 | rbe = rb_entry(parent, struct nft_rbtree_elem, node); |
164 | 155 | ||
165 | d = nft_data_cmp(&rbe->key, &elem->key, set->klen); | 156 | d = nft_data_cmp(nft_set_ext_key(&rbe->ext), &elem->key, |
157 | set->klen); | ||
166 | if (d < 0) | 158 | if (d < 0) |
167 | parent = parent->rb_left; | 159 | parent = parent->rb_left; |
168 | else if (d > 0) | 160 | else if (d > 0) |
169 | parent = parent->rb_right; | 161 | parent = parent->rb_right; |
170 | else { | 162 | else { |
171 | elem->cookie = rbe; | 163 | if (!nft_set_elem_active(&rbe->ext, genmask)) { |
172 | if (set->flags & NFT_SET_MAP && | 164 | parent = parent->rb_left; |
173 | !(rbe->flags & NFT_SET_ELEM_INTERVAL_END)) | 165 | continue; |
174 | nft_data_copy(&elem->data, rbe->data); | 166 | } |
175 | elem->flags = rbe->flags; | 167 | nft_set_elem_change_active(set, &rbe->ext); |
176 | return 0; | 168 | return rbe; |
177 | } | 169 | } |
178 | } | 170 | } |
179 | return -ENOENT; | 171 | return NULL; |
180 | } | 172 | } |
181 | 173 | ||
182 | static void nft_rbtree_walk(const struct nft_ctx *ctx, | 174 | static void nft_rbtree_walk(const struct nft_ctx *ctx, |
@@ -184,21 +176,21 @@ static void nft_rbtree_walk(const struct nft_ctx *ctx, | |||
184 | struct nft_set_iter *iter) | 176 | struct nft_set_iter *iter) |
185 | { | 177 | { |
186 | const struct nft_rbtree *priv = nft_set_priv(set); | 178 | const struct nft_rbtree *priv = nft_set_priv(set); |
187 | const struct nft_rbtree_elem *rbe; | 179 | struct nft_rbtree_elem *rbe; |
188 | struct nft_set_elem elem; | 180 | struct nft_set_elem elem; |
189 | struct rb_node *node; | 181 | struct rb_node *node; |
182 | u8 genmask = nft_genmask_cur(read_pnet(&set->pnet)); | ||
190 | 183 | ||
191 | spin_lock_bh(&nft_rbtree_lock); | 184 | spin_lock_bh(&nft_rbtree_lock); |
192 | for (node = rb_first(&priv->root); node != NULL; node = rb_next(node)) { | 185 | for (node = rb_first(&priv->root); node != NULL; node = rb_next(node)) { |
186 | rbe = rb_entry(node, struct nft_rbtree_elem, node); | ||
187 | |||
193 | if (iter->count < iter->skip) | 188 | if (iter->count < iter->skip) |
194 | goto cont; | 189 | goto cont; |
190 | if (!nft_set_elem_active(&rbe->ext, genmask)) | ||
191 | goto cont; | ||
195 | 192 | ||
196 | rbe = rb_entry(node, struct nft_rbtree_elem, node); | 193 | elem.priv = rbe; |
197 | nft_data_copy(&elem.key, &rbe->key); | ||
198 | if (set->flags & NFT_SET_MAP && | ||
199 | !(rbe->flags & NFT_SET_ELEM_INTERVAL_END)) | ||
200 | nft_data_copy(&elem.data, rbe->data); | ||
201 | elem.flags = rbe->flags; | ||
202 | 194 | ||
203 | iter->err = iter->fn(ctx, set, iter, &elem); | 195 | iter->err = iter->fn(ctx, set, iter, &elem); |
204 | if (iter->err < 0) { | 196 | if (iter->err < 0) { |
@@ -235,7 +227,7 @@ static void nft_rbtree_destroy(const struct nft_set *set) | |||
235 | while ((node = priv->root.rb_node) != NULL) { | 227 | while ((node = priv->root.rb_node) != NULL) { |
236 | rb_erase(node, &priv->root); | 228 | rb_erase(node, &priv->root); |
237 | rbe = rb_entry(node, struct nft_rbtree_elem, node); | 229 | rbe = rb_entry(node, struct nft_rbtree_elem, node); |
238 | nft_rbtree_elem_destroy(set, rbe); | 230 | nft_set_elem_destroy(set, rbe); |
239 | } | 231 | } |
240 | } | 232 | } |
241 | 233 | ||
@@ -245,9 +237,6 @@ static bool nft_rbtree_estimate(const struct nft_set_desc *desc, u32 features, | |||
245 | unsigned int nsize; | 237 | unsigned int nsize; |
246 | 238 | ||
247 | nsize = sizeof(struct nft_rbtree_elem); | 239 | nsize = sizeof(struct nft_rbtree_elem); |
248 | if (features & NFT_SET_MAP) | ||
249 | nsize += FIELD_SIZEOF(struct nft_rbtree_elem, data[0]); | ||
250 | |||
251 | if (desc->size) | 240 | if (desc->size) |
252 | est->size = sizeof(struct nft_rbtree) + desc->size * nsize; | 241 | est->size = sizeof(struct nft_rbtree) + desc->size * nsize; |
253 | else | 242 | else |
@@ -260,12 +249,14 @@ static bool nft_rbtree_estimate(const struct nft_set_desc *desc, u32 features, | |||
260 | 249 | ||
261 | static struct nft_set_ops nft_rbtree_ops __read_mostly = { | 250 | static struct nft_set_ops nft_rbtree_ops __read_mostly = { |
262 | .privsize = nft_rbtree_privsize, | 251 | .privsize = nft_rbtree_privsize, |
252 | .elemsize = offsetof(struct nft_rbtree_elem, ext), | ||
263 | .estimate = nft_rbtree_estimate, | 253 | .estimate = nft_rbtree_estimate, |
264 | .init = nft_rbtree_init, | 254 | .init = nft_rbtree_init, |
265 | .destroy = nft_rbtree_destroy, | 255 | .destroy = nft_rbtree_destroy, |
266 | .insert = nft_rbtree_insert, | 256 | .insert = nft_rbtree_insert, |
267 | .remove = nft_rbtree_remove, | 257 | .remove = nft_rbtree_remove, |
268 | .get = nft_rbtree_get, | 258 | .deactivate = nft_rbtree_deactivate, |
259 | .activate = nft_rbtree_activate, | ||
269 | .lookup = nft_rbtree_lookup, | 260 | .lookup = nft_rbtree_lookup, |
270 | .walk = nft_rbtree_walk, | 261 | .walk = nft_rbtree_walk, |
271 | .features = NFT_SET_INTERVAL | NFT_SET_MAP, | 262 | .features = NFT_SET_INTERVAL | NFT_SET_MAP, |
diff --git a/net/netlink/af_netlink.c b/net/netlink/af_netlink.c index 4caa809dbbe0..19909d0786a2 100644 --- a/net/netlink/af_netlink.c +++ b/net/netlink/af_netlink.c | |||
@@ -3127,7 +3127,7 @@ static struct pernet_operations __net_initdata netlink_net_ops = { | |||
3127 | .exit = netlink_net_exit, | 3127 | .exit = netlink_net_exit, |
3128 | }; | 3128 | }; |
3129 | 3129 | ||
3130 | static inline u32 netlink_hash(const void *data, u32 seed) | 3130 | static inline u32 netlink_hash(const void *data, u32 len, u32 seed) |
3131 | { | 3131 | { |
3132 | const struct netlink_sock *nlk = data; | 3132 | const struct netlink_sock *nlk = data; |
3133 | struct netlink_compare_arg arg; | 3133 | struct netlink_compare_arg arg; |