summaryrefslogtreecommitdiffstats
path: root/net/netfilter/ipvs/ip_vs_conn.c
diff options
context:
space:
mode:
authorJulian Anastasov <ja@ssi.bg>2012-04-24 23:46:37 +0300
committerPablo Neira Ayuso <pablo@netfilter.org>2012-05-08 19:38:28 +0200
commit882a844bd5b3ffa35e059f21ee920cc113985a89 (patch)
tree62cbd6b18cf7a0b2c5aee37b3c4c26c0e62e466f /net/netfilter/ipvs/ip_vs_conn.c
parent06611f82cc0d8b957d6399f11f2799683ad002c3 (diff)
downloadlinux-stable-882a844bd5b3ffa35e059f21ee920cc113985a89.tar.gz
linux-stable-882a844bd5b3ffa35e059f21ee920cc113985a89.tar.bz2
linux-stable-882a844bd5b3ffa35e059f21ee920cc113985a89.zip
ipvs: fix ip_vs_try_bind_dest to rebind app and transmitter
Initially, when the synced connection is created we use the forwarding method provided by master but once we bind to destination it can be changed. As result, we must update the application and the transmitter. As ip_vs_try_bind_dest is called always for connections that require dest binding, there is no need to validate the cp and dest pointers. Signed-off-by: Julian Anastasov <ja@ssi.bg> Signed-off-by: Simon Horman <horms@verge.net.au>
Diffstat (limited to 'net/netfilter/ipvs/ip_vs_conn.c')
-rw-r--r--net/netfilter/ipvs/ip_vs_conn.c33
1 files changed, 26 insertions, 7 deletions
diff --git a/net/netfilter/ipvs/ip_vs_conn.c b/net/netfilter/ipvs/ip_vs_conn.c
index 1c1bb309a955..fd74f881d04a 100644
--- a/net/netfilter/ipvs/ip_vs_conn.c
+++ b/net/netfilter/ipvs/ip_vs_conn.c
@@ -613,14 +613,33 @@ struct ip_vs_dest *ip_vs_try_bind_dest(struct ip_vs_conn *cp)
{
struct ip_vs_dest *dest;
- if ((cp) && (!cp->dest)) {
- dest = ip_vs_find_dest(ip_vs_conn_net(cp), cp->af, &cp->daddr,
- cp->dport, &cp->vaddr, cp->vport,
- cp->protocol, cp->fwmark, cp->flags);
+ dest = ip_vs_find_dest(ip_vs_conn_net(cp), cp->af, &cp->daddr,
+ cp->dport, &cp->vaddr, cp->vport,
+ cp->protocol, cp->fwmark, cp->flags);
+ if (dest) {
+ struct ip_vs_proto_data *pd;
+
+ /* Applications work depending on the forwarding method
+ * but better to reassign them always when binding dest */
+ if (cp->app)
+ ip_vs_unbind_app(cp);
+
ip_vs_bind_dest(cp, dest);
- return dest;
- } else
- return NULL;
+
+ /* Update its packet transmitter */
+ cp->packet_xmit = NULL;
+#ifdef CONFIG_IP_VS_IPV6
+ if (cp->af == AF_INET6)
+ ip_vs_bind_xmit_v6(cp);
+ else
+#endif
+ ip_vs_bind_xmit(cp);
+
+ pd = ip_vs_proto_data_get(ip_vs_conn_net(cp), cp->protocol);
+ if (pd && atomic_read(&pd->appcnt))
+ ip_vs_bind_app(cp, pd->pp);
+ }
+ return dest;
}