Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

Merge git://git.kernel.org/pub/scm/linux/kernel/git/pablo/nf-next

Pablo Neira Ayuso says:

====================
Netfilter updates for net-next

The following patchset contains Netfilter updates for your net-next
tree. This batch contains connection tracking updates for the cleanup
iteration path, patches from Florian Westphal:

X) Skip unconfirmed conntracks in nf_ct_iterate_cleanup_net(), just set
dying bit to let the CPU release them.

X) Add nf_ct_iterate_destroy() to be used on module removal, to kill
conntrack from all namespace.

X) Restart iteration on hashtable resizing, since both may occur at
the same time.

X) Use the new nf_ct_iterate_destroy() to remove conntrack with NAT
mapping on module removal.

X) Use nf_ct_iterate_destroy() to remove conntrack entries helper
module removal, from Liping Zhang.

X) Use nf_ct_iterate_cleanup_net() to remove the timeout extension
if user requests this, also from Liping.

X) Add net_ns_barrier() and use it from FTP helper, so make sure
no concurrent namespace removal happens at the same time while
the helper module is being removed.

X) Use NFPROTO_MAX in layer 3 conntrack protocol array, to reduce
module size. Same thing in nf_tables.

Updates for the nf_tables infrastructure:

X) Prepare usage of the extended ACK reporting infrastructure for
nf_tables.

X) Remove unnecessary forward declaration in nf_tables hash set.

X) Skip set size estimation if number of element is not specified.

X) Changes to accomodate a (faster) unresizable hash set implementation,
for anonymous sets and dynamic size fixed sets with no timeouts.

X) Faster lookup function for unresizable hash table for 2 and 4
bytes key.

And, finally, a bunch of asorted small updates and cleanups:

X) Do not hold reference to netdev from ipt_CLUSTER, instead subscribe
to device events and look up for index from the packet path, this
is fixing an issue that is present since the very beginning, patch
from Xin Long.

X) Use nf_register_net_hook() in ipt_CLUSTER, from Florian Westphal.

X) Use ebt_invalid_target() whenever possible in the ebtables tree,
from Gao Feng.

X) Calm down compilation warning in nf_dup infrastructure, patch from
stephen hemminger.

X) Statify functions in nftables rt expression, also from stephen.

X) Update Makefile to use canonical method to specify nf_tables-objs.
From Jike Song.

X) Use nf_conntrack_helpers_register() in amanda and H323.

X) Space cleanup for ctnetlink, from linzhang.
====================

Signed-off-by: David S. Miller <davem@davemloft.net>

