aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJulian Anastasov <ja@ssi.bg>2010-10-17 09:14:31 -0400
committerSimon Horman <horms@verge.net.au>2010-10-21 04:49:39 -0400
commit5bc9068e9d962ca6b8bec3f0eb6f60ab4dee1d04 (patch)
treefaa2317aa2a175a1dff24ab62447aeddda342b8e
parentd86bef73b4a24e59e7c1f896a72bbf38430ac2c6 (diff)
ipvs: fix CHECKSUM_PARTIAL for TCP, UDP
Fix CHECKSUM_PARTIAL handling. Tested for IPv4 TCP, UDP not tested because it needs network card with HW CSUM support. May be fixes problem where IPVS can not be used in virtual boxes. Problem appears with DNAT to local address when the local stack sends reply in CHECKSUM_PARTIAL mode. Fix tcp_dnat_handler and udp_dnat_handler to provide vaddr and daddr in right order (old and new IP) when calling tcp_partial_csum_update/udp_partial_csum_update (CHECKSUM_PARTIAL). Signed-off-by: Julian Anastasov <ja@ssi.bg> Signed-off-by: Simon Horman <horms@verge.net.au>
-rw-r--r--net/netfilter/ipvs/ip_vs_proto_tcp.c10
-rw-r--r--net/netfilter/ipvs/ip_vs_proto_udp.c10
2 files changed, 10 insertions, 10 deletions
diff --git a/net/netfilter/ipvs/ip_vs_proto_tcp.c b/net/netfilter/ipvs/ip_vs_proto_tcp.c
index 282d24de8592..318d011036db 100644
--- a/net/netfilter/ipvs/ip_vs_proto_tcp.c
+++ b/net/netfilter/ipvs/ip_vs_proto_tcp.c
@@ -101,15 +101,15 @@ tcp_partial_csum_update(int af, struct tcphdr *tcph,
101#ifdef CONFIG_IP_VS_IPV6 101#ifdef CONFIG_IP_VS_IPV6
102 if (af == AF_INET6) 102 if (af == AF_INET6)
103 tcph->check = 103 tcph->check =
104 csum_fold(ip_vs_check_diff16(oldip->ip6, newip->ip6, 104 ~csum_fold(ip_vs_check_diff16(oldip->ip6, newip->ip6,
105 ip_vs_check_diff2(oldlen, newlen, 105 ip_vs_check_diff2(oldlen, newlen,
106 ~csum_unfold(tcph->check)))); 106 csum_unfold(tcph->check))));
107 else 107 else
108#endif 108#endif
109 tcph->check = 109 tcph->check =
110 csum_fold(ip_vs_check_diff4(oldip->ip, newip->ip, 110 ~csum_fold(ip_vs_check_diff4(oldip->ip, newip->ip,
111 ip_vs_check_diff2(oldlen, newlen, 111 ip_vs_check_diff2(oldlen, newlen,
112 ~csum_unfold(tcph->check)))); 112 csum_unfold(tcph->check))));
113} 113}
114 114
115 115
@@ -223,7 +223,7 @@ tcp_dnat_handler(struct sk_buff *skb,
223 * Adjust TCP checksums 223 * Adjust TCP checksums
224 */ 224 */
225 if (skb->ip_summed == CHECKSUM_PARTIAL) { 225 if (skb->ip_summed == CHECKSUM_PARTIAL) {
226 tcp_partial_csum_update(cp->af, tcph, &cp->daddr, &cp->vaddr, 226 tcp_partial_csum_update(cp->af, tcph, &cp->vaddr, &cp->daddr,
227 htons(oldlen), 227 htons(oldlen),
228 htons(skb->len - tcphoff)); 228 htons(skb->len - tcphoff));
229 } else if (!cp->app) { 229 } else if (!cp->app) {
diff --git a/net/netfilter/ipvs/ip_vs_proto_udp.c b/net/netfilter/ipvs/ip_vs_proto_udp.c
index 8553231b5d41..f9290893bd93 100644
--- a/net/netfilter/ipvs/ip_vs_proto_udp.c
+++ b/net/netfilter/ipvs/ip_vs_proto_udp.c
@@ -102,15 +102,15 @@ udp_partial_csum_update(int af, struct udphdr *uhdr,
102#ifdef CONFIG_IP_VS_IPV6 102#ifdef CONFIG_IP_VS_IPV6
103 if (af == AF_INET6) 103 if (af == AF_INET6)
104 uhdr->check = 104 uhdr->check =
105 csum_fold(ip_vs_check_diff16(oldip->ip6, newip->ip6, 105 ~csum_fold(ip_vs_check_diff16(oldip->ip6, newip->ip6,
106 ip_vs_check_diff2(oldlen, newlen, 106 ip_vs_check_diff2(oldlen, newlen,
107 ~csum_unfold(uhdr->check)))); 107 csum_unfold(uhdr->check))));
108 else 108 else
109#endif 109#endif
110 uhdr->check = 110 uhdr->check =
111 csum_fold(ip_vs_check_diff4(oldip->ip, newip->ip, 111 ~csum_fold(ip_vs_check_diff4(oldip->ip, newip->ip,
112 ip_vs_check_diff2(oldlen, newlen, 112 ip_vs_check_diff2(oldlen, newlen,
113 ~csum_unfold(uhdr->check)))); 113 csum_unfold(uhdr->check))));
114} 114}
115 115
116 116
@@ -229,7 +229,7 @@ udp_dnat_handler(struct sk_buff *skb,
229 * Adjust UDP checksums 229 * Adjust UDP checksums
230 */ 230 */
231 if (skb->ip_summed == CHECKSUM_PARTIAL) { 231 if (skb->ip_summed == CHECKSUM_PARTIAL) {
232 udp_partial_csum_update(cp->af, udph, &cp->daddr, &cp->vaddr, 232 udp_partial_csum_update(cp->af, udph, &cp->vaddr, &cp->daddr,
233 htons(oldlen), 233 htons(oldlen),
234 htons(skb->len - udphoff)); 234 htons(skb->len - udphoff));
235 } else if (!cp->app && (udph->check != 0)) { 235 } else if (!cp->app && (udph->check != 0)) {