Skip to contentSkip to conversation

Fix NAT for domU checksum offload

PATCH New Jon Mason 1 participant 1 message Oct 14, 2005

Subsystems (2)
lore
Share & tools
lore

Jon Mason

author
#0 lore raw

PATCH 1/1 Fix NAT for domU checksum offload

Below is a fix for the current problem of checksum offload not working in a NAT'ed network. The cause is the NAT/iptables code incorrectly modifying the TCP/UDP checksum (for the checksum offload case). The original code assumes a valid checksum, which is not the case for checksum offload packets (which has a complimented, partial checksum for the hardware to use). The fix is to compliment the new address and not compliment the old address (which is complimented in the partial checksum), and roll that with the ip_nat_cheat_check function.

There are two "versions" of the patch below. The first version is a diff to show the actual changes made to the ip_nat_proto_udp.c and ip_nat_proto_tcp.c file (as it is difficult/impossible to tell from the second patch). The second version is the one to commit to the tree (which creates 2 new files in the sparse directory).

Thanks,
Jon

net/ipv4/netfilter/ip_nat_proto_udp.c renamed from xen-unstable.hg/linux-2.6.12-xen0/net/ipv4/netfilter/ip_nat_proto_udp.c +10 -2
@@ -112,11 +112,19 @@ udp_manip_pkt(struct sk_buff **pskb,
 		newport = tuple->dst.u.udp.port;
 		portptr = &hdr->dest;
 	}
-	if (hdr->check) /* 0 is a special case meaning no checksum */
-		hdr->check = ip_nat_cheat_check(~oldip, newip,
+	
+	if (hdr->check) { /* 0 is a special case meaning no checksum */
+		if ((*pskb)->proto_csum_blank) {
+			hdr->check = ip_nat_cheat_check(oldip, ~newip, 
+					ip_nat_cheat_check(*portptr ^ 0xFFFF, 
+						newport, hdr->check));
+		} else {
+			hdr->check = ip_nat_cheat_check(~oldip, newip,
 					ip_nat_cheat_check(*portptr ^ 0xFFFF,
 							   newport,
 							   hdr->check));
+		}
+	}
 	*portptr = newport;
 	return 1;
 }
net/ipv4/netfilter/ip_nat_proto_tcp.c renamed from xen-unstable.hg/linux-2.6.12-xen0/net/ipv4/netfilter/ip_nat_proto_tcp.c +7 -1
@@ -127,10 +127,16 @@ tcp_manip_pkt(struct sk_buff **pskb,
 	if (hdrsize < sizeof(*hdr))
 		return 1;
 
-	hdr->check = ip_nat_cheat_check(~oldip, newip,
+	if ((*pskb)->proto_csum_blank) {
+		hdr->check = ip_nat_cheat_check(oldip, ~newip,
+				ip_nat_cheat_check(oldport ^ 0xFFFF,
+					newport, hdr->check));
+	} else { 
+		hdr->check = ip_nat_cheat_check(~oldip, newip,
 					ip_nat_cheat_check(oldport ^ 0xFFFF,
 							   newport,
 							   hdr->check));
+	}
 	return 1;
 }
 

# HG changeset patch
# User root@pentium4
# Node ID 51129b413cc4dd097b415d89c81965e51bfe3e0e # Parent b7a71e4db06d0235d67fef66db1e78cd2238c240

Fix NAT for domU checksum offload.

linux-2.6-xen-sparse/net/ipv4/netfilter/ip_nat_proto_tcp.c new file +184 -0

184 lines not on this page · raw message

linux-2.6-xen-sparse/net/ipv4/netfilter/ip_nat_proto_udp.c new file +173 -0

173 lines not on this page · raw message