+951 -500
+6 -4
include/linux/netfilter/nfnetlink.h
··· 1 1 #ifndef _NFNETLINK_H 2 2 #define _NFNETLINK_H 3 3 4 - 5 4 #include <linux/netlink.h> 6 5 #include <linux/capability.h> 7 6 #include <net/netlink.h> ··· 9 10 struct nfnl_callback { 10 11 int (*call)(struct net *net, struct sock *nl, struct sk_buff *skb, 11 12 const struct nlmsghdr *nlh, 12 - const struct nlattr * const cda[]); 13 + const struct nlattr * const cda[], 14 + struct netlink_ext_ack *extack); 13 15 int (*call_rcu)(struct net *net, struct sock *nl, struct sk_buff *skb, 14 16 const struct nlmsghdr *nlh, 15 - const struct nlattr * const cda[]); 17 + const struct nlattr * const cda[], 18 + struct netlink_ext_ack *extack); 16 19 int (*call_batch)(struct net *net, struct sock *nl, struct sk_buff *skb, 17 20 const struct nlmsghdr *nlh, 18 - const struct nlattr * const cda[]); 21 + const struct nlattr * const cda[], 22 + struct netlink_ext_ack *extack); 19 23 const struct nla_policy *policy; /* netlink attribute policy */ 20 24 const u_int16_t attr_count; /* number of nlattr's */ 21 25 };
-2
include/linux/netfilter_bridge/ebtables.h
··· 122 122 #define BASE_CHAIN (par->hook_mask & (1 << NF_BR_NUMHOOKS)) 123 123 /* Clear the bit in the hook mask that tells if the rule is on a base chain */ 124 124 #define CLEAR_BASE_CHAIN_BIT (par->hook_mask &= ~(1 << NF_BR_NUMHOOKS)) 125 - /* True if the target is not a standard target */ 126 - #define INVALID_TARGET (info->target < -NUM_STANDARD_TARGETS || info->target >= 0) 127 125 128 126 static inline bool ebt_invalid_target(int target) 129 127 {
+3
include/net/net_namespace.h
··· 158 158 struct net *copy_net_ns(unsigned long flags, struct user_namespace *user_ns, 159 159 struct net *old_net); 160 160 161 + void net_ns_barrier(void); 161 162 #else /* CONFIG_NET_NS */ 162 163 #include <linux/sched.h> 163 164 #include <linux/nsproxy.h> ··· 169 168 return ERR_PTR(-EINVAL); 170 169 return old_net; 171 170 } 171 + 172 + static inline void net_ns_barrier(void) {} 172 173 #endif /* CONFIG_NET_NS */ 173 174 174 175
+7 -3
include/net/netfilter/nf_conntrack.h
··· 225 225 u32 seq); 226 226 227 227 /* Iterate over all conntracks: if iter returns true, it's deleted. */ 228 - void nf_ct_iterate_cleanup(struct net *net, 229 - int (*iter)(struct nf_conn *i, void *data), 230 - void *data, u32 portid, int report); 228 + void nf_ct_iterate_cleanup_net(struct net *net, 229 + int (*iter)(struct nf_conn *i, void *data), 230 + void *data, u32 portid, int report); 231 + 232 + /* also set unconfirmed conntracks as dying. Only use in module exit path. */ 233 + void nf_ct_iterate_destroy(int (*iter)(struct nf_conn *i, void *data), 234 + void *data); 231 235 232 236 struct nf_conntrack_zone; 233 237
+2 -2
include/net/netfilter/nf_conntrack_l3proto.h
··· 71 71 struct module *me; 72 72 }; 73 73 74 - extern struct nf_conntrack_l3proto __rcu *nf_ct_l3protos[AF_MAX]; 74 + extern struct nf_conntrack_l3proto __rcu *nf_ct_l3protos[NFPROTO_NUMPROTO]; 75 75 76 76 #ifdef CONFIG_SYSCTL 77 77 /* Protocol pernet registration. */ ··· 100 100 static inline struct nf_conntrack_l3proto * 101 101 __nf_ct_l3proto_find(u_int16_t l3proto) 102 102 { 103 - if (unlikely(l3proto >= AF_MAX)) 103 + if (unlikely(l3proto >= NFPROTO_NUMPROTO)) 104 104 return &nf_conntrack_l3proto_generic; 105 105 return rcu_dereference(nf_ct_l3protos[l3proto]); 106 106 }
+22 -7
include/net/netfilter/nf_tables.h
··· 281 281 enum nft_set_class space; 282 282 }; 283 283 284 + /** 285 + * struct nft_set_type - nf_tables set type 286 + * 287 + * @select_ops: function to select nft_set_ops 288 + * @ops: default ops, used when no select_ops functions is present 289 + * @list: used internally 290 + * @owner: module reference 291 + */ 292 + struct nft_set_type { 293 + const struct nft_set_ops *(*select_ops)(const struct nft_ctx *, 294 + const struct nft_set_desc *desc, 295 + u32 flags); 296 + const struct nft_set_ops *ops; 297 + struct list_head list; 298 + struct module *owner; 299 + }; 300 + 284 301 struct nft_set_ext; 285 302 struct nft_expr; 286 303 ··· 314 297 * @privsize: function to return size of set private data 315 298 * @init: initialize private data of new set instance 316 299 * @destroy: destroy private data of set instance 317 - * @list: nf_tables_set_ops list node 318 - * @owner: module reference 319 300 * @elemsize: element private size 320 301 * @features: features supported by the implementation 321 302 */ ··· 351 336 struct nft_set *set, 352 337 struct nft_set_iter *iter); 353 338 354 - unsigned int (*privsize)(const struct nlattr * const nla[]); 339 + unsigned int (*privsize)(const struct nlattr * const nla[], 340 + const struct nft_set_desc *desc); 355 341 bool (*estimate)(const struct nft_set_desc *desc, 356 342 u32 features, 357 343 struct nft_set_estimate *est); ··· 361 345 const struct nlattr * const nla[]); 362 346 void (*destroy)(const struct nft_set *set); 363 347 364 - struct list_head list; 365 - struct module *owner; 366 348 unsigned int elemsize; 367 349 u32 features; 350 + const struct nft_set_type *type; 368 351 }; 369 352 370 - int nft_register_set(struct nft_set_ops *ops); 371 - void nft_unregister_set(struct nft_set_ops *ops); 353 + int nft_register_set(struct nft_set_type *type); 354 + void nft_unregister_set(struct nft_set_type *type); 372 355 373 356 /** 374 357 * struct nft_set - nf_tables set instance
+1 -1
net/bridge/netfilter/ebt_dnat.c
··· 61 61 (strcmp(par->table, "broute") != 0 || 62 62 hook_mask & ~(1 << NF_BR_BROUTING))) 63 63 return -EINVAL; 64 - if (INVALID_TARGET) 64 + if (ebt_invalid_target(info->target)) 65 65 return -EINVAL; 66 66 return 0; 67 67 }
+1 -1
net/bridge/netfilter/ebt_mark.c
··· 44 44 tmp = info->target | ~EBT_VERDICT_BITS; 45 45 if (BASE_CHAIN && tmp == EBT_RETURN) 46 46 return -EINVAL; 47 - if (tmp < -NUM_STANDARD_TARGETS || tmp >= 0) 47 + if (ebt_invalid_target(tmp)) 48 48 return -EINVAL; 49 49 tmp = info->target & ~EBT_VERDICT_BITS; 50 50 if (tmp != MARK_SET_VALUE && tmp != MARK_OR_VALUE &&
+1 -1
net/bridge/netfilter/ebt_redirect.c
··· 47 47 (strcmp(par->table, "broute") != 0 || 48 48 hook_mask & ~(1 << NF_BR_BROUTING))) 49 49 return -EINVAL; 50 - if (INVALID_TARGET) 50 + if (ebt_invalid_target(info->target)) 51 51 return -EINVAL; 52 52 return 0; 53 53 }
+1 -1
net/bridge/netfilter/ebt_snat.c
··· 51 51 if (BASE_CHAIN && tmp == EBT_RETURN) 52 52 return -EINVAL; 53 53 54 - if (tmp < -NUM_STANDARD_TARGETS || tmp >= 0) 54 + if (ebt_invalid_target(tmp)) 55 55 return -EINVAL; 56 56 tmp = info->target | EBT_VERDICT_BITS; 57 57 if ((tmp & ~NAT_ARP_BIT) != ~NAT_ARP_BIT)
+17
net/core/net_namespace.c
··· 501 501 net_drop_ns(net); 502 502 } 503 503 } 504 + 505 + /** 506 + * net_ns_barrier - wait until concurrent net_cleanup_work is done 507 + * 508 + * cleanup_net runs from work queue and will first remove namespaces 509 + * from the global list, then run net exit functions. 510 + * 511 + * Call this in module exit path to make sure that all netns 512 + * ->exit ops have been invoked before the function is removed. 513 + */ 514 + void net_ns_barrier(void) 515 + { 516 + mutex_lock(&net_mutex); 517 + mutex_unlock(&net_mutex); 518 + } 519 + EXPORT_SYMBOL(net_ns_barrier); 520 + 504 521 static DECLARE_WORK(net_cleanup_work, cleanup_net); 505 522 506 523 void __put_net(struct net *net)
+80 -35
net/ipv4/netfilter/ipt_CLUSTERIP.c
··· 47 47 48 48 __be32 clusterip; /* the IP address */ 49 49 u_int8_t clustermac[ETH_ALEN]; /* the MAC address */ 50 - struct net_device *dev; /* device */ 50 + int ifindex; /* device ifindex */ 51 51 u_int16_t num_total_nodes; /* total number of nodes */ 52 52 unsigned long local_nodes; /* node number array */ 53 53 ··· 57 57 enum clusterip_hashmode hash_mode; /* which hashing mode */ 58 58 u_int32_t hash_initval; /* hash initialization */ 59 59 struct rcu_head rcu; 60 + 61 + char ifname[IFNAMSIZ]; /* device ifname */ 62 + struct notifier_block notifier; /* refresh c->ifindex in it */ 60 63 }; 61 64 62 65 #ifdef CONFIG_PROC_FS ··· 101 98 * entry(rule) is removed, remove the config from lists, but don't free it 102 99 * yet, since proc-files could still be holding references */ 103 100 static inline void 104 - clusterip_config_entry_put(struct clusterip_config *c) 101 + clusterip_config_entry_put(struct net *net, struct clusterip_config *c) 105 102 { 106 - struct net *net = dev_net(c->dev); 107 103 struct clusterip_net *cn = net_generic(net, clusterip_net_id); 108 104 109 105 local_bh_disable(); ··· 111 109 spin_unlock(&cn->lock); 112 110 local_bh_enable(); 113 111 114 - dev_mc_del(c->dev, c->clustermac); 115 - dev_put(c->dev); 112 + unregister_netdevice_notifier(&c->notifier); 116 113 117 114 /* In case anyone still accesses the file, the open/close 118 115 * functions are also incrementing the refcount on their own, ··· 171 170 set_bit(i->local_nodes[n] - 1, &c->local_nodes); 172 171 } 173 172 174 - static struct clusterip_config * 175 - clusterip_config_init(const struct ipt_clusterip_tgt_info *i, __be32 ip, 176 - struct net_device *dev) 173 + static int 174 + clusterip_netdev_event(struct notifier_block *this, unsigned long event, 175 + void *ptr) 177 176 { 178 - struct net *net = dev_net(dev); 177 + struct net_device *dev = netdev_notifier_info_to_dev(ptr); 179 178 struct clusterip_config *c; 179 + 180 + c = container_of(this, struct clusterip_config, notifier); 181 + switch (event) { 182 + case NETDEV_REGISTER: 183 + if (!strcmp(dev->name, c->ifname)) { 184 + c->ifindex = dev->ifindex; 185 + dev_mc_add(dev, c->clustermac); 186 + } 187 + break; 188 + case NETDEV_UNREGISTER: 189 + if (dev->ifindex == c->ifindex) { 190 + dev_mc_del(dev, c->clustermac); 191 + c->ifindex = -1; 192 + } 193 + break; 194 + case NETDEV_CHANGENAME: 195 + if (!strcmp(dev->name, c->ifname)) { 196 + c->ifindex = dev->ifindex; 197 + dev_mc_add(dev, c->clustermac); 198 + } else if (dev->ifindex == c->ifindex) { 199 + dev_mc_del(dev, c->clustermac); 200 + c->ifindex = -1; 201 + } 202 + break; 203 + } 204 + 205 + return NOTIFY_DONE; 206 + } 207 + 208 + static struct clusterip_config * 209 + clusterip_config_init(struct net *net, const struct ipt_clusterip_tgt_info *i, 210 + __be32 ip, const char *iniface) 211 + { 180 212 struct clusterip_net *cn = net_generic(net, clusterip_net_id); 213 + struct clusterip_config *c; 214 + int err; 181 215 182 216 c = kzalloc(sizeof(*c), GFP_ATOMIC); 183 217 if (!c) 184 218 return ERR_PTR(-ENOMEM); 185 219 186 - c->dev = dev; 220 + strcpy(c->ifname, iniface); 221 + c->ifindex = -1; 187 222 c->clusterip = ip; 188 223 memcpy(&c->clustermac, &i->clustermac, ETH_ALEN); 189 224 c->num_total_nodes = i->num_total_nodes; ··· 250 213 cn->procdir, 251 214 &clusterip_proc_fops, c); 252 215 if (!c->pde) { 253 - spin_lock_bh(&cn->lock); 254 - list_del_rcu(&c->list); 255 - spin_unlock_bh(&cn->lock); 256 - kfree(c); 257 - 258 - return ERR_PTR(-ENOMEM); 216 + err = -ENOMEM; 217 + goto err; 259 218 } 260 219 } 261 220 #endif 262 221 263 - return c; 222 + c->notifier.notifier_call = clusterip_netdev_event; 223 + err = register_netdevice_notifier(&c->notifier); 224 + if (!err) 225 + return c; 226 + 227 + #ifdef CONFIG_PROC_FS 228 + proc_remove(c->pde); 229 + err: 230 + #endif 231 + spin_lock_bh(&cn->lock); 232 + list_del_rcu(&c->list); 233 + spin_unlock_bh(&cn->lock); 234 + kfree(c); 235 + 236 + return ERR_PTR(err); 264 237 } 265 238 266 239 #ifdef CONFIG_PROC_FS ··· 472 425 e->ip.iniface); 473 426 return -ENOENT; 474 427 } 428 + dev_put(dev); 475 429 476 - config = clusterip_config_init(cipinfo, 477 - e->ip.dst.s_addr, dev); 478 - if (IS_ERR(config)) { 479 - dev_put(dev); 430 + config = clusterip_config_init(par->net, cipinfo, 431 + e->ip.dst.s_addr, 432 + e->ip.iniface); 433 + if (IS_ERR(config)) 480 434 return PTR_ERR(config); 481 - } 482 - dev_mc_add(config->dev, config->clustermac); 483 435 } 484 436 } 485 437 cipinfo->config = config; ··· 504 458 505 459 /* if no more entries are referencing the config, remove it 506 460 * from the list and destroy the proc entry */ 507 - clusterip_config_entry_put(cipinfo->config); 461 + clusterip_config_entry_put(par->net, cipinfo->config); 508 462 509 463 clusterip_config_put(cipinfo->config); 510 464 ··· 604 558 * addresses on different interfacs. However, in the CLUSTERIP case 605 559 * this wouldn't work, since we didn't subscribe the mcast group on 606 560 * other interfaces */ 607 - if (c->dev != state->out) { 608 - pr_debug("not mangling arp reply on different " 609 - "interface: cip'%s'-skb'%s'\n", 610 - c->dev->name, state->out->name); 561 + if (c->ifindex != state->out->ifindex) { 562 + pr_debug("not mangling arp reply on different interface: cip'%d'-skb'%d'\n", 563 + c->ifindex, state->out->ifindex); 611 564 clusterip_config_put(c); 612 565 return NF_ACCEPT; 613 566 } ··· 788 743 static int clusterip_net_init(struct net *net) 789 744 { 790 745 struct clusterip_net *cn = net_generic(net, clusterip_net_id); 746 + int ret; 791 747 792 748 INIT_LIST_HEAD(&cn->configs); 793 749 794 750 spin_lock_init(&cn->lock); 795 751 752 + ret = nf_register_net_hook(net, &cip_arp_ops); 753 + if (ret < 0) 754 + return ret; 755 + 796 756 #ifdef CONFIG_PROC_FS 797 757 cn->procdir = proc_mkdir("ipt_CLUSTERIP", net->proc_net); 798 758 if (!cn->procdir) { 759 + nf_unregister_net_hook(net, &cip_arp_ops); 799 760 pr_err("Unable to proc dir entry\n"); 800 761 return -ENOMEM; 801 762 } ··· 816 765 struct clusterip_net *cn = net_generic(net, clusterip_net_id); 817 766 proc_remove(cn->procdir); 818 767 #endif 768 + nf_unregister_net_hook(net, &cip_arp_ops); 819 769 } 820 770 821 771 static struct pernet_operations clusterip_net_ops = { ··· 838 786 if (ret < 0) 839 787 goto cleanup_subsys; 840 788 841 - ret = nf_register_hook(&cip_arp_ops); 842 - if (ret < 0) 843 - goto cleanup_target; 844 - 845 789 pr_info("ClusterIP Version %s loaded successfully\n", 846 790 CLUSTERIP_VERSION); 847 791 848 792 return 0; 849 793 850 - cleanup_target: 851 - xt_unregister_target(&clusterip_tg_reg); 852 794 cleanup_subsys: 853 795 unregister_pernet_subsys(&clusterip_net_ops); 854 796 return ret; ··· 852 806 { 853 807 pr_info("ClusterIP Version %s unloading\n", CLUSTERIP_VERSION); 854 808 855 - nf_unregister_hook(&cip_arp_ops); 856 809 xt_unregister_target(&clusterip_tg_reg); 857 810 unregister_pernet_subsys(&clusterip_net_ops); 858 811
+2 -2
net/ipv4/netfilter/nf_nat_masquerade_ipv4.c
··· 98 98 */ 99 99 NF_CT_ASSERT(dev->ifindex != 0); 100 100 101 - nf_ct_iterate_cleanup(net, device_cmp, 102 - (void *)(long)dev->ifindex, 0, 0); 101 + nf_ct_iterate_cleanup_net(net, device_cmp, 102 + (void *)(long)dev->ifindex, 0, 0); 103 103 } 104 104 105 105 return NOTIFY_DONE;
+5 -5
net/ipv6/netfilter/nf_nat_masquerade_ipv6.c
··· 75 75 struct net *net = dev_net(dev); 76 76 77 77 if (event == NETDEV_DOWN) 78 - nf_ct_iterate_cleanup(net, device_cmp, 79 - (void *)(long)dev->ifindex, 0, 0); 78 + nf_ct_iterate_cleanup_net(net, device_cmp, 79 + (void *)(long)dev->ifindex, 0, 0); 80 80 81 81 return NOTIFY_DONE; 82 82 } ··· 99 99 w = container_of(work, struct masq_dev_work, work); 100 100 101 101 index = w->ifindex; 102 - nf_ct_iterate_cleanup(w->net, device_cmp, (void *)index, 0, 0); 102 + nf_ct_iterate_cleanup_net(w->net, device_cmp, (void *)index, 0, 0); 103 103 104 104 put_net(w->net); 105 105 kfree(w); ··· 110 110 /* ipv6 inet notifier is an atomic notifier, i.e. we cannot 111 111 * schedule. 112 112 * 113 - * Unfortunately, nf_ct_iterate_cleanup can run for a long 113 + * Unfortunately, nf_ct_iterate_cleanup_net can run for a long 114 114 * time if there are lots of conntracks and the system 115 115 * handles high softirq load, so it frequently calls cond_resched 116 116 * while iterating the conntrack table. 117 117 * 118 - * So we defer nf_ct_iterate_cleanup walk to the system workqueue. 118 + * So we defer nf_ct_iterate_cleanup_net walk to the system workqueue. 119 119 * 120 120 * As we can have 'a lot' of inet_events (depending on amount 121 121 * of ipv6 addresses being deleted), we also need to add an upper
+3 -4
net/netfilter/Makefile
··· 70 70 obj-$(CONFIG_NF_DUP_NETDEV) += nf_dup_netdev.o 71 71 72 72 # nf_tables 73 - nf_tables-objs += nf_tables_core.o nf_tables_api.o nf_tables_trace.o 74 - nf_tables-objs += nft_immediate.o nft_cmp.o nft_range.o 75 - nf_tables-objs += nft_bitwise.o nft_byteorder.o nft_payload.o 76 - nf_tables-objs += nft_lookup.o nft_dynset.o 73 + nf_tables-objs := nf_tables_core.o nf_tables_api.o nf_tables_trace.o \ 74 + nft_immediate.o nft_cmp.o nft_range.o nft_bitwise.o \ 75 + nft_byteorder.o nft_payload.o nft_lookup.o nft_dynset.o 77 76 78 77 obj-$(CONFIG_NF_TABLES) += nf_tables.o 79 78 obj-$(CONFIG_NF_TABLES_INET) += nf_tables_inet.o
+26 -13
net/netfilter/ipset/ip_set_core.c
··· 841 841 842 842 static int ip_set_none(struct net *net, struct sock *ctnl, struct sk_buff *skb, 843 843 const struct nlmsghdr *nlh, 844 - const struct nlattr * const attr[]) 844 + const struct nlattr * const attr[], 845 + struct netlink_ext_ack *extack) 845 846 { 846 847 return -EOPNOTSUPP; 847 848 } 848 849 849 850 static int ip_set_create(struct net *net, struct sock *ctnl, 850 851 struct sk_buff *skb, const struct nlmsghdr *nlh, 851 - const struct nlattr * const attr[]) 852 + const struct nlattr * const attr[], 853 + struct netlink_ext_ack *extack) 852 854 { 853 855 struct ip_set_net *inst = ip_set_pernet(net); 854 856 struct ip_set *set, *clash = NULL; ··· 991 989 992 990 static int ip_set_destroy(struct net *net, struct sock *ctnl, 993 991 struct sk_buff *skb, const struct nlmsghdr *nlh, 994 - const struct nlattr * const attr[]) 992 + const struct nlattr * const attr[], 993 + struct netlink_ext_ack *extack) 995 994 { 996 995 struct ip_set_net *inst = ip_set_pernet(net); 997 996 struct ip_set *s; ··· 1070 1067 1071 1068 static int ip_set_flush(struct net *net, struct sock *ctnl, struct sk_buff *skb, 1072 1069 const struct nlmsghdr *nlh, 1073 - const struct nlattr * const attr[]) 1070 + const struct nlattr * const attr[], 1071 + struct netlink_ext_ack *extack) 1074 1072 { 1075 1073 struct ip_set_net *inst = ip_set_pernet(net); 1076 1074 struct ip_set *s; ··· 1110 1106 1111 1107 static int ip_set_rename(struct net *net, struct sock *ctnl, 1112 1108 struct sk_buff *skb, const struct nlmsghdr *nlh, 1113 - const struct nlattr * const attr[]) 1109 + const struct nlattr * const attr[], 1110 + struct netlink_ext_ack *extack) 1114 1111 { 1115 1112 struct ip_set_net *inst = ip_set_pernet(net); 1116 1113 struct ip_set *set, *s; ··· 1160 1155 1161 1156 static int ip_set_swap(struct net *net, struct sock *ctnl, struct sk_buff *skb, 1162 1157 const struct nlmsghdr *nlh, 1163 - const struct nlattr * const attr[]) 1158 + const struct nlattr * const attr[], 1159 + struct netlink_ext_ack *extack) 1164 1160 { 1165 1161 struct ip_set_net *inst = ip_set_pernet(net); 1166 1162 struct ip_set *from, *to; ··· 1434 1428 1435 1429 static int ip_set_dump(struct net *net, struct sock *ctnl, struct sk_buff *skb, 1436 1430 const struct nlmsghdr *nlh, 1437 - const struct nlattr * const attr[]) 1431 + const struct nlattr * const attr[], 1432 + struct netlink_ext_ack *extack) 1438 1433 { 1439 1434 if (unlikely(protocol_failed(attr))) 1440 1435 return -IPSET_ERR_PROTOCOL; ··· 1520 1513 1521 1514 static int ip_set_uadd(struct net *net, struct sock *ctnl, struct sk_buff *skb, 1522 1515 const struct nlmsghdr *nlh, 1523 - const struct nlattr * const attr[]) 1516 + const struct nlattr * const attr[], 1517 + struct netlink_ext_ack *extack) 1524 1518 { 1525 1519 struct ip_set_net *inst = ip_set_pernet(net); 1526 1520 struct ip_set *set; ··· 1575 1567 1576 1568 static int ip_set_udel(struct net *net, struct sock *ctnl, struct sk_buff *skb, 1577 1569 const struct nlmsghdr *nlh, 1578 - const struct nlattr * const attr[]) 1570 + const struct nlattr * const attr[], 1571 + struct netlink_ext_ack *extack) 1579 1572 { 1580 1573 struct ip_set_net *inst = ip_set_pernet(net); 1581 1574 struct ip_set *set; ··· 1630 1621 1631 1622 static int ip_set_utest(struct net *net, struct sock *ctnl, struct sk_buff *skb, 1632 1623 const struct nlmsghdr *nlh, 1633 - const struct nlattr * const attr[]) 1624 + const struct nlattr * const attr[], 1625 + struct netlink_ext_ack *extack) 1634 1626 { 1635 1627 struct ip_set_net *inst = ip_set_pernet(net); 1636 1628 struct ip_set *set; ··· 1666 1656 1667 1657 static int ip_set_header(struct net *net, struct sock *ctnl, 1668 1658 struct sk_buff *skb, const struct nlmsghdr *nlh, 1669 - const struct nlattr * const attr[]) 1659 + const struct nlattr * const attr[], 1660 + struct netlink_ext_ack *extack) 1670 1661 { 1671 1662 struct ip_set_net *inst = ip_set_pernet(net); 1672 1663 const struct ip_set *set; ··· 1723 1712 1724 1713 static int ip_set_type(struct net *net, struct sock *ctnl, struct sk_buff *skb, 1725 1714 const struct nlmsghdr *nlh, 1726 - const struct nlattr * const attr[]) 1715 + const struct nlattr * const attr[], 1716 + struct netlink_ext_ack *extack) 1727 1717 { 1728 1718 struct sk_buff *skb2; 1729 1719 struct nlmsghdr *nlh2; ··· 1782 1770 1783 1771 static int ip_set_protocol(struct net *net, struct sock *ctnl, 1784 1772 struct sk_buff *skb, const struct nlmsghdr *nlh, 1785 - const struct nlattr * const attr[]) 1773 + const struct nlattr * const attr[], 1774 + struct netlink_ext_ack *extack) 1786 1775 { 1787 1776 struct sk_buff *skb2; 1788 1777 struct nlmsghdr *nlh2;
+4 -8
net/netfilter/nf_conntrack_amanda.c
··· 197 197 { 198 198 int i; 199 199 200 - nf_conntrack_helper_unregister(&amanda_helper[0]); 201 - nf_conntrack_helper_unregister(&amanda_helper[1]); 200 + nf_conntrack_helpers_unregister(amanda_helper, 201 + ARRAY_SIZE(amanda_helper)); 202 202 for (i = 0; i < ARRAY_SIZE(search); i++) 203 203 textsearch_destroy(search[i].ts); 204 204 } ··· 218 218 goto err1; 219 219 } 220 220 } 221 - ret = nf_conntrack_helper_register(&amanda_helper[0]); 221 + ret = nf_conntrack_helpers_register(amanda_helper, 222 + ARRAY_SIZE(amanda_helper)); 222 223 if (ret < 0) 223 224 goto err1; 224 - ret = nf_conntrack_helper_register(&amanda_helper[1]); 225 - if (ret < 0) 226 - goto err2; 227 225 return 0; 228 226 229 - err2: 230 - nf_conntrack_helper_unregister(&amanda_helper[0]); 231 227 err1: 232 228 while (--i >= 0) 233 229 textsearch_destroy(search[i].ts);
+126 -29
net/netfilter/nf_conntrack_core.c
··· 1586 1586 1587 1587 /* Bring out ya dead! */ 1588 1588 static struct nf_conn * 1589 - get_next_corpse(struct net *net, int (*iter)(struct nf_conn *i, void *data), 1589 + get_next_corpse(int (*iter)(struct nf_conn *i, void *data), 1590 1590 void *data, unsigned int *bucket) 1591 1591 { 1592 1592 struct nf_conntrack_tuple_hash *h; 1593 1593 struct nf_conn *ct; 1594 1594 struct hlist_nulls_node *n; 1595 - int cpu; 1596 1595 spinlock_t *lockp; 1597 1596 1598 1597 for (; *bucket < nf_conntrack_htable_size; (*bucket)++) { ··· 1603 1604 if (NF_CT_DIRECTION(h) != IP_CT_DIR_ORIGINAL) 1604 1605 continue; 1605 1606 ct = nf_ct_tuplehash_to_ctrack(h); 1606 - if (net_eq(nf_ct_net(ct), net) && 1607 - iter(ct, data)) 1607 + if (iter(ct, data)) 1608 1608 goto found; 1609 1609 } 1610 1610 } ··· 1612 1614 cond_resched(); 1613 1615 } 1614 1616 1615 - for_each_possible_cpu(cpu) { 1616 - struct ct_pcpu *pcpu = per_cpu_ptr(net->ct.pcpu_lists, cpu); 1617 - 1618 - spin_lock_bh(&pcpu->lock); 1619 - hlist_nulls_for_each_entry(h, n, &pcpu->unconfirmed, hnnode) { 1620 - ct = nf_ct_tuplehash_to_ctrack(h); 1621 - if (iter(ct, data)) 1622 - set_bit(IPS_DYING_BIT, &ct->status); 1623 - } 1624 - spin_unlock_bh(&pcpu->lock); 1625 - cond_resched(); 1626 - } 1627 1617 return NULL; 1628 1618 found: 1629 1619 atomic_inc(&ct->ct_general.use); ··· 1620 1634 return ct; 1621 1635 } 1622 1636 1623 - void nf_ct_iterate_cleanup(struct net *net, 1624 - int (*iter)(struct nf_conn *i, void *data), 1625 - void *data, u32 portid, int report) 1637 + static void nf_ct_iterate_cleanup(int (*iter)(struct nf_conn *i, void *data), 1638 + void *data, u32 portid, int report) 1626 1639 { 1640 + unsigned int bucket = 0, sequence; 1627 1641 struct nf_conn *ct; 1628 - unsigned int bucket = 0; 1642 + 1643 + might_sleep(); 1644 + 1645 + for (;;) { 1646 + sequence = read_seqcount_begin(&nf_conntrack_generation); 1647 + 1648 + while ((ct = get_next_corpse(iter, data, &bucket)) != NULL) { 1649 + /* Time to push up daises... */ 1650 + 1651 + nf_ct_delete(ct, portid, report); 1652 + nf_ct_put(ct); 1653 + cond_resched(); 1654 + } 1655 + 1656 + if (!read_seqcount_retry(&nf_conntrack_generation, sequence)) 1657 + break; 1658 + bucket = 0; 1659 + } 1660 + } 1661 + 1662 + struct iter_data { 1663 + int (*iter)(struct nf_conn *i, void *data); 1664 + void *data; 1665 + struct net *net; 1666 + }; 1667 + 1668 + static int iter_net_only(struct nf_conn *i, void *data) 1669 + { 1670 + struct iter_data *d = data; 1671 + 1672 + if (!net_eq(d->net, nf_ct_net(i))) 1673 + return 0; 1674 + 1675 + return d->iter(i, d->data); 1676 + } 1677 + 1678 + static void 1679 + __nf_ct_unconfirmed_destroy(struct net *net) 1680 + { 1681 + int cpu; 1682 + 1683 + for_each_possible_cpu(cpu) { 1684 + struct nf_conntrack_tuple_hash *h; 1685 + struct hlist_nulls_node *n; 1686 + struct ct_pcpu *pcpu; 1687 + 1688 + pcpu = per_cpu_ptr(net->ct.pcpu_lists, cpu); 1689 + 1690 + spin_lock_bh(&pcpu->lock); 1691 + hlist_nulls_for_each_entry(h, n, &pcpu->unconfirmed, hnnode) { 1692 + struct nf_conn *ct; 1693 + 1694 + ct = nf_ct_tuplehash_to_ctrack(h); 1695 + 1696 + /* we cannot call iter() on unconfirmed list, the 1697 + * owning cpu can reallocate ct->ext at any time. 1698 + */ 1699 + set_bit(IPS_DYING_BIT, &ct->status); 1700 + } 1701 + spin_unlock_bh(&pcpu->lock); 1702 + cond_resched(); 1703 + } 1704 + } 1705 + 1706 + void nf_ct_iterate_cleanup_net(struct net *net, 1707 + int (*iter)(struct nf_conn *i, void *data), 1708 + void *data, u32 portid, int report) 1709 + { 1710 + struct iter_data d; 1629 1711 1630 1712 might_sleep(); 1631 1713 1632 1714 if (atomic_read(&net->ct.count) == 0) 1633 1715 return; 1634 1716 1635 - while ((ct = get_next_corpse(net, iter, data, &bucket)) != NULL) { 1636 - /* Time to push up daises... */ 1717 + __nf_ct_unconfirmed_destroy(net); 1637 1718 1638 - nf_ct_delete(ct, portid, report); 1639 - nf_ct_put(ct); 1640 - cond_resched(); 1641 - } 1719 + d.iter = iter; 1720 + d.data = data; 1721 + d.net = net; 1722 + 1723 + synchronize_net(); 1724 + 1725 + nf_ct_iterate_cleanup(iter_net_only, &d, portid, report); 1642 1726 } 1643 - EXPORT_SYMBOL_GPL(nf_ct_iterate_cleanup); 1727 + EXPORT_SYMBOL_GPL(nf_ct_iterate_cleanup_net); 1728 + 1729 + /** 1730 + * nf_ct_iterate_destroy - destroy unconfirmed conntracks and iterate table 1731 + * @iter: callback to invoke for each conntrack 1732 + * @data: data to pass to @iter 1733 + * 1734 + * Like nf_ct_iterate_cleanup, but first marks conntracks on the 1735 + * unconfirmed list as dying (so they will not be inserted into 1736 + * main table). 1737 + * 1738 + * Can only be called in module exit path. 1739 + */ 1740 + void 1741 + nf_ct_iterate_destroy(int (*iter)(struct nf_conn *i, void *data), void *data) 1742 + { 1743 + struct net *net; 1744 + 1745 + rtnl_lock(); 1746 + for_each_net(net) { 1747 + if (atomic_read(&net->ct.count) == 0) 1748 + continue; 1749 + __nf_ct_unconfirmed_destroy(net); 1750 + } 1751 + rtnl_unlock(); 1752 + 1753 + /* Need to wait for netns cleanup worker to finish, if its 1754 + * running -- it might have deleted a net namespace from 1755 + * the global list, so our __nf_ct_unconfirmed_destroy() might 1756 + * not have affected all namespaces. 1757 + */ 1758 + net_ns_barrier(); 1759 + 1760 + /* a conntrack could have been unlinked from unconfirmed list 1761 + * before we grabbed pcpu lock in __nf_ct_unconfirmed_destroy(). 1762 + * This makes sure its inserted into conntrack table. 1763 + */ 1764 + synchronize_net(); 1765 + 1766 + nf_ct_iterate_cleanup(iter, data, 0, 0); 1767 + } 1768 + EXPORT_SYMBOL_GPL(nf_ct_iterate_destroy); 1644 1769 1645 1770 static int kill_all(struct nf_conn *i, void *data) 1646 1771 { 1647 - return 1; 1772 + return net_eq(nf_ct_net(i), data); 1648 1773 } 1649 1774 1650 1775 void nf_ct_free_hashtable(void *hash, unsigned int size) ··· 1820 1723 i_see_dead_people: 1821 1724 busy = 0; 1822 1725 list_for_each_entry(net, net_exit_list, exit_list) { 1823 - nf_ct_iterate_cleanup(net, kill_all, NULL, 0, 0); 1726 + nf_ct_iterate_cleanup(kill_all, net, 0, 0); 1824 1727 if (atomic_read(&net->ct.count) != 0) 1825 1728 busy = 1; 1826 1729 }
+36 -27
net/netfilter/nf_conntrack_h323_main.c
··· 1815 1815 }, 1816 1816 }; 1817 1817 1818 + static int __init h323_helper_init(void) 1819 + { 1820 + int ret; 1821 + 1822 + ret = nf_conntrack_helper_register(&nf_conntrack_helper_h245); 1823 + if (ret < 0) 1824 + return ret; 1825 + ret = nf_conntrack_helpers_register(nf_conntrack_helper_q931, 1826 + ARRAY_SIZE(nf_conntrack_helper_q931)); 1827 + if (ret < 0) 1828 + goto err1; 1829 + ret = nf_conntrack_helpers_register(nf_conntrack_helper_ras, 1830 + ARRAY_SIZE(nf_conntrack_helper_ras)); 1831 + if (ret < 0) 1832 + goto err2; 1833 + 1834 + return 0; 1835 + err2: 1836 + nf_conntrack_helpers_unregister(nf_conntrack_helper_q931, 1837 + ARRAY_SIZE(nf_conntrack_helper_q931)); 1838 + err1: 1839 + nf_conntrack_helper_unregister(&nf_conntrack_helper_h245); 1840 + return ret; 1841 + } 1842 + 1843 + static void __exit h323_helper_exit(void) 1844 + { 1845 + nf_conntrack_helpers_unregister(nf_conntrack_helper_ras, 1846 + ARRAY_SIZE(nf_conntrack_helper_ras)); 1847 + nf_conntrack_helpers_unregister(nf_conntrack_helper_q931, 1848 + ARRAY_SIZE(nf_conntrack_helper_q931)); 1849 + nf_conntrack_helper_unregister(&nf_conntrack_helper_h245); 1850 + } 1851 + 1818 1852 /****************************************************************************/ 1819 1853 static void __exit nf_conntrack_h323_fini(void) 1820 1854 { 1821 - nf_conntrack_helper_unregister(&nf_conntrack_helper_ras[1]); 1822 - nf_conntrack_helper_unregister(&nf_conntrack_helper_ras[0]); 1823 - nf_conntrack_helper_unregister(&nf_conntrack_helper_q931[1]); 1824 - nf_conntrack_helper_unregister(&nf_conntrack_helper_q931[0]); 1825 - nf_conntrack_helper_unregister(&nf_conntrack_helper_h245); 1855 + h323_helper_exit(); 1826 1856 kfree(h323_buffer); 1827 1857 pr_debug("nf_ct_h323: fini\n"); 1828 1858 } ··· 1867 1837 h323_buffer = kmalloc(65536, GFP_KERNEL); 1868 1838 if (!h323_buffer) 1869 1839 return -ENOMEM; 1870 - ret = nf_conntrack_helper_register(&nf_conntrack_helper_h245); 1840 + ret = h323_helper_init(); 1871 1841 if (ret < 0) 1872 1842 goto err1; 1873 - ret = nf_conntrack_helper_register(&nf_conntrack_helper_q931[0]); 1874 - if (ret < 0) 1875 - goto err2; 1876 - ret = nf_conntrack_helper_register(&nf_conntrack_helper_q931[1]); 1877 - if (ret < 0) 1878 - goto err3; 1879 - ret = nf_conntrack_helper_register(&nf_conntrack_helper_ras[0]); 1880 - if (ret < 0) 1881 - goto err4; 1882 - ret = nf_conntrack_helper_register(&nf_conntrack_helper_ras[1]); 1883 - if (ret < 0) 1884 - goto err5; 1885 1843 pr_debug("nf_ct_h323: init success\n"); 1886 1844 return 0; 1887 - 1888 - err5: 1889 - nf_conntrack_helper_unregister(&nf_conntrack_helper_ras[0]); 1890 - err4: 1891 - nf_conntrack_helper_unregister(&nf_conntrack_helper_q931[1]); 1892 - err3: 1893 - nf_conntrack_helper_unregister(&nf_conntrack_helper_q931[0]); 1894 - err2: 1895 - nf_conntrack_helper_unregister(&nf_conntrack_helper_h245); 1896 1845 err1: 1897 1846 kfree(h323_buffer); 1898 1847 return ret;
+4 -46
net/netfilter/nf_conntrack_helper.c
··· 285 285 EXPORT_SYMBOL_GPL(__nf_ct_try_assign_helper); 286 286 287 287 /* appropriate ct lock protecting must be taken by caller */ 288 - static inline int unhelp(struct nf_conntrack_tuple_hash *i, 289 - const struct nf_conntrack_helper *me) 288 + static int unhelp(struct nf_conn *ct, void *me) 290 289 { 291 - struct nf_conn *ct = nf_ct_tuplehash_to_ctrack(i); 292 290 struct nf_conn_help *help = nfct_help(ct); 293 291 294 292 if (help && rcu_dereference_raw(help->helper) == me) { 295 293 nf_conntrack_event(IPCT_HELPER, ct); 296 294 RCU_INIT_POINTER(help->helper, NULL); 297 295 } 296 + 297 + /* We are not intended to delete this conntrack. */ 298 298 return 0; 299 299 } 300 300 ··· 437 437 } 438 438 EXPORT_SYMBOL_GPL(nf_conntrack_helper_register); 439 439 440 - static void __nf_conntrack_helper_unregister(struct nf_conntrack_helper *me, 441 - struct net *net) 442 - { 443 - struct nf_conntrack_tuple_hash *h; 444 - const struct hlist_nulls_node *nn; 445 - int cpu; 446 - 447 - /* Get rid of expecteds, set helpers to NULL. */ 448 - for_each_possible_cpu(cpu) { 449 - struct ct_pcpu *pcpu = per_cpu_ptr(net->ct.pcpu_lists, cpu); 450 - 451 - spin_lock_bh(&pcpu->lock); 452 - hlist_nulls_for_each_entry(h, nn, &pcpu->unconfirmed, hnnode) 453 - unhelp(h, me); 454 - spin_unlock_bh(&pcpu->lock); 455 - } 456 - } 457 - 458 440 void nf_conntrack_helper_unregister(struct nf_conntrack_helper *me) 459 441 { 460 - struct nf_conntrack_tuple_hash *h; 461 442 struct nf_conntrack_expect *exp; 462 443 const struct hlist_node *next; 463 - const struct hlist_nulls_node *nn; 464 - unsigned int last_hsize; 465 - spinlock_t *lock; 466 - struct net *net; 467 444 unsigned int i; 468 445 469 446 mutex_lock(&nf_ct_helper_mutex); ··· 468 491 } 469 492 spin_unlock_bh(&nf_conntrack_expect_lock); 470 493 471 - rtnl_lock(); 472 - for_each_net(net) 473 - __nf_conntrack_helper_unregister(me, net); 474 - rtnl_unlock(); 475 - 476 - local_bh_disable(); 477 - restart: 478 - last_hsize = nf_conntrack_htable_size; 479 - for (i = 0; i < last_hsize; i++) { 480 - lock = &nf_conntrack_locks[i % CONNTRACK_LOCKS]; 481 - nf_conntrack_lock(lock); 482 - if (last_hsize != nf_conntrack_htable_size) { 483 - spin_unlock(lock); 484 - goto restart; 485 - } 486 - hlist_nulls_for_each_entry(h, nn, &nf_conntrack_hash[i], hnnode) 487 - unhelp(h, me); 488 - spin_unlock(lock); 489 - } 490 - local_bh_enable(); 494 + nf_ct_iterate_destroy(unhelp, me); 491 495 } 492 496 EXPORT_SYMBOL_GPL(nf_conntrack_helper_unregister); 493 497
+30 -17
net/netfilter/nf_conntrack_netlink.c
··· 636 636 if (events & (1 << IPCT_DESTROY)) { 637 637 type = IPCTNL_MSG_CT_DELETE; 638 638 group = NFNLGRP_CONNTRACK_DESTROY; 639 - } else if (events & ((1 << IPCT_NEW) | (1 << IPCT_RELATED))) { 639 + } else if (events & ((1 << IPCT_NEW) | (1 << IPCT_RELATED))) { 640 640 type = IPCTNL_MSG_CT_NEW; 641 641 flags = NLM_F_CREATE|NLM_F_EXCL; 642 642 group = NFNLGRP_CONNTRACK_NEW; 643 - } else if (events) { 643 + } else if (events) { 644 644 type = IPCTNL_MSG_CT_NEW; 645 645 group = NFNLGRP_CONNTRACK_UPDATE; 646 646 } else ··· 1122 1122 return PTR_ERR(filter); 1123 1123 } 1124 1124 1125 - nf_ct_iterate_cleanup(net, ctnetlink_filter_match, filter, 1126 - portid, report); 1125 + nf_ct_iterate_cleanup_net(net, ctnetlink_filter_match, filter, 1126 + portid, report); 1127 1127 kfree(filter); 1128 1128 1129 1129 return 0; ··· 1132 1132 static int ctnetlink_del_conntrack(struct net *net, struct sock *ctnl, 1133 1133 struct sk_buff *skb, 1134 1134 const struct nlmsghdr *nlh, 1135 - const struct nlattr * const cda[]) 1135 + const struct nlattr * const cda[], 1136 + struct netlink_ext_ack *extack) 1136 1137 { 1137 1138 struct nf_conntrack_tuple_hash *h; 1138 1139 struct nf_conntrack_tuple tuple; ··· 1185 1184 static int ctnetlink_get_conntrack(struct net *net, struct sock *ctnl, 1186 1185 struct sk_buff *skb, 1187 1186 const struct nlmsghdr *nlh, 1188 - const struct nlattr * const cda[]) 1187 + const struct nlattr * const cda[], 1188 + struct netlink_ext_ack *extack) 1189 1189 { 1190 1190 struct nf_conntrack_tuple_hash *h; 1191 1191 struct nf_conntrack_tuple tuple; ··· 1347 1345 static int ctnetlink_get_ct_dying(struct net *net, struct sock *ctnl, 1348 1346 struct sk_buff *skb, 1349 1347 const struct nlmsghdr *nlh, 1350 - const struct nlattr * const cda[]) 1348 + const struct nlattr * const cda[], 1349 + struct netlink_ext_ack *extack) 1351 1350 { 1352 1351 if (nlh->nlmsg_flags & NLM_F_DUMP) { 1353 1352 struct netlink_dump_control c = { ··· 1370 1367 static int ctnetlink_get_ct_unconfirmed(struct net *net, struct sock *ctnl, 1371 1368 struct sk_buff *skb, 1372 1369 const struct nlmsghdr *nlh, 1373 - const struct nlattr * const cda[]) 1370 + const struct nlattr * const cda[], 1371 + struct netlink_ext_ack *extack) 1374 1372 { 1375 1373 if (nlh->nlmsg_flags & NLM_F_DUMP) { 1376 1374 struct netlink_dump_control c = { ··· 1910 1906 static int ctnetlink_new_conntrack(struct net *net, struct sock *ctnl, 1911 1907 struct sk_buff *skb, 1912 1908 const struct nlmsghdr *nlh, 1913 - const struct nlattr * const cda[]) 1909 + const struct nlattr * const cda[], 1910 + struct netlink_ext_ack *extack) 1914 1911 { 1915 1912 struct nf_conntrack_tuple otuple, rtuple; 1916 1913 struct nf_conntrack_tuple_hash *h = NULL; ··· 2076 2071 static int ctnetlink_stat_ct_cpu(struct net *net, struct sock *ctnl, 2077 2072 struct sk_buff *skb, 2078 2073 const struct nlmsghdr *nlh, 2079 - const struct nlattr * const cda[]) 2074 + const struct nlattr * const cda[], 2075 + struct netlink_ext_ack *extack) 2080 2076 { 2081 2077 if (nlh->nlmsg_flags & NLM_F_DUMP) { 2082 2078 struct netlink_dump_control c = { ··· 2122 2116 2123 2117 static int ctnetlink_stat_ct(struct net *net, struct sock *ctnl, 2124 2118 struct sk_buff *skb, const struct nlmsghdr *nlh, 2125 - const struct nlattr * const cda[]) 2119 + const struct nlattr * const cda[], 2120 + struct netlink_ext_ack *extack) 2126 2121 { 2127 2122 struct sk_buff *skb2; 2128 2123 int err; ··· 2785 2778 static int ctnetlink_dump_exp_ct(struct net *net, struct sock *ctnl, 2786 2779 struct sk_buff *skb, 2787 2780 const struct nlmsghdr *nlh, 2788 - const struct nlattr * const cda[]) 2781 + const struct nlattr * const cda[], 2782 + struct netlink_ext_ack *extack) 2789 2783 { 2790 2784 int err; 2791 2785 struct nfgenmsg *nfmsg = nlmsg_data(nlh); ··· 2830 2822 2831 2823 static int ctnetlink_get_expect(struct net *net, struct sock *ctnl, 2832 2824 struct sk_buff *skb, const struct nlmsghdr *nlh, 2833 - const struct nlattr * const cda[]) 2825 + const struct nlattr * const cda[], 2826 + struct netlink_ext_ack *extack) 2834 2827 { 2835 2828 struct nf_conntrack_tuple tuple; 2836 2829 struct nf_conntrack_expect *exp; ··· 2843 2834 2844 2835 if (nlh->nlmsg_flags & NLM_F_DUMP) { 2845 2836 if (cda[CTA_EXPECT_MASTER]) 2846 - return ctnetlink_dump_exp_ct(net, ctnl, skb, nlh, cda); 2837 + return ctnetlink_dump_exp_ct(net, ctnl, skb, nlh, cda, 2838 + extack); 2847 2839 else { 2848 2840 struct netlink_dump_control c = { 2849 2841 .dump = ctnetlink_exp_dump_table, ··· 2912 2902 2913 2903 static int ctnetlink_del_expect(struct net *net, struct sock *ctnl, 2914 2904 struct sk_buff *skb, const struct nlmsghdr *nlh, 2915 - const struct nlattr * const cda[]) 2905 + const struct nlattr * const cda[], 2906 + struct netlink_ext_ack *extack) 2916 2907 { 2917 2908 struct nf_conntrack_expect *exp; 2918 2909 struct nf_conntrack_tuple tuple; ··· 3201 3190 3202 3191 static int ctnetlink_new_expect(struct net *net, struct sock *ctnl, 3203 3192 struct sk_buff *skb, const struct nlmsghdr *nlh, 3204 - const struct nlattr * const cda[]) 3193 + const struct nlattr * const cda[], 3194 + struct netlink_ext_ack *extack) 3205 3195 { 3206 3196 struct nf_conntrack_tuple tuple; 3207 3197 struct nf_conntrack_expect *exp; ··· 3308 3296 static int ctnetlink_stat_exp_cpu(struct net *net, struct sock *ctnl, 3309 3297 struct sk_buff *skb, 3310 3298 const struct nlmsghdr *nlh, 3311 - const struct nlattr * const cda[]) 3299 + const struct nlattr * const cda[], 3300 + struct netlink_ext_ack *extack) 3312 3301 { 3313 3302 if (nlh->nlmsg_flags & NLM_F_DUMP) { 3314 3303 struct netlink_dump_control c = {
+27 -19
net/netfilter/nf_conntrack_proto.c
··· 28 28 #include <net/netfilter/nf_conntrack_l4proto.h> 29 29 #include <net/netfilter/nf_conntrack_core.h> 30 30 31 - static struct nf_conntrack_l4proto __rcu **nf_ct_protos[PF_MAX] __read_mostly; 32 - struct nf_conntrack_l3proto __rcu *nf_ct_l3protos[AF_MAX] __read_mostly; 31 + static struct nf_conntrack_l4proto __rcu **nf_ct_protos[NFPROTO_NUMPROTO] __read_mostly; 32 + struct nf_conntrack_l3proto __rcu *nf_ct_l3protos[NFPROTO_NUMPROTO] __read_mostly; 33 33 EXPORT_SYMBOL_GPL(nf_ct_l3protos); 34 34 35 35 static DEFINE_MUTEX(nf_ct_proto_mutex); ··· 68 68 struct nf_conntrack_l4proto * 69 69 __nf_ct_l4proto_find(u_int16_t l3proto, u_int8_t l4proto) 70 70 { 71 - if (unlikely(l3proto >= AF_MAX || nf_ct_protos[l3proto] == NULL)) 71 + if (unlikely(l3proto >= NFPROTO_NUMPROTO || nf_ct_protos[l3proto] == NULL)) 72 72 return &nf_conntrack_l4proto_generic; 73 73 74 74 return rcu_dereference(nf_ct_protos[l3proto][l4proto]); ··· 212 212 int ret = 0; 213 213 struct nf_conntrack_l3proto *old; 214 214 215 - if (proto->l3proto >= AF_MAX) 215 + if (proto->l3proto >= NFPROTO_NUMPROTO) 216 216 return -EBUSY; 217 217 218 218 if (proto->tuple_to_nlattr && !proto->nlattr_tuple_size) ··· 254 254 255 255 void nf_ct_l3proto_unregister(struct nf_conntrack_l3proto *proto) 256 256 { 257 - BUG_ON(proto->l3proto >= AF_MAX); 257 + BUG_ON(proto->l3proto >= NFPROTO_NUMPROTO); 258 258 259 259 mutex_lock(&nf_ct_proto_mutex); 260 260 BUG_ON(rcu_dereference_protected(nf_ct_l3protos[proto->l3proto], ··· 265 265 mutex_unlock(&nf_ct_proto_mutex); 266 266 267 267 synchronize_rcu(); 268 + /* Remove all contrack entries for this protocol */ 269 + nf_ct_iterate_destroy(kill_l3proto, proto); 268 270 } 269 271 EXPORT_SYMBOL_GPL(nf_ct_l3proto_unregister); 270 272 ··· 282 280 */ 283 281 if (proto->net_ns_put) 284 282 proto->net_ns_put(net); 285 - 286 - /* Remove all contrack entries for this protocol */ 287 - nf_ct_iterate_cleanup(net, kill_l3proto, proto, 0, 0); 288 283 } 289 284 EXPORT_SYMBOL_GPL(nf_ct_l3proto_pernet_unregister); 290 285 ··· 341 342 { 342 343 int ret = 0; 343 344 344 - if (l4proto->l3proto >= PF_MAX) 345 + if (l4proto->l3proto >= ARRAY_SIZE(nf_ct_protos)) 345 346 return -EBUSY; 346 347 347 348 if ((l4proto->to_nlattr && !l4proto->nlattr_size) || ··· 420 421 } 421 422 EXPORT_SYMBOL_GPL(nf_ct_l4proto_pernet_register_one); 422 423 423 - void nf_ct_l4proto_unregister_one(struct nf_conntrack_l4proto *l4proto) 424 - { 425 - BUG_ON(l4proto->l3proto >= PF_MAX); 424 + static void __nf_ct_l4proto_unregister_one(struct nf_conntrack_l4proto *l4proto) 426 425 427 - mutex_lock(&nf_ct_proto_mutex); 426 + { 427 + BUG_ON(l4proto->l3proto >= ARRAY_SIZE(nf_ct_protos)); 428 + 428 429 BUG_ON(rcu_dereference_protected( 429 430 nf_ct_protos[l4proto->l3proto][l4proto->l4proto], 430 431 lockdep_is_held(&nf_ct_proto_mutex) 431 432 ) != l4proto); 432 433 rcu_assign_pointer(nf_ct_protos[l4proto->l3proto][l4proto->l4proto], 433 434 &nf_conntrack_l4proto_generic); 435 + } 436 + 437 + void nf_ct_l4proto_unregister_one(struct nf_conntrack_l4proto *l4proto) 438 + { 439 + mutex_lock(&nf_ct_proto_mutex); 440 + __nf_ct_l4proto_unregister_one(l4proto); 434 441 mutex_unlock(&nf_ct_proto_mutex); 435 442 436 443 synchronize_rcu(); ··· 453 448 454 449 pn->users--; 455 450 nf_ct_l4proto_unregister_sysctl(net, pn, l4proto); 456 - 457 - /* Remove all contrack entries for this protocol */ 458 - nf_ct_iterate_cleanup(net, kill_l4proto, l4proto, 0, 0); 459 451 } 460 452 EXPORT_SYMBOL_GPL(nf_ct_l4proto_pernet_unregister_one); 461 453 ··· 502 500 void nf_ct_l4proto_unregister(struct nf_conntrack_l4proto *l4proto[], 503 501 unsigned int num_proto) 504 502 { 503 + mutex_lock(&nf_ct_proto_mutex); 505 504 while (num_proto-- != 0) 506 - nf_ct_l4proto_unregister_one(l4proto[num_proto]); 505 + __nf_ct_l4proto_unregister_one(l4proto[num_proto]); 506 + mutex_unlock(&nf_ct_proto_mutex); 507 + 508 + synchronize_net(); 509 + /* Remove all contrack entries for this protocol */ 510 + nf_ct_iterate_destroy(kill_l4proto, l4proto); 507 511 } 508 512 EXPORT_SYMBOL_GPL(nf_ct_l4proto_unregister); 509 513 ··· 556 548 int nf_conntrack_proto_init(void) 557 549 { 558 550 unsigned int i; 559 - for (i = 0; i < AF_MAX; i++) 551 + for (i = 0; i < NFPROTO_NUMPROTO; i++) 560 552 rcu_assign_pointer(nf_ct_l3protos[i], 561 553 &nf_conntrack_l3proto_generic); 562 554 return 0; ··· 566 558 { 567 559 unsigned int i; 568 560 /* free l3proto protocol tables */ 569 - for (i = 0; i < PF_MAX; i++) 561 + for (i = 0; i < ARRAY_SIZE(nf_ct_protos); i++) 570 562 kfree(nf_ct_protos[i]); 571 563 }
+1
net/netfilter/nf_dup_netdev.c
··· 13 13 #include <linux/netfilter.h> 14 14 #include <linux/netfilter/nf_tables.h> 15 15 #include <net/netfilter/nf_tables.h> 16 + #include <net/netfilter/nf_dup_netdev.h> 16 17 17 18 static void nf_do_netdev_egress(struct sk_buff *skb, struct net_device *dev) 18 19 {
+5 -32
net/netfilter/nf_nat_core.c
··· 582 582 .l3proto = l3proto, 583 583 .l4proto = l4proto, 584 584 }; 585 - struct net *net; 586 585 587 - rtnl_lock(); 588 - for_each_net(net) 589 - nf_ct_iterate_cleanup(net, nf_nat_proto_remove, &clean, 0, 0); 590 - rtnl_unlock(); 586 + nf_ct_iterate_destroy(nf_nat_proto_remove, &clean); 591 587 } 592 588 593 589 static void nf_nat_l3proto_clean(u8 l3proto) ··· 591 595 struct nf_nat_proto_clean clean = { 592 596 .l3proto = l3proto, 593 597 }; 594 - struct net *net; 595 598 596 - rtnl_lock(); 597 - 598 - for_each_net(net) 599 - nf_ct_iterate_cleanup(net, nf_nat_proto_remove, &clean, 0, 0); 600 - rtnl_unlock(); 599 + nf_ct_iterate_destroy(nf_nat_proto_remove, &clean); 601 600 } 602 601 603 602 /* Protocol registration. */ ··· 813 822 } 814 823 #endif 815 824 816 - static void __net_exit nf_nat_net_exit(struct net *net) 817 - { 818 - struct nf_nat_proto_clean clean = {}; 819 - 820 - nf_ct_iterate_cleanup(net, nf_nat_proto_clean, &clean, 0, 0); 821 - } 822 - 823 - static struct pernet_operations nf_nat_net_ops = { 824 - .exit = nf_nat_net_exit, 825 - }; 826 - 827 825 static struct nf_ct_helper_expectfn follow_master_nat = { 828 826 .name = "nat-follow-master", 829 827 .expectfn = nf_nat_follow_master, ··· 833 853 return ret; 834 854 } 835 855 836 - ret = register_pernet_subsys(&nf_nat_net_ops); 837 - if (ret < 0) 838 - goto cleanup_extend; 839 - 840 856 nf_ct_helper_expectfn_register(&follow_master_nat); 841 857 842 858 BUG_ON(nfnetlink_parse_nat_setup_hook != NULL); ··· 843 867 RCU_INIT_POINTER(nf_nat_decode_session_hook, __nf_nat_decode_session); 844 868 #endif 845 869 return 0; 846 - 847 - cleanup_extend: 848 - rhltable_destroy(&nf_nat_bysource_table); 849 - nf_ct_extend_unregister(&nat_extend); 850 - return ret; 851 870 } 852 871 853 872 static void __exit nf_nat_cleanup(void) 854 873 { 874 + struct nf_nat_proto_clean clean = {}; 855 875 unsigned int i; 856 876 857 - unregister_pernet_subsys(&nf_nat_net_ops); 877 + nf_ct_iterate_destroy(nf_nat_proto_clean, &clean); 878 + 858 879 nf_ct_extend_unregister(&nat_extend); 859 880 nf_ct_helper_expectfn_unregister(&follow_master_nat); 860 881 RCU_INIT_POINTER(nfnetlink_parse_nat_setup_hook, NULL);
+87 -50
net/netfilter/nf_tables_api.c
··· 13 13 #include <linux/list.h> 14 14 #include <linux/skbuff.h> 15 15 #include <linux/netlink.h> 16 + #include <linux/vmalloc.h> 16 17 #include <linux/netfilter.h> 17 18 #include <linux/netfilter/nfnetlink.h> 18 19 #include <linux/netfilter/nf_tables.h> ··· 387 386 return ++table->hgenerator; 388 387 } 389 388 390 - static const struct nf_chain_type *chain_type[AF_MAX][NFT_CHAIN_T_MAX]; 389 + static const struct nf_chain_type *chain_type[NFPROTO_NUMPROTO][NFT_CHAIN_T_MAX]; 391 390 392 391 static const struct nf_chain_type * 393 392 __nf_tables_chain_type_lookup(int family, const struct nlattr *nla) ··· 535 534 536 535 static int nf_tables_gettable(struct net *net, struct sock *nlsk, 537 536 struct sk_buff *skb, const struct nlmsghdr *nlh, 538 - const struct nlattr * const nla[]) 537 + const struct nlattr * const nla[], 538 + struct netlink_ext_ack *extack) 539 539 { 540 540 const struct nfgenmsg *nfmsg = nlmsg_data(nlh); 541 541 u8 genmask = nft_genmask_cur(net); ··· 679 677 680 678 static int nf_tables_newtable(struct net *net, struct sock *nlsk, 681 679 struct sk_buff *skb, const struct nlmsghdr *nlh, 682 - const struct nlattr * const nla[]) 680 + const struct nlattr * const nla[], 681 + struct netlink_ext_ack *extack) 683 682 { 684 683 const struct nfgenmsg *nfmsg = nlmsg_data(nlh); 685 684 u8 genmask = nft_genmask_next(net); ··· 833 830 834 831 static int nf_tables_deltable(struct net *net, struct sock *nlsk, 835 832 struct sk_buff *skb, const struct nlmsghdr *nlh, 836 - const struct nlattr * const nla[]) 833 + const struct nlattr * const nla[], 834 + struct netlink_ext_ack *extack) 837 835 { 838 836 const struct nfgenmsg *nfmsg = nlmsg_data(nlh); 839 837 u8 genmask = nft_genmask_next(net); ··· 872 868 int nft_register_chain_type(const struct nf_chain_type *ctype) 873 869 { 874 870 int err = 0; 871 + 872 + if (WARN_ON(ctype->family >= NFPROTO_NUMPROTO)) 873 + return -EINVAL; 875 874 876 875 nfnl_lock(NFNL_SUBSYS_NFTABLES); 877 876 if (chain_type[ctype->family][ctype->type] != NULL) { ··· 1130 1123 1131 1124 static int nf_tables_getchain(struct net *net, struct sock *nlsk, 1132 1125 struct sk_buff *skb, const struct nlmsghdr *nlh, 1133 - const struct nlattr * const nla[]) 1126 + const struct nlattr * const nla[], 1127 + struct netlink_ext_ack *extack) 1134 1128 { 1135 1129 const struct nfgenmsg *nfmsg = nlmsg_data(nlh); 1136 1130 u8 genmask = nft_genmask_cur(net); ··· 1327 1319 1328 1320 static int nf_tables_newchain(struct net *net, struct sock *nlsk, 1329 1321 struct sk_buff *skb, const struct nlmsghdr *nlh, 1330 - const struct nlattr * const nla[]) 1322 + const struct nlattr * const nla[], 1323 + struct netlink_ext_ack *extack) 1331 1324 { 1332 1325 const struct nfgenmsg *nfmsg = nlmsg_data(nlh); 1333 1326 const struct nlattr * uninitialized_var(name); ··· 1566 1557 1567 1558 static int nf_tables_delchain(struct net *net, struct sock *nlsk, 1568 1559 struct sk_buff *skb, const struct nlmsghdr *nlh, 1569 - const struct nlattr * const nla[]) 1560 + const struct nlattr * const nla[], 1561 + struct netlink_ext_ack *extack) 1570 1562 { 1571 1563 const struct nfgenmsg *nfmsg = nlmsg_data(nlh); 1572 1564 u8 genmask = nft_genmask_next(net); ··· 2048 2038 2049 2039 static int nf_tables_getrule(struct net *net, struct sock *nlsk, 2050 2040 struct sk_buff *skb, const struct nlmsghdr *nlh, 2051 - const struct nlattr * const nla[]) 2041 + const struct nlattr * const nla[], 2042 + struct netlink_ext_ack *extack) 2052 2043 { 2053 2044 const struct nfgenmsg *nfmsg = nlmsg_data(nlh); 2054 2045 u8 genmask = nft_genmask_cur(net); ··· 2142 2131 2143 2132 static int nf_tables_newrule(struct net *net, struct sock *nlsk, 2144 2133 struct sk_buff *skb, const struct nlmsghdr *nlh, 2145 - const struct nlattr * const nla[]) 2134 + const struct nlattr * const nla[], 2135 + struct netlink_ext_ack *extack) 2146 2136 { 2147 2137 const struct nfgenmsg *nfmsg = nlmsg_data(nlh); 2148 2138 u8 genmask = nft_genmask_next(net); ··· 2325 2313 2326 2314 static int nf_tables_delrule(struct net *net, struct sock *nlsk, 2327 2315 struct sk_buff *skb, const struct nlmsghdr *nlh, 2328 - const struct nlattr * const nla[]) 2316 + const struct nlattr * const nla[], 2317 + struct netlink_ext_ack *extack) 2329 2318 { 2330 2319 const struct nfgenmsg *nfmsg = nlmsg_data(nlh); 2331 2320 u8 genmask = nft_genmask_next(net); ··· 2390 2377 * Sets 2391 2378 */ 2392 2379 2393 - static LIST_HEAD(nf_tables_set_ops); 2380 + static LIST_HEAD(nf_tables_set_types); 2394 2381 2395 - int nft_register_set(struct nft_set_ops *ops) 2382 + int nft_register_set(struct nft_set_type *type) 2396 2383 { 2397 2384 nfnl_lock(NFNL_SUBSYS_NFTABLES); 2398 - list_add_tail_rcu(&ops->list, &nf_tables_set_ops); 2385 + list_add_tail_rcu(&type->list, &nf_tables_set_types); 2399 2386 nfnl_unlock(NFNL_SUBSYS_NFTABLES); 2400 2387 return 0; 2401 2388 } 2402 2389 EXPORT_SYMBOL_GPL(nft_register_set); 2403 2390 2404 - void nft_unregister_set(struct nft_set_ops *ops) 2391 + void nft_unregister_set(struct nft_set_type *type) 2405 2392 { 2406 2393 nfnl_lock(NFNL_SUBSYS_NFTABLES); 2407 - list_del_rcu(&ops->list); 2394 + list_del_rcu(&type->list); 2408 2395 nfnl_unlock(NFNL_SUBSYS_NFTABLES); 2409 2396 } 2410 2397 EXPORT_SYMBOL_GPL(nft_unregister_set); 2398 + 2399 + #define NFT_SET_FEATURES (NFT_SET_INTERVAL | NFT_SET_MAP | \ 2400 + NFT_SET_TIMEOUT | NFT_SET_OBJECT) 2401 + 2402 + static bool nft_set_ops_candidate(const struct nft_set_ops *ops, u32 flags) 2403 + { 2404 + return (flags & ops->features) == (flags & NFT_SET_FEATURES); 2405 + } 2411 2406 2412 2407 /* 2413 2408 * Select a set implementation based on the data characteristics and the ··· 2423 2402 * given, in that case the amount of memory per element is used. 2424 2403 */ 2425 2404 static const struct nft_set_ops * 2426 - nft_select_set_ops(const struct nlattr * const nla[], 2405 + nft_select_set_ops(const struct nft_ctx *ctx, 2406 + const struct nlattr * const nla[], 2427 2407 const struct nft_set_desc *desc, 2428 2408 enum nft_set_policies policy) 2429 2409 { 2430 2410 const struct nft_set_ops *ops, *bops; 2431 2411 struct nft_set_estimate est, best; 2432 - u32 features; 2412 + const struct nft_set_type *type; 2413 + u32 flags = 0; 2433 2414 2434 2415 #ifdef CONFIG_MODULES 2435 - if (list_empty(&nf_tables_set_ops)) { 2416 + if (list_empty(&nf_tables_set_types)) { 2436 2417 nfnl_unlock(NFNL_SUBSYS_NFTABLES); 2437 2418 request_module("nft-set"); 2438 2419 nfnl_lock(NFNL_SUBSYS_NFTABLES); 2439 - if (!list_empty(&nf_tables_set_ops)) 2420 + if (!list_empty(&nf_tables_set_types)) 2440 2421 return ERR_PTR(-EAGAIN); 2441 2422 } 2442 2423 #endif 2443 - features = 0; 2444 - if (nla[NFTA_SET_FLAGS] != NULL) { 2445 - features = ntohl(nla_get_be32(nla[NFTA_SET_FLAGS])); 2446 - features &= NFT_SET_INTERVAL | NFT_SET_MAP | NFT_SET_TIMEOUT | 2447 - NFT_SET_OBJECT; 2448 - } 2424 + if (nla[NFTA_SET_FLAGS] != NULL) 2425 + flags = ntohl(nla_get_be32(nla[NFTA_SET_FLAGS])); 2449 2426 2450 2427 bops = NULL; 2451 2428 best.size = ~0; 2452 2429 best.lookup = ~0; 2453 2430 best.space = ~0; 2454 2431 2455 - list_for_each_entry(ops, &nf_tables_set_ops, list) { 2456 - if ((ops->features & features) != features) 2432 + list_for_each_entry(type, &nf_tables_set_types, list) { 2433 + if (!type->select_ops) 2434 + ops = type->ops; 2435 + else 2436 + ops = type->select_ops(ctx, desc, flags); 2437 + if (!ops) 2457 2438 continue; 2458 - if (!ops->estimate(desc, features, &est)) 2439 + 2440 + if (!nft_set_ops_candidate(ops, flags)) 2441 + continue; 2442 + if (!ops->estimate(desc, flags, &est)) 2459 2443 continue; 2460 2444 2461 2445 switch (policy) { ··· 2491 2465 break; 2492 2466 } 2493 2467 2494 - if (!try_module_get(ops->owner)) 2468 + if (!try_module_get(type->owner)) 2495 2469 continue; 2496 2470 if (bops != NULL) 2497 - module_put(bops->owner); 2471 + module_put(bops->type->owner); 2498 2472 2499 2473 bops = ops; 2500 2474 best = est; ··· 2842 2816 2843 2817 static int nf_tables_getset(struct net *net, struct sock *nlsk, 2844 2818 struct sk_buff *skb, const struct nlmsghdr *nlh, 2845 - const struct nlattr * const nla[]) 2819 + const struct nlattr * const nla[], 2820 + struct netlink_ext_ack *extack) 2846 2821 { 2847 2822 u8 genmask = nft_genmask_cur(net); 2848 2823 const struct nft_set *set; ··· 2919 2892 2920 2893 static int nf_tables_newset(struct net *net, struct sock *nlsk, 2921 2894 struct sk_buff *skb, const struct nlmsghdr *nlh, 2922 - const struct nlattr * const nla[]) 2895 + const struct nlattr * const nla[], 2896 + struct netlink_ext_ack *extack) 2923 2897 { 2924 2898 const struct nfgenmsg *nfmsg = nlmsg_data(nlh); 2925 2899 u8 genmask = nft_genmask_next(net); ··· 3057 3029 if (!(nlh->nlmsg_flags & NLM_F_CREATE)) 3058 3030 return -ENOENT; 3059 3031 3060 - ops = nft_select_set_ops(nla, &desc, policy); 3032 + ops = nft_select_set_ops(&ctx, nla, &desc, policy); 3061 3033 if (IS_ERR(ops)) 3062 3034 return PTR_ERR(ops); 3063 3035 ··· 3067 3039 3068 3040 size = 0; 3069 3041 if (ops->privsize != NULL) 3070 - size = ops->privsize(nla); 3042 + size = ops->privsize(nla, &desc); 3071 3043 3072 - err = -ENOMEM; 3073 - set = kzalloc(sizeof(*set) + size + udlen, GFP_KERNEL); 3074 - if (set == NULL) 3044 + set = kvzalloc(sizeof(*set) + size + udlen, GFP_KERNEL); 3045 + if (!set) { 3046 + err = -ENOMEM; 3075 3047 goto err1; 3048 + } 3076 3049 3077 3050 nla_strlcpy(name, nla[NFTA_SET_NAME], sizeof(set->name)); 3078 3051 err = nf_tables_set_alloc_name(&ctx, set, name); ··· 3116 3087 err3: 3117 3088 ops->destroy(set); 3118 3089 err2: 3119 - kfree(set); 3090 + kvfree(set); 3120 3091 err1: 3121 - module_put(ops->owner); 3092 + module_put(ops->type->owner); 3122 3093 return err; 3123 3094 } 3124 3095 3125 3096 static void nft_set_destroy(struct nft_set *set) 3126 3097 { 3127 3098 set->ops->destroy(set); 3128 - module_put(set->ops->owner); 3129 - kfree(set); 3099 + module_put(set->ops->type->owner); 3100 + kvfree(set); 3130 3101 } 3131 3102 3132 3103 static void nf_tables_set_destroy(const struct nft_ctx *ctx, struct nft_set *set) ··· 3138 3109 3139 3110 static int nf_tables_delset(struct net *net, struct sock *nlsk, 3140 3111 struct sk_buff *skb, const struct nlmsghdr *nlh, 3141 - const struct nlattr * const nla[]) 3112 + const struct nlattr * const nla[], 3113 + struct netlink_ext_ack *extack) 3142 3114 { 3143 3115 const struct nfgenmsg *nfmsg = nlmsg_data(nlh); 3144 3116 u8 genmask = nft_genmask_next(net); ··· 3499 3469 3500 3470 static int nf_tables_getsetelem(struct net *net, struct sock *nlsk, 3501 3471 struct sk_buff *skb, const struct nlmsghdr *nlh, 3502 - const struct nlattr * const nla[]) 3472 + const struct nlattr * const nla[], 3473 + struct netlink_ext_ack *extack) 3503 3474 { 3504 3475 u8 genmask = nft_genmask_cur(net); 3505 3476 const struct nft_set *set; ··· 3901 3870 3902 3871 static int nf_tables_newsetelem(struct net *net, struct sock *nlsk, 3903 3872 struct sk_buff *skb, const struct nlmsghdr *nlh, 3904 - const struct nlattr * const nla[]) 3873 + const struct nlattr * const nla[], 3874 + struct netlink_ext_ack *extack) 3905 3875 { 3906 3876 u8 genmask = nft_genmask_next(net); 3907 3877 const struct nlattr *attr; ··· 4099 4067 4100 4068 static int nf_tables_delsetelem(struct net *net, struct sock *nlsk, 4101 4069 struct sk_buff *skb, const struct nlmsghdr *nlh, 4102 - const struct nlattr * const nla[]) 4070 + const struct nlattr * const nla[], 4071 + struct netlink_ext_ack *extack) 4103 4072 { 4104 4073 u8 genmask = nft_genmask_next(net); 4105 4074 const struct nlattr *attr; ··· 4310 4277 4311 4278 static int nf_tables_newobj(struct net *net, struct sock *nlsk, 4312 4279 struct sk_buff *skb, const struct nlmsghdr *nlh, 4313 - const struct nlattr * const nla[]) 4280 + const struct nlattr * const nla[], 4281 + struct netlink_ext_ack *extack) 4314 4282 { 4315 4283 const struct nfgenmsg *nfmsg = nlmsg_data(nlh); 4316 4284 const struct nft_object_type *type; ··· 4505 4471 4506 4472 static int nf_tables_getobj(struct net *net, struct sock *nlsk, 4507 4473 struct sk_buff *skb, const struct nlmsghdr *nlh, 4508 - const struct nlattr * const nla[]) 4474 + const struct nlattr * const nla[], 4475 + struct netlink_ext_ack *extack) 4509 4476 { 4510 4477 const struct nfgenmsg *nfmsg = nlmsg_data(nlh); 4511 4478 u8 genmask = nft_genmask_cur(net); ··· 4584 4549 } 4585 4550 4586 4551 static int nf_tables_delobj(struct net *net, struct sock *nlsk, 4587 - struct sk_buff *skb, const struct nlmsghdr *nlh, 4588 - const struct nlattr * const nla[]) 4552 + struct sk_buff *skb, const struct nlmsghdr *nlh, 4553 + const struct nlattr * const nla[], 4554 + struct netlink_ext_ack *extack) 4589 4555 { 4590 4556 const struct nfgenmsg *nfmsg = nlmsg_data(nlh); 4591 4557 u8 genmask = nft_genmask_next(net); ··· 4716 4680 4717 4681 static int nf_tables_getgen(struct net *net, struct sock *nlsk, 4718 4682 struct sk_buff *skb, const struct nlmsghdr *nlh, 4719 - const struct nlattr * const nla[]) 4683 + const struct nlattr * const nla[], 4684 + struct netlink_ext_ack *extack) 4720 4685 { 4721 4686 struct sk_buff *skb2; 4722 4687 int err;
+15 -6
net/netfilter/nfnetlink.c
··· 201 201 202 202 if (nc->call_rcu) { 203 203 err = nc->call_rcu(net, net->nfnl, skb, nlh, 204 - (const struct nlattr **)cda); 204 + (const struct nlattr **)cda, 205 + extack); 205 206 rcu_read_unlock(); 206 207 } else { 207 208 rcu_read_unlock(); ··· 212 211 err = -EAGAIN; 213 212 else if (nc->call) 214 213 err = nc->call(net, net->nfnl, skb, nlh, 215 - (const struct nlattr **)cda); 214 + (const struct nlattr **)cda, 215 + extack); 216 216 else 217 217 err = -EINVAL; 218 218 nfnl_unlock(subsys_id); ··· 228 226 struct list_head head; 229 227 struct nlmsghdr *nlh; 230 228 int err; 229 + struct netlink_ext_ack extack; 231 230 }; 232 231 233 - static int nfnl_err_add(struct list_head *list, struct nlmsghdr *nlh, int err) 232 + static int nfnl_err_add(struct list_head *list, struct nlmsghdr *nlh, int err, 233 + const struct netlink_ext_ack *extack) 234 234 { 235 235 struct nfnl_err *nfnl_err; 236 236 ··· 242 238 243 239 nfnl_err->nlh = nlh; 244 240 nfnl_err->err = err; 241 + nfnl_err->extack = *extack; 245 242 list_add_tail(&nfnl_err->head, list); 246 243 247 244 return 0; ··· 267 262 struct nfnl_err *nfnl_err, *next; 268 263 269 264 list_for_each_entry_safe(nfnl_err, next, err_list, head) { 270 - netlink_ack(skb, nfnl_err->nlh, nfnl_err->err, NULL); 265 + netlink_ack(skb, nfnl_err->nlh, nfnl_err->err, 266 + &nfnl_err->extack); 271 267 nfnl_err_del(nfnl_err); 272 268 } 273 269 } ··· 286 280 struct net *net = sock_net(skb->sk); 287 281 const struct nfnetlink_subsystem *ss; 288 282 const struct nfnl_callback *nc; 283 + struct netlink_ext_ack extack; 289 284 LIST_HEAD(err_list); 290 285 u32 status; 291 286 int err; ··· 332 325 while (skb->len >= nlmsg_total_size(0)) { 333 326 int msglen, type; 334 327 328 + memset(&extack, 0, sizeof(extack)); 335 329 nlh = nlmsg_hdr(skb); 336 330 err = 0; 337 331 ··· 392 384 393 385 if (nc->call_batch) { 394 386 err = nc->call_batch(net, net->nfnl, skb, nlh, 395 - (const struct nlattr **)cda); 387 + (const struct nlattr **)cda, 388 + &extack); 396 389 } 397 390 398 391 /* The lock was released to autoload some module, we ··· 411 402 * processed, this avoids that the same error is 412 403 * reported several times when replaying the batch. 413 404 */ 414 - if (nfnl_err_add(&err_list, nlh, err) < 0) { 405 + if (nfnl_err_add(&err_list, nlh, err, &extack) < 0) { 415 406 /* We failed to enqueue an error, reset the 416 407 * list of errors and send OOM to userspace 417 408 * pointing to the batch header.
+2 -1
net/netfilter/nft_compat.c
··· 530 530 531 531 static int nfnl_compat_get(struct net *net, struct sock *nfnl, 532 532 struct sk_buff *skb, const struct nlmsghdr *nlh, 533 - const struct nlattr * const tb[]) 533 + const struct nlattr * const tb[], 534 + struct netlink_ext_ack *extack) 534 535 { 535 536 int ret = 0, target; 536 537 struct nfgenmsg *nfmsg;
+8 -8
net/netfilter/nft_rt.c
··· 23 23 enum nft_registers dreg:8; 24 24 }; 25 25 26 - void nft_rt_get_eval(const struct nft_expr *expr, 27 - struct nft_regs *regs, 28 - const struct nft_pktinfo *pkt) 26 + static void nft_rt_get_eval(const struct nft_expr *expr, 27 + struct nft_regs *regs, 28 + const struct nft_pktinfo *pkt) 29 29 { 30 30 const struct nft_rt *priv = nft_expr_priv(expr); 31 31 const struct sk_buff *skb = pkt->skb; ··· 72 72 [NFTA_RT_KEY] = { .type = NLA_U32 }, 73 73 }; 74 74 75 - int nft_rt_get_init(const struct nft_ctx *ctx, 76 - const struct nft_expr *expr, 77 - const struct nlattr * const tb[]) 75 + static int nft_rt_get_init(const struct nft_ctx *ctx, 76 + const struct nft_expr *expr, 77 + const struct nlattr * const tb[]) 78 78 { 79 79 struct nft_rt *priv = nft_expr_priv(expr); 80 80 unsigned int len; ··· 103 103 NFT_DATA_VALUE, len); 104 104 } 105 105 106 - int nft_rt_get_dump(struct sk_buff *skb, 107 - const struct nft_expr *expr) 106 + static int nft_rt_get_dump(struct sk_buff *skb, 107 + const struct nft_expr *expr) 108 108 { 109 109 const struct nft_rt *priv = nft_expr_priv(expr); 110 110
+10 -3
net/netfilter/nft_set_bitmap.c
··· 236 236 return sizeof(struct nft_bitmap) + nft_bitmap_size(klen); 237 237 } 238 238 239 - static unsigned int nft_bitmap_privsize(const struct nlattr * const nla[]) 239 + static unsigned int nft_bitmap_privsize(const struct nlattr * const nla[], 240 + const struct nft_set_desc *desc) 240 241 { 241 242 u32 klen = ntohl(nla_get_be32(nla[NFTA_SET_KEY_LEN])); 242 243 ··· 279 278 return true; 280 279 } 281 280 281 + static struct nft_set_type nft_bitmap_type; 282 282 static struct nft_set_ops nft_bitmap_ops __read_mostly = { 283 + .type = &nft_bitmap_type, 283 284 .privsize = nft_bitmap_privsize, 284 285 .elemsize = offsetof(struct nft_bitmap_elem, ext), 285 286 .estimate = nft_bitmap_estimate, ··· 294 291 .activate = nft_bitmap_activate, 295 292 .lookup = nft_bitmap_lookup, 296 293 .walk = nft_bitmap_walk, 294 + }; 295 + 296 + static struct nft_set_type nft_bitmap_type __read_mostly = { 297 + .ops = &nft_bitmap_ops, 297 298 .owner = THIS_MODULE, 298 299 }; 299 300 300 301 static int __init nft_bitmap_module_init(void) 301 302 { 302 - return nft_register_set(&nft_bitmap_ops); 303 + return nft_register_set(&nft_bitmap_type); 303 304 } 304 305 305 306 static void __exit nft_bitmap_module_exit(void) 306 307 { 307 - nft_unregister_set(&nft_bitmap_ops); 308 + nft_unregister_set(&nft_bitmap_type); 308 309 } 309 310 310 311 module_init(nft_bitmap_module_init);
+363 -112
net/netfilter/nft_set_hash.c
··· 22 22 #include <net/netfilter/nf_tables.h> 23 23 24 24 /* We target a hash table size of 4, element hint is 75% of final size */ 25 - #define NFT_HASH_ELEMENT_HINT 3 25 + #define NFT_RHASH_ELEMENT_HINT 3 26 26 27 - struct nft_hash { 27 + struct nft_rhash { 28 28 struct rhashtable ht; 29 29 struct delayed_work gc_work; 30 30 }; 31 31 32 - struct nft_hash_elem { 32 + struct nft_rhash_elem { 33 33 struct rhash_head node; 34 34 struct nft_set_ext ext; 35 35 }; 36 36 37 - struct nft_hash_cmp_arg { 37 + struct nft_rhash_cmp_arg { 38 38 const struct nft_set *set; 39 39 const u32 *key; 40 40 u8 genmask; 41 41 }; 42 42 43 - static const struct rhashtable_params nft_hash_params; 44 - 45 - static inline u32 nft_hash_key(const void *data, u32 len, u32 seed) 43 + static inline u32 nft_rhash_key(const void *data, u32 len, u32 seed) 46 44 { 47 - const struct nft_hash_cmp_arg *arg = data; 45 + const struct nft_rhash_cmp_arg *arg = data; 48 46 49 47 return jhash(arg->key, len, seed); 50 48 } 51 49 52 - static inline u32 nft_hash_obj(const void *data, u32 len, u32 seed) 50 + static inline u32 nft_rhash_obj(const void *data, u32 len, u32 seed) 53 51 { 54 - const struct nft_hash_elem *he = data; 52 + const struct nft_rhash_elem *he = data; 55 53 56 54 return jhash(nft_set_ext_key(&he->ext), len, seed); 57 55 } 58 56 59 - static inline int nft_hash_cmp(struct rhashtable_compare_arg *arg, 60 - const void *ptr) 57 + static inline int nft_rhash_cmp(struct rhashtable_compare_arg *arg, 58 + const void *ptr) 61 59 { 62 - const struct nft_hash_cmp_arg *x = arg->key; 63 - const struct nft_hash_elem *he = ptr; 60 + const struct nft_rhash_cmp_arg *x = arg->key; 61 + const struct nft_rhash_elem *he = ptr; 64 62 65 63 if (memcmp(nft_set_ext_key(&he->ext), x->key, x->set->klen)) 66 64 return 1; ··· 69 71 return 0; 70 72 } 71 73 72 - static bool nft_hash_lookup(const struct net *net, const struct nft_set *set, 73 - const u32 *key, const struct nft_set_ext **ext) 74 + static const struct rhashtable_params nft_rhash_params = { 75 + .head_offset = offsetof(struct nft_rhash_elem, node), 76 + .hashfn = nft_rhash_key, 77 + .obj_hashfn = nft_rhash_obj, 78 + .obj_cmpfn = nft_rhash_cmp, 79 + .automatic_shrinking = true, 80 + }; 81 + 82 + static bool nft_rhash_lookup(const struct net *net, const struct nft_set *set, 83 + const u32 *key, const struct nft_set_ext **ext) 74 84 { 75 - struct nft_hash *priv = nft_set_priv(set); 76 - const struct nft_hash_elem *he; 77 - struct nft_hash_cmp_arg arg = { 85 + struct nft_rhash *priv = nft_set_priv(set); 86 + const struct nft_rhash_elem *he; 87 + struct nft_rhash_cmp_arg arg = { 78 88 .genmask = nft_genmask_cur(net), 79 89 .set = set, 80 90 .key = key, 81 91 }; 82 92 83 - he = rhashtable_lookup_fast(&priv->ht, &arg, nft_hash_params); 93 + he = rhashtable_lookup_fast(&priv->ht, &arg, nft_rhash_params); 84 94 if (he != NULL) 85 95 *ext = &he->ext; 86 96 87 97 return !!he; 88 98 } 89 99 90 - static bool nft_hash_update(struct nft_set *set, const u32 *key, 91 - void *(*new)(struct nft_set *, 92 - const struct nft_expr *, 93 - struct nft_regs *regs), 94 - const struct nft_expr *expr, 95 - struct nft_regs *regs, 96 - const struct nft_set_ext **ext) 100 + static bool nft_rhash_update(struct nft_set *set, const u32 *key, 101 + void *(*new)(struct nft_set *, 102 + const struct nft_expr *, 103 + struct nft_regs *regs), 104 + const struct nft_expr *expr, 105 + struct nft_regs *regs, 106 + const struct nft_set_ext **ext) 97 107 { 98 - struct nft_hash *priv = nft_set_priv(set); 99 - struct nft_hash_elem *he, *prev; 100 - struct nft_hash_cmp_arg arg = { 108 + struct nft_rhash *priv = nft_set_priv(set); 109 + struct nft_rhash_elem *he, *prev; 110 + struct nft_rhash_cmp_arg arg = { 101 111 .genmask = NFT_GENMASK_ANY, 102 112 .set = set, 103 113 .key = key, 104 114 }; 105 115 106 - he = rhashtable_lookup_fast(&priv->ht, &arg, nft_hash_params); 116 + he = rhashtable_lookup_fast(&priv->ht, &arg, nft_rhash_params); 107 117 if (he != NULL) 108 118 goto out; 109 119 ··· 120 114 goto err1; 121 115 122 116 prev = rhashtable_lookup_get_insert_key(&priv->ht, &arg, &he->node, 123 - nft_hash_params); 117 + nft_rhash_params); 124 118 if (IS_ERR(prev)) 125 119 goto err2; 126 120 ··· 140 134 return false; 141 135 } 142 136 143 - static int nft_hash_insert(const struct net *net, const struct nft_set *set, 144 - const struct nft_set_elem *elem, 145 - struct nft_set_ext **ext) 137 + static int nft_rhash_insert(const struct net *net, const struct nft_set *set, 138 + const struct nft_set_elem *elem, 139 + struct nft_set_ext **ext) 146 140 { 147 - struct nft_hash *priv = nft_set_priv(set); 148 - struct nft_hash_elem *he = elem->priv; 149 - struct nft_hash_cmp_arg arg = { 141 + struct nft_rhash *priv = nft_set_priv(set); 142 + struct nft_rhash_elem *he = elem->priv; 143 + struct nft_rhash_cmp_arg arg = { 150 144 .genmask = nft_genmask_next(net), 151 145 .set = set, 152 146 .key = elem->key.val.data, 153 147 }; 154 - struct nft_hash_elem *prev; 148 + struct nft_rhash_elem *prev; 155 149 156 150 prev = rhashtable_lookup_get_insert_key(&priv->ht, &arg, &he->node, 157 - nft_hash_params); 151 + nft_rhash_params); 158 152 if (IS_ERR(prev)) 159 153 return PTR_ERR(prev); 160 154 if (prev) { ··· 164 158 return 0; 165 159 } 166 160 167 - static void nft_hash_activate(const struct net *net, const struct nft_set *set, 168 - const struct nft_set_elem *elem) 161 + static void nft_rhash_activate(const struct net *net, const struct nft_set *set, 162 + const struct nft_set_elem *elem) 169 163 { 170 - struct nft_hash_elem *he = elem->priv; 164 + struct nft_rhash_elem *he = elem->priv; 171 165 172 166 nft_set_elem_change_active(net, set, &he->ext); 173 167 nft_set_elem_clear_busy(&he->ext); 174 168 } 175 169 176 - static bool nft_hash_flush(const struct net *net, 177 - const struct nft_set *set, void *priv) 170 + static bool nft_rhash_flush(const struct net *net, 171 + const struct nft_set *set, void *priv) 178 172 { 179 - struct nft_hash_elem *he = priv; 173 + struct nft_rhash_elem *he = priv; 180 174 181 175 if (!nft_set_elem_mark_busy(&he->ext) || 182 176 !nft_is_active(net, &he->ext)) { ··· 186 180 return false; 187 181 } 188 182 189 - static void *nft_hash_deactivate(const struct net *net, 190 - const struct nft_set *set, 191 - const struct nft_set_elem *elem) 183 + static void *nft_rhash_deactivate(const struct net *net, 184 + const struct nft_set *set, 185 + const struct nft_set_elem *elem) 192 186 { 193 - struct nft_hash *priv = nft_set_priv(set); 194 - struct nft_hash_elem *he; 195 - struct nft_hash_cmp_arg arg = { 187 + struct nft_rhash *priv = nft_set_priv(set); 188 + struct nft_rhash_elem *he; 189 + struct nft_rhash_cmp_arg arg = { 196 190 .genmask = nft_genmask_next(net), 197 191 .set = set, 198 192 .key = elem->key.val.data, 199 193 }; 200 194 201 195 rcu_read_lock(); 202 - he = rhashtable_lookup_fast(&priv->ht, &arg, nft_hash_params); 196 + he = rhashtable_lookup_fast(&priv->ht, &arg, nft_rhash_params); 203 197 if (he != NULL && 204 - !nft_hash_flush(net, set, he)) 198 + !nft_rhash_flush(net, set, he)) 205 199 he = NULL; 206 200 207 201 rcu_read_unlock(); ··· 209 203 return he; 210 204 } 211 205 212 - static void nft_hash_remove(const struct net *net, 213 - const struct nft_set *set, 214 - const struct nft_set_elem *elem) 206 + static void nft_rhash_remove(const struct net *net, 207 + const struct nft_set *set, 208 + const struct nft_set_elem *elem) 215 209 { 216 - struct nft_hash *priv = nft_set_priv(set); 217 - struct nft_hash_elem *he = elem->priv; 210 + struct nft_rhash *priv = nft_set_priv(set); 211 + struct nft_rhash_elem *he = elem->priv; 218 212 219 - rhashtable_remove_fast(&priv->ht, &he->node, nft_hash_params); 213 + rhashtable_remove_fast(&priv->ht, &he->node, nft_rhash_params); 220 214 } 221 215 222 - static void nft_hash_walk(const struct nft_ctx *ctx, struct nft_set *set, 223 - struct nft_set_iter *iter) 216 + static void nft_rhash_walk(const struct nft_ctx *ctx, struct nft_set *set, 217 + struct nft_set_iter *iter) 224 218 { 225 - struct nft_hash *priv = nft_set_priv(set); 226 - struct nft_hash_elem *he; 219 + struct nft_rhash *priv = nft_set_priv(set); 220 + struct nft_rhash_elem *he; 227 221 struct rhashtable_iter hti; 228 222 struct nft_set_elem elem; 229 223 int err; ··· 272 266 rhashtable_walk_exit(&hti); 273 267 } 274 268 275 - static void nft_hash_gc(struct work_struct *work) 269 + static void nft_rhash_gc(struct work_struct *work) 276 270 { 277 271 struct nft_set *set; 278 - struct nft_hash_elem *he; 279 - struct nft_hash *priv; 272 + struct nft_rhash_elem *he; 273 + struct nft_rhash *priv; 280 274 struct nft_set_gc_batch *gcb = NULL; 281 275 struct rhashtable_iter hti; 282 276 int err; 283 277 284 - priv = container_of(work, struct nft_hash, gc_work.work); 278 + priv = container_of(work, struct nft_rhash, gc_work.work); 285 279 set = nft_set_container_of(priv); 286 280 287 281 err = rhashtable_walk_init(&priv->ht, &hti, GFP_KERNEL); ··· 307 301 gcb = nft_set_gc_batch_check(set, gcb, GFP_ATOMIC); 308 302 if (gcb == NULL) 309 303 goto out; 310 - rhashtable_remove_fast(&priv->ht, &he->node, nft_hash_params); 304 + rhashtable_remove_fast(&priv->ht, &he->node, nft_rhash_params); 311 305 atomic_dec(&set->nelems); 312 306 nft_set_gc_batch_add(gcb, he); 313 307 } ··· 321 315 nft_set_gc_interval(set)); 322 316 } 323 317 324 - static unsigned int nft_hash_privsize(const struct nlattr * const nla[]) 318 + static unsigned int nft_rhash_privsize(const struct nlattr * const nla[], 319 + const struct nft_set_desc *desc) 325 320 { 326 - return sizeof(struct nft_hash); 321 + return sizeof(struct nft_rhash); 327 322 } 328 323 329 - static const struct rhashtable_params nft_hash_params = { 330 - .head_offset = offsetof(struct nft_hash_elem, node), 331 - .hashfn = nft_hash_key, 332 - .obj_hashfn = nft_hash_obj, 333 - .obj_cmpfn = nft_hash_cmp, 334 - .automatic_shrinking = true, 335 - }; 336 - 337 - static int nft_hash_init(const struct nft_set *set, 338 - const struct nft_set_desc *desc, 339 - const struct nlattr * const tb[]) 324 + static int nft_rhash_init(const struct nft_set *set, 325 + const struct nft_set_desc *desc, 326 + const struct nlattr * const tb[]) 340 327 { 341 - struct nft_hash *priv = nft_set_priv(set); 342 - struct rhashtable_params params = nft_hash_params; 328 + struct nft_rhash *priv = nft_set_priv(set); 329 + struct rhashtable_params params = nft_rhash_params; 343 330 int err; 344 331 345 - params.nelem_hint = desc->size ?: NFT_HASH_ELEMENT_HINT; 332 + params.nelem_hint = desc->size ?: NFT_RHASH_ELEMENT_HINT; 346 333 params.key_len = set->klen; 347 334 348 335 err = rhashtable_init(&priv->ht, &params); 349 336 if (err < 0) 350 337 return err; 351 338 352 - INIT_DEFERRABLE_WORK(&priv->gc_work, nft_hash_gc); 339 + INIT_DEFERRABLE_WORK(&priv->gc_work, nft_rhash_gc); 353 340 if (set->flags & NFT_SET_TIMEOUT) 354 341 queue_delayed_work(system_power_efficient_wq, &priv->gc_work, 355 342 nft_set_gc_interval(set)); 356 343 return 0; 357 344 } 358 345 359 - static void nft_hash_elem_destroy(void *ptr, void *arg) 346 + static void nft_rhash_elem_destroy(void *ptr, void *arg) 360 347 { 361 348 nft_set_elem_destroy(arg, ptr, true); 362 349 } 363 350 364 - static void nft_hash_destroy(const struct nft_set *set) 351 + static void nft_rhash_destroy(const struct nft_set *set) 365 352 { 366 - struct nft_hash *priv = nft_set_priv(set); 353 + struct nft_rhash *priv = nft_set_priv(set); 367 354 368 355 cancel_delayed_work_sync(&priv->gc_work); 369 - rhashtable_free_and_destroy(&priv->ht, nft_hash_elem_destroy, 356 + rhashtable_free_and_destroy(&priv->ht, nft_rhash_elem_destroy, 370 357 (void *)set); 371 358 } 372 359 373 - static bool nft_hash_estimate(const struct nft_set_desc *desc, u32 features, 374 - struct nft_set_estimate *est) 360 + static u32 nft_hash_buckets(u32 size) 375 361 { 376 - unsigned int esize; 362 + return roundup_pow_of_two(size * 4 / 3); 363 + } 377 364 378 - esize = sizeof(struct nft_hash_elem); 379 - if (desc->size) { 380 - est->size = sizeof(struct nft_hash) + 381 - roundup_pow_of_two(desc->size * 4 / 3) * 382 - sizeof(struct nft_hash_elem *) + 383 - desc->size * esize; 384 - } else { 385 - /* Resizing happens when the load drops below 30% or goes 386 - * above 75%. The average of 52.5% load (approximated by 50%) 387 - * is used for the size estimation of the hash buckets, 388 - * meaning we calculate two buckets per element. 389 - */ 390 - est->size = esize + 2 * sizeof(struct nft_hash_elem *); 391 - } 392 - 365 + static bool nft_rhash_estimate(const struct nft_set_desc *desc, u32 features, 366 + struct nft_set_estimate *est) 367 + { 368 + est->size = ~0; 393 369 est->lookup = NFT_SET_CLASS_O_1; 394 370 est->space = NFT_SET_CLASS_O_N; 395 371 396 372 return true; 397 373 } 398 374 375 + struct nft_hash { 376 + u32 seed; 377 + u32 buckets; 378 + struct hlist_head table[]; 379 + }; 380 + 381 + struct nft_hash_elem { 382 + struct hlist_node node; 383 + struct nft_set_ext ext; 384 + }; 385 + 386 + static bool nft_hash_lookup(const struct net *net, const struct nft_set *set, 387 + const u32 *key, const struct nft_set_ext **ext) 388 + { 389 + struct nft_hash *priv = nft_set_priv(set); 390 + u8 genmask = nft_genmask_cur(net); 391 + const struct nft_hash_elem *he; 392 + u32 hash; 393 + 394 + hash = jhash(key, set->klen, priv->seed); 395 + hash = reciprocal_scale(hash, priv->buckets); 396 + hlist_for_each_entry_rcu(he, &priv->table[hash], node) { 397 + if (!memcmp(nft_set_ext_key(&he->ext), key, set->klen) && 398 + nft_set_elem_active(&he->ext, genmask)) { 399 + *ext = &he->ext; 400 + return true; 401 + } 402 + } 403 + return false; 404 + } 405 + 406 + /* nft_hash_select_ops() makes sure key size can be either 2 or 4 bytes . */ 407 + static inline u32 nft_hash_key(const u32 *key, u32 klen) 408 + { 409 + if (klen == 4) 410 + return *key; 411 + 412 + return *(u16 *)key; 413 + } 414 + 415 + static bool nft_hash_lookup_fast(const struct net *net, 416 + const struct nft_set *set, 417 + const u32 *key, const struct nft_set_ext **ext) 418 + { 419 + struct nft_hash *priv = nft_set_priv(set); 420 + u8 genmask = nft_genmask_cur(net); 421 + const struct nft_hash_elem *he; 422 + u32 hash, k1, k2; 423 + 424 + k1 = nft_hash_key(key, set->klen); 425 + hash = jhash_1word(k1, priv->seed); 426 + hash = reciprocal_scale(hash, priv->buckets); 427 + hlist_for_each_entry_rcu(he, &priv->table[hash], node) { 428 + k2 = nft_hash_key(nft_set_ext_key(&he->ext)->data, set->klen); 429 + if (k1 == k2 && 430 + nft_set_elem_active(&he->ext, genmask)) { 431 + *ext = &he->ext; 432 + return true; 433 + } 434 + } 435 + return false; 436 + } 437 + 438 + static int nft_hash_insert(const struct net *net, const struct nft_set *set, 439 + const struct nft_set_elem *elem, 440 + struct nft_set_ext **ext) 441 + { 442 + struct nft_hash_elem *this = elem->priv, *he; 443 + struct nft_hash *priv = nft_set_priv(set); 444 + u8 genmask = nft_genmask_next(net); 445 + u32 hash; 446 + 447 + hash = jhash(nft_set_ext_key(&this->ext), set->klen, priv->seed); 448 + hash = reciprocal_scale(hash, priv->buckets); 449 + hlist_for_each_entry(he, &priv->table[hash], node) { 450 + if (!memcmp(nft_set_ext_key(&this->ext), 451 + nft_set_ext_key(&he->ext), set->klen) && 452 + nft_set_elem_active(&he->ext, genmask)) { 453 + *ext = &he->ext; 454 + return -EEXIST; 455 + } 456 + } 457 + hlist_add_head_rcu(&this->node, &priv->table[hash]); 458 + return 0; 459 + } 460 + 461 + static void nft_hash_activate(const struct net *net, const struct nft_set *set, 462 + const struct nft_set_elem *elem) 463 + { 464 + struct nft_hash_elem *he = elem->priv; 465 + 466 + nft_set_elem_change_active(net, set, &he->ext); 467 + } 468 + 469 + static bool nft_hash_flush(const struct net *net, 470 + const struct nft_set *set, void *priv) 471 + { 472 + struct nft_hash_elem *he = priv; 473 + 474 + nft_set_elem_change_active(net, set, &he->ext); 475 + return true; 476 + } 477 + 478 + static void *nft_hash_deactivate(const struct net *net, 479 + const struct nft_set *set, 480 + const struct nft_set_elem *elem) 481 + { 482 + struct nft_hash *priv = nft_set_priv(set); 483 + struct nft_hash_elem *this = elem->priv, *he; 484 + u8 genmask = nft_genmask_next(net); 485 + u32 hash; 486 + 487 + hash = jhash(nft_set_ext_key(&this->ext), set->klen, priv->seed); 488 + hash = reciprocal_scale(hash, priv->buckets); 489 + hlist_for_each_entry(he, &priv->table[hash], node) { 490 + if (!memcmp(nft_set_ext_key(&this->ext), &elem->key.val, 491 + set->klen) || 492 + nft_set_elem_active(&he->ext, genmask)) { 493 + nft_set_elem_change_active(net, set, &he->ext); 494 + return he; 495 + } 496 + } 497 + return NULL; 498 + } 499 + 500 + static void nft_hash_remove(const struct net *net, 501 + const struct nft_set *set, 502 + const struct nft_set_elem *elem) 503 + { 504 + struct nft_hash_elem *he = elem->priv; 505 + 506 + hlist_del_rcu(&he->node); 507 + } 508 + 509 + static void nft_hash_walk(const struct nft_ctx *ctx, struct nft_set *set, 510 + struct nft_set_iter *iter) 511 + { 512 + struct nft_hash *priv = nft_set_priv(set); 513 + struct nft_hash_elem *he; 514 + struct nft_set_elem elem; 515 + int i; 516 + 517 + for (i = 0; i < priv->buckets; i++) { 518 + hlist_for_each_entry_rcu(he, &priv->table[i], node) { 519 + if (iter->count < iter->skip) 520 + goto cont; 521 + if (!nft_set_elem_active(&he->ext, iter->genmask)) 522 + goto cont; 523 + 524 + elem.priv = he; 525 + 526 + iter->err = iter->fn(ctx, set, iter, &elem); 527 + if (iter->err < 0) 528 + return; 529 + cont: 530 + iter->count++; 531 + } 532 + } 533 + } 534 + 535 + static unsigned int nft_hash_privsize(const struct nlattr * const nla[], 536 + const struct nft_set_desc *desc) 537 + { 538 + return sizeof(struct nft_hash) + 539 + nft_hash_buckets(desc->size) * sizeof(struct hlist_head); 540 + } 541 + 542 + static int nft_hash_init(const struct nft_set *set, 543 + const struct nft_set_desc *desc, 544 + const struct nlattr * const tb[]) 545 + { 546 + struct nft_hash *priv = nft_set_priv(set); 547 + 548 + priv->buckets = nft_hash_buckets(desc->size); 549 + get_random_bytes(&priv->seed, sizeof(priv->seed)); 550 + 551 + return 0; 552 + } 553 + 554 + static void nft_hash_destroy(const struct nft_set *set) 555 + { 556 + struct nft_hash *priv = nft_set_priv(set); 557 + struct nft_hash_elem *he; 558 + struct hlist_node *next; 559 + int i; 560 + 561 + for (i = 0; i < priv->buckets; i++) { 562 + hlist_for_each_entry_safe(he, next, &priv->table[i], node) { 563 + hlist_del_rcu(&he->node); 564 + nft_set_elem_destroy(set, he, true); 565 + } 566 + } 567 + } 568 + 569 + static bool nft_hash_estimate(const struct nft_set_desc *desc, u32 features, 570 + struct nft_set_estimate *est) 571 + { 572 + est->size = sizeof(struct nft_hash) + 573 + nft_hash_buckets(desc->size) * sizeof(struct hlist_head) + 574 + desc->size * sizeof(struct nft_hash_elem); 575 + est->lookup = NFT_SET_CLASS_O_1; 576 + est->space = NFT_SET_CLASS_O_N; 577 + 578 + return true; 579 + } 580 + 581 + static struct nft_set_type nft_hash_type; 582 + static struct nft_set_ops nft_rhash_ops __read_mostly = { 583 + .type = &nft_hash_type, 584 + .privsize = nft_rhash_privsize, 585 + .elemsize = offsetof(struct nft_rhash_elem, ext), 586 + .estimate = nft_rhash_estimate, 587 + .init = nft_rhash_init, 588 + .destroy = nft_rhash_destroy, 589 + .insert = nft_rhash_insert, 590 + .activate = nft_rhash_activate, 591 + .deactivate = nft_rhash_deactivate, 592 + .flush = nft_rhash_flush, 593 + .remove = nft_rhash_remove, 594 + .lookup = nft_rhash_lookup, 595 + .update = nft_rhash_update, 596 + .walk = nft_rhash_walk, 597 + .features = NFT_SET_MAP | NFT_SET_OBJECT | NFT_SET_TIMEOUT, 598 + }; 599 + 399 600 static struct nft_set_ops nft_hash_ops __read_mostly = { 601 + .type = &nft_hash_type, 400 602 .privsize = nft_hash_privsize, 401 603 .elemsize = offsetof(struct nft_hash_elem, ext), 402 604 .estimate = nft_hash_estimate, ··· 616 402 .flush = nft_hash_flush, 617 403 .remove = nft_hash_remove, 618 404 .lookup = nft_hash_lookup, 619 - .update = nft_hash_update, 620 405 .walk = nft_hash_walk, 621 - .features = NFT_SET_MAP | NFT_SET_OBJECT | NFT_SET_TIMEOUT, 406 + .features = NFT_SET_MAP | NFT_SET_OBJECT, 407 + }; 408 + 409 + static struct nft_set_ops nft_hash_fast_ops __read_mostly = { 410 + .type = &nft_hash_type, 411 + .privsize = nft_hash_privsize, 412 + .elemsize = offsetof(struct nft_hash_elem, ext), 413 + .estimate = nft_hash_estimate, 414 + .init = nft_hash_init, 415 + .destroy = nft_hash_destroy, 416 + .insert = nft_hash_insert, 417 + .activate = nft_hash_activate, 418 + .deactivate = nft_hash_deactivate, 419 + .flush = nft_hash_flush, 420 + .remove = nft_hash_remove, 421 + .lookup = nft_hash_lookup_fast, 422 + .walk = nft_hash_walk, 423 + .features = NFT_SET_MAP | NFT_SET_OBJECT, 424 + }; 425 + 426 + static const struct nft_set_ops * 427 + nft_hash_select_ops(const struct nft_ctx *ctx, const struct nft_set_desc *desc, 428 + u32 flags) 429 + { 430 + if (desc->size) { 431 + switch (desc->klen) { 432 + case 2: 433 + case 4: 434 + return &nft_hash_fast_ops; 435 + default: 436 + return &nft_hash_ops; 437 + } 438 + } 439 + 440 + return &nft_rhash_ops; 441 + } 442 + 443 + static struct nft_set_type nft_hash_type __read_mostly = { 444 + .select_ops = nft_hash_select_ops, 622 445 .owner = THIS_MODULE, 623 446 }; 624 447 625 448 static int __init nft_hash_module_init(void) 626 449 { 627 - return nft_register_set(&nft_hash_ops); 450 + return nft_register_set(&nft_hash_type); 628 451 } 629 452 630 453 static void __exit nft_hash_module_exit(void) 631 454 { 632 - nft_unregister_set(&nft_hash_ops); 455 + nft_unregister_set(&nft_hash_type); 633 456 } 634 457 635 458 module_init(nft_hash_module_init);
+13 -8
net/netfilter/nft_set_rbtree.c
··· 251 251 read_unlock_bh(&priv->lock); 252 252 } 253 253 254 - static unsigned int nft_rbtree_privsize(const struct nlattr * const nla[]) 254 + static unsigned int nft_rbtree_privsize(const struct nlattr * const nla[], 255 + const struct nft_set_desc *desc) 255 256 { 256 257 return sizeof(struct nft_rbtree); 257 258 } ··· 284 283 static bool nft_rbtree_estimate(const struct nft_set_desc *desc, u32 features, 285 284 struct nft_set_estimate *est) 286 285 { 287 - unsigned int nsize; 288 - 289 - nsize = sizeof(struct nft_rbtree_elem); 290 286 if (desc->size) 291 - est->size = sizeof(struct nft_rbtree) + desc->size * nsize; 287 + est->size = sizeof(struct nft_rbtree) + 288 + desc->size * sizeof(struct nft_rbtree_elem); 292 289 else 293 - est->size = nsize; 290 + est->size = ~0; 294 291 295 292 est->lookup = NFT_SET_CLASS_O_LOG_N; 296 293 est->space = NFT_SET_CLASS_O_N; ··· 296 297 return true; 297 298 } 298 299 300 + static struct nft_set_type nft_rbtree_type; 299 301 static struct nft_set_ops nft_rbtree_ops __read_mostly = { 302 + .type = &nft_rbtree_type, 300 303 .privsize = nft_rbtree_privsize, 301 304 .elemsize = offsetof(struct nft_rbtree_elem, ext), 302 305 .estimate = nft_rbtree_estimate, ··· 312 311 .lookup = nft_rbtree_lookup, 313 312 .walk = nft_rbtree_walk, 314 313 .features = NFT_SET_INTERVAL | NFT_SET_MAP | NFT_SET_OBJECT, 314 + }; 315 + 316 + static struct nft_set_type nft_rbtree_type __read_mostly = { 317 + .ops = &nft_rbtree_ops, 315 318 .owner = THIS_MODULE, 316 319 }; 317 320 318 321 static int __init nft_rbtree_module_init(void) 319 322 { 320 - return nft_register_set(&nft_rbtree_ops); 323 + return nft_register_set(&nft_rbtree_type); 321 324 } 322 325 323 326 static void __exit nft_rbtree_module_exit(void) 324 327 { 325 - nft_unregister_set(&nft_rbtree_ops); 328 + nft_unregister_set(&nft_rbtree_type); 326 329 } 327 330 328 331 module_init(nft_rbtree_module_init);
+4 -2
net/netfilter/xt_osf.c
··· 63 63 64 64 static int xt_osf_add_callback(struct net *net, struct sock *ctnl, 65 65 struct sk_buff *skb, const struct nlmsghdr *nlh, 66 - const struct nlattr * const osf_attrs[]) 66 + const struct nlattr * const osf_attrs[], 67 + struct netlink_ext_ack *extack) 67 68 { 68 69 struct xt_osf_user_finger *f; 69 70 struct xt_osf_finger *kf = NULL, *sf; ··· 108 107 static int xt_osf_remove_callback(struct net *net, struct sock *ctnl, 109 108 struct sk_buff *skb, 110 109 const struct nlmsghdr *nlh, 111 - const struct nlattr * const osf_attrs[]) 110 + const struct nlattr * const osf_attrs[], 111 + struct netlink_ext_ack *extack) 112 112 { 113 113 struct xt_osf_user_finger *f; 114 114 struct xt_osf_finger *sf;