diff options
author | David S. Miller <davem@davemloft.net> | 2013-11-04 19:46:58 -0500 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2013-11-04 19:46:58 -0500 |
commit | 72c39a0ade6229a938736fe1aa1d5e471fc7face (patch) | |
tree | 33e5e634d553750eba4bf876a23c4c051e0d9c26 /net/ipv4 | |
parent | 6fcf018ae4491dc11b080892fa9f3dbd928fdbb9 (diff) | |
parent | 4542fa4727f5f83faf9e1f28f35be0b9a2317aec (diff) |
Merge branch 'master' of git://git.kernel.org/pub/scm/linux/kernel/git/pablo/nf-next
Pablo Neira Ayuso says:
====================
This is another batch containing Netfilter/IPVS updates for your net-next
tree, they are:
* Six patches to make the ipt_CLUSTERIP target support netnamespace,
from Gao feng.
* Two cleanups for the nf_conntrack_acct infrastructure, introducing
a new structure to encapsulate conntrack counters, from Holger
Eitzenberger.
* Fix missing verdict in SCTP support for IPVS, from Daniel Borkmann.
* Skip checksum recalculation in SCTP support for IPVS, also from
Daniel Borkmann.
* Fix behavioural change in xt_socket after IP early demux, from
Florian Westphal.
* Fix bogus large memory allocation in the bitmap port set type in ipset,
from Jozsef Kadlecsik.
* Fix possible compilation issues in the hash netnet set type in ipset,
also from Jozsef Kadlecsik.
* Define constants to identify netlink callback data in ipset dumps,
again from Jozsef Kadlecsik.
* Use sock_gen_put() in xt_socket to replace xt_socket_put_sk,
from Eric Dumazet.
* Improvements for the SH scheduler in IPVS, from Alexander Frolkin.
* Remove extra delay due to unneeded rcu barrier in IPVS net namespace
cleanup path, from Julian Anastasov.
* Save some cycles in ip6t_REJECT by skipping checksum validation in
packets leaving from our stack, from Stanislav Fomichev.
* Fix IPVS_CMD_ATTR_MAX definition in IPVS, larger that required, from
Julian Anastasov.
====================
Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'net/ipv4')
-rw-r--r-- | net/ipv4/netfilter/ipt_CLUSTERIP.c | 110 |
1 files changed, 75 insertions, 35 deletions
diff --git a/net/ipv4/netfilter/ipt_CLUSTERIP.c b/net/ipv4/netfilter/ipt_CLUSTERIP.c index a2e2b61cd7da..2510c02c2d21 100644 --- a/net/ipv4/netfilter/ipt_CLUSTERIP.c +++ b/net/ipv4/netfilter/ipt_CLUSTERIP.c | |||
@@ -28,6 +28,7 @@ | |||
28 | #include <linux/netfilter_ipv4/ipt_CLUSTERIP.h> | 28 | #include <linux/netfilter_ipv4/ipt_CLUSTERIP.h> |
29 | #include <net/netfilter/nf_conntrack.h> | 29 | #include <net/netfilter/nf_conntrack.h> |
30 | #include <net/net_namespace.h> | 30 | #include <net/net_namespace.h> |
31 | #include <net/netns/generic.h> | ||
31 | #include <net/checksum.h> | 32 | #include <net/checksum.h> |
32 | #include <net/ip.h> | 33 | #include <net/ip.h> |
33 | 34 | ||
@@ -57,15 +58,21 @@ struct clusterip_config { | |||
57 | struct rcu_head rcu; | 58 | struct rcu_head rcu; |
58 | }; | 59 | }; |
59 | 60 | ||
60 | static LIST_HEAD(clusterip_configs); | 61 | #ifdef CONFIG_PROC_FS |
62 | static const struct file_operations clusterip_proc_fops; | ||
63 | #endif | ||
61 | 64 | ||
62 | /* clusterip_lock protects the clusterip_configs list */ | 65 | static int clusterip_net_id __read_mostly; |
63 | static DEFINE_SPINLOCK(clusterip_lock); | 66 | |
67 | struct clusterip_net { | ||
68 | struct list_head configs; | ||
69 | /* lock protects the configs list */ | ||
70 | spinlock_t lock; | ||
64 | 71 | ||
65 | #ifdef CONFIG_PROC_FS | 72 | #ifdef CONFIG_PROC_FS |
66 | static const struct file_operations clusterip_proc_fops; | 73 | struct proc_dir_entry *procdir; |
67 | static struct proc_dir_entry *clusterip_procdir; | ||
68 | #endif | 74 | #endif |
75 | }; | ||
69 | 76 | ||
70 | static inline void | 77 | static inline void |
71 | clusterip_config_get(struct clusterip_config *c) | 78 | clusterip_config_get(struct clusterip_config *c) |
@@ -92,10 +99,13 @@ clusterip_config_put(struct clusterip_config *c) | |||
92 | static inline void | 99 | static inline void |
93 | clusterip_config_entry_put(struct clusterip_config *c) | 100 | clusterip_config_entry_put(struct clusterip_config *c) |
94 | { | 101 | { |
102 | struct net *net = dev_net(c->dev); | ||
103 | struct clusterip_net *cn = net_generic(net, clusterip_net_id); | ||
104 | |||
95 | local_bh_disable(); | 105 | local_bh_disable(); |
96 | if (atomic_dec_and_lock(&c->entries, &clusterip_lock)) { | 106 | if (atomic_dec_and_lock(&c->entries, &cn->lock)) { |
97 | list_del_rcu(&c->list); | 107 | list_del_rcu(&c->list); |
98 | spin_unlock(&clusterip_lock); | 108 | spin_unlock(&cn->lock); |
99 | local_bh_enable(); | 109 | local_bh_enable(); |
100 | 110 | ||
101 | dev_mc_del(c->dev, c->clustermac); | 111 | dev_mc_del(c->dev, c->clustermac); |
@@ -113,11 +123,12 @@ clusterip_config_entry_put(struct clusterip_config *c) | |||
113 | } | 123 | } |
114 | 124 | ||
115 | static struct clusterip_config * | 125 | static struct clusterip_config * |
116 | __clusterip_config_find(__be32 clusterip) | 126 | __clusterip_config_find(struct net *net, __be32 clusterip) |
117 | { | 127 | { |
118 | struct clusterip_config *c; | 128 | struct clusterip_config *c; |
129 | struct clusterip_net *cn = net_generic(net, clusterip_net_id); | ||
119 | 130 | ||
120 | list_for_each_entry_rcu(c, &clusterip_configs, list) { | 131 | list_for_each_entry_rcu(c, &cn->configs, list) { |
121 | if (c->clusterip == clusterip) | 132 | if (c->clusterip == clusterip) |
122 | return c; | 133 | return c; |
123 | } | 134 | } |
@@ -126,12 +137,12 @@ __clusterip_config_find(__be32 clusterip) | |||
126 | } | 137 | } |
127 | 138 | ||
128 | static inline struct clusterip_config * | 139 | static inline struct clusterip_config * |
129 | clusterip_config_find_get(__be32 clusterip, int entry) | 140 | clusterip_config_find_get(struct net *net, __be32 clusterip, int entry) |
130 | { | 141 | { |
131 | struct clusterip_config *c; | 142 | struct clusterip_config *c; |
132 | 143 | ||
133 | rcu_read_lock_bh(); | 144 | rcu_read_lock_bh(); |
134 | c = __clusterip_config_find(clusterip); | 145 | c = __clusterip_config_find(net, clusterip); |
135 | if (c) { | 146 | if (c) { |
136 | if (unlikely(!atomic_inc_not_zero(&c->refcount))) | 147 | if (unlikely(!atomic_inc_not_zero(&c->refcount))) |
137 | c = NULL; | 148 | c = NULL; |
@@ -158,6 +169,7 @@ clusterip_config_init(const struct ipt_clusterip_tgt_info *i, __be32 ip, | |||
158 | struct net_device *dev) | 169 | struct net_device *dev) |
159 | { | 170 | { |
160 | struct clusterip_config *c; | 171 | struct clusterip_config *c; |
172 | struct clusterip_net *cn = net_generic(dev_net(dev), clusterip_net_id); | ||
161 | 173 | ||
162 | c = kzalloc(sizeof(*c), GFP_ATOMIC); | 174 | c = kzalloc(sizeof(*c), GFP_ATOMIC); |
163 | if (!c) | 175 | if (!c) |
@@ -180,7 +192,7 @@ clusterip_config_init(const struct ipt_clusterip_tgt_info *i, __be32 ip, | |||
180 | /* create proc dir entry */ | 192 | /* create proc dir entry */ |
181 | sprintf(buffer, "%pI4", &ip); | 193 | sprintf(buffer, "%pI4", &ip); |
182 | c->pde = proc_create_data(buffer, S_IWUSR|S_IRUSR, | 194 | c->pde = proc_create_data(buffer, S_IWUSR|S_IRUSR, |
183 | clusterip_procdir, | 195 | cn->procdir, |
184 | &clusterip_proc_fops, c); | 196 | &clusterip_proc_fops, c); |
185 | if (!c->pde) { | 197 | if (!c->pde) { |
186 | kfree(c); | 198 | kfree(c); |
@@ -189,9 +201,9 @@ clusterip_config_init(const struct ipt_clusterip_tgt_info *i, __be32 ip, | |||
189 | } | 201 | } |
190 | #endif | 202 | #endif |
191 | 203 | ||
192 | spin_lock_bh(&clusterip_lock); | 204 | spin_lock_bh(&cn->lock); |
193 | list_add_rcu(&c->list, &clusterip_configs); | 205 | list_add_rcu(&c->list, &cn->configs); |
194 | spin_unlock_bh(&clusterip_lock); | 206 | spin_unlock_bh(&cn->lock); |
195 | 207 | ||
196 | return c; | 208 | return c; |
197 | } | 209 | } |
@@ -370,7 +382,7 @@ static int clusterip_tg_check(const struct xt_tgchk_param *par) | |||
370 | 382 | ||
371 | /* FIXME: further sanity checks */ | 383 | /* FIXME: further sanity checks */ |
372 | 384 | ||
373 | config = clusterip_config_find_get(e->ip.dst.s_addr, 1); | 385 | config = clusterip_config_find_get(par->net, e->ip.dst.s_addr, 1); |
374 | if (!config) { | 386 | if (!config) { |
375 | if (!(cipinfo->flags & CLUSTERIP_FLAG_NEW)) { | 387 | if (!(cipinfo->flags & CLUSTERIP_FLAG_NEW)) { |
376 | pr_info("no config found for %pI4, need 'new'\n", | 388 | pr_info("no config found for %pI4, need 'new'\n", |
@@ -384,7 +396,7 @@ static int clusterip_tg_check(const struct xt_tgchk_param *par) | |||
384 | return -EINVAL; | 396 | return -EINVAL; |
385 | } | 397 | } |
386 | 398 | ||
387 | dev = dev_get_by_name(&init_net, e->ip.iniface); | 399 | dev = dev_get_by_name(par->net, e->ip.iniface); |
388 | if (!dev) { | 400 | if (!dev) { |
389 | pr_info("no such interface %s\n", | 401 | pr_info("no such interface %s\n", |
390 | e->ip.iniface); | 402 | e->ip.iniface); |
@@ -492,6 +504,7 @@ arp_mangle(const struct nf_hook_ops *ops, | |||
492 | struct arphdr *arp = arp_hdr(skb); | 504 | struct arphdr *arp = arp_hdr(skb); |
493 | struct arp_payload *payload; | 505 | struct arp_payload *payload; |
494 | struct clusterip_config *c; | 506 | struct clusterip_config *c; |
507 | struct net *net = dev_net(in ? in : out); | ||
495 | 508 | ||
496 | /* we don't care about non-ethernet and non-ipv4 ARP */ | 509 | /* we don't care about non-ethernet and non-ipv4 ARP */ |
497 | if (arp->ar_hrd != htons(ARPHRD_ETHER) || | 510 | if (arp->ar_hrd != htons(ARPHRD_ETHER) || |
@@ -508,7 +521,7 @@ arp_mangle(const struct nf_hook_ops *ops, | |||
508 | 521 | ||
509 | /* if there is no clusterip configuration for the arp reply's | 522 | /* if there is no clusterip configuration for the arp reply's |
510 | * source ip, we don't want to mangle it */ | 523 | * source ip, we don't want to mangle it */ |
511 | c = clusterip_config_find_get(payload->src_ip, 0); | 524 | c = clusterip_config_find_get(net, payload->src_ip, 0); |
512 | if (!c) | 525 | if (!c) |
513 | return NF_ACCEPT; | 526 | return NF_ACCEPT; |
514 | 527 | ||
@@ -698,48 +711,75 @@ static const struct file_operations clusterip_proc_fops = { | |||
698 | 711 | ||
699 | #endif /* CONFIG_PROC_FS */ | 712 | #endif /* CONFIG_PROC_FS */ |
700 | 713 | ||
714 | static int clusterip_net_init(struct net *net) | ||
715 | { | ||
716 | struct clusterip_net *cn = net_generic(net, clusterip_net_id); | ||
717 | |||
718 | INIT_LIST_HEAD(&cn->configs); | ||
719 | |||
720 | spin_lock_init(&cn->lock); | ||
721 | |||
722 | #ifdef CONFIG_PROC_FS | ||
723 | cn->procdir = proc_mkdir("ipt_CLUSTERIP", net->proc_net); | ||
724 | if (!cn->procdir) { | ||
725 | pr_err("Unable to proc dir entry\n"); | ||
726 | return -ENOMEM; | ||
727 | } | ||
728 | #endif /* CONFIG_PROC_FS */ | ||
729 | |||
730 | return 0; | ||
731 | } | ||
732 | |||
733 | static void clusterip_net_exit(struct net *net) | ||
734 | { | ||
735 | #ifdef CONFIG_PROC_FS | ||
736 | struct clusterip_net *cn = net_generic(net, clusterip_net_id); | ||
737 | proc_remove(cn->procdir); | ||
738 | #endif | ||
739 | } | ||
740 | |||
741 | static struct pernet_operations clusterip_net_ops = { | ||
742 | .init = clusterip_net_init, | ||
743 | .exit = clusterip_net_exit, | ||
744 | .id = &clusterip_net_id, | ||
745 | .size = sizeof(struct clusterip_net), | ||
746 | }; | ||
747 | |||
701 | static int __init clusterip_tg_init(void) | 748 | static int __init clusterip_tg_init(void) |
702 | { | 749 | { |
703 | int ret; | 750 | int ret; |
704 | 751 | ||
705 | ret = xt_register_target(&clusterip_tg_reg); | 752 | ret = register_pernet_subsys(&clusterip_net_ops); |
706 | if (ret < 0) | 753 | if (ret < 0) |
707 | return ret; | 754 | return ret; |
708 | 755 | ||
756 | ret = xt_register_target(&clusterip_tg_reg); | ||
757 | if (ret < 0) | ||
758 | goto cleanup_subsys; | ||
759 | |||
709 | ret = nf_register_hook(&cip_arp_ops); | 760 | ret = nf_register_hook(&cip_arp_ops); |
710 | if (ret < 0) | 761 | if (ret < 0) |
711 | goto cleanup_target; | 762 | goto cleanup_target; |
712 | 763 | ||
713 | #ifdef CONFIG_PROC_FS | ||
714 | clusterip_procdir = proc_mkdir("ipt_CLUSTERIP", init_net.proc_net); | ||
715 | if (!clusterip_procdir) { | ||
716 | pr_err("Unable to proc dir entry\n"); | ||
717 | ret = -ENOMEM; | ||
718 | goto cleanup_hook; | ||
719 | } | ||
720 | #endif /* CONFIG_PROC_FS */ | ||
721 | |||
722 | pr_info("ClusterIP Version %s loaded successfully\n", | 764 | pr_info("ClusterIP Version %s loaded successfully\n", |
723 | CLUSTERIP_VERSION); | 765 | CLUSTERIP_VERSION); |
766 | |||
724 | return 0; | 767 | return 0; |
725 | 768 | ||
726 | #ifdef CONFIG_PROC_FS | ||
727 | cleanup_hook: | ||
728 | nf_unregister_hook(&cip_arp_ops); | ||
729 | #endif /* CONFIG_PROC_FS */ | ||
730 | cleanup_target: | 769 | cleanup_target: |
731 | xt_unregister_target(&clusterip_tg_reg); | 770 | xt_unregister_target(&clusterip_tg_reg); |
771 | cleanup_subsys: | ||
772 | unregister_pernet_subsys(&clusterip_net_ops); | ||
732 | return ret; | 773 | return ret; |
733 | } | 774 | } |
734 | 775 | ||
735 | static void __exit clusterip_tg_exit(void) | 776 | static void __exit clusterip_tg_exit(void) |
736 | { | 777 | { |
737 | pr_info("ClusterIP Version %s unloading\n", CLUSTERIP_VERSION); | 778 | pr_info("ClusterIP Version %s unloading\n", CLUSTERIP_VERSION); |
738 | #ifdef CONFIG_PROC_FS | 779 | |
739 | proc_remove(clusterip_procdir); | ||
740 | #endif | ||
741 | nf_unregister_hook(&cip_arp_ops); | 780 | nf_unregister_hook(&cip_arp_ops); |
742 | xt_unregister_target(&clusterip_tg_reg); | 781 | xt_unregister_target(&clusterip_tg_reg); |
782 | unregister_pernet_subsys(&clusterip_net_ops); | ||
743 | 783 | ||
744 | /* Wait for completion of call_rcu_bh()'s (clusterip_config_rcu_free) */ | 784 | /* Wait for completion of call_rcu_bh()'s (clusterip_config_rcu_free) */ |
745 | rcu_barrier_bh(); | 785 | rcu_barrier_bh(); |