Skip to contentSkip to conversation

: Fix invalid tcp/udp checksums within NATed icmp errors

PATCH In review Patrick McHardy 1 participant 1 message Nov 15, 2004

Subsystems (2)
lore
Share & tools
lore
#0 lore raw

PATCH 8/9 : Fix invalid tcp/udp checksums within NATed icmp errors

Fix invalid tcp/udp checksums within NATed icmp errors. The IP used for checksum adjustment is always the address of the outer IP header.

# This is a BitKeeper generated diff -Nru style patch. #
# ChangeSet
# 2004/11/13 17:01:15+01:00 [email protected]
# [NETFILTER]: Fix invalid tcp/udp checksums within NATed icmp errors
#
# Signed-off-by: Patrick McHardy <[email protected]>
#

# net/ipv4/netfilter/ip_nat_proto_unknown.c
#   2004/11/13 17:01:07+01:00 [email protected] +1 -1
#   [NETFILTER]: Fix invalid tcp/udp checksums within NATed icmp errors
#   
#   Signed-off-by: Patrick McHardy <[email protected]>
# 
# net/ipv4/netfilter/ip_nat_proto_udp.c
#   2004/11/13 17:01:07+01:00 [email protected] +5 -3
#   [NETFILTER]: Fix invalid tcp/udp checksums within NATed icmp errors
#   
#   Signed-off-by: Patrick McHardy <[email protected]>
# 
# net/ipv4/netfilter/ip_nat_proto_tcp.c
#   2004/11/13 17:01:07+01:00 [email protected] +5 -3
#   [NETFILTER]: Fix invalid tcp/udp checksums within NATed icmp errors
#   
#   Signed-off-by: Patrick McHardy <[email protected]>
# 
# net/ipv4/netfilter/ip_nat_proto_icmp.c
#   2004/11/13 17:01:07+01:00 [email protected] +3 -1
#   [NETFILTER]: Fix invalid tcp/udp checksums within NATed icmp errors
#   
#   Signed-off-by: Patrick McHardy <[email protected]>
# 
# net/ipv4/netfilter/ip_nat_core.c
#   2004/11/13 17:01:07+01:00 [email protected] +1 -1
#   [NETFILTER]: Fix invalid tcp/udp checksums within NATed icmp errors
#   
#   Signed-off-by: Patrick McHardy <[email protected]>
# 
# include/linux/netfilter_ipv4/ip_nat_protocol.h
#   2004/11/13 17:01:07+01:00 [email protected] +1 -1
#   [NETFILTER]: Fix invalid tcp/udp checksums within NATed icmp errors
#   
#   Signed-off-by: Patrick McHardy <[email protected]>
# 
diff -Nru a/include/linux/netfilter_ipv4/ip_nat_protocol.h b/include/linux/netfilter_ipv4/ip_nat_protocol.h
--- a/include/linux/netfilter_ipv4/ip_nat_protocol.h	2004-11-15 22:07:44 +01:00
+++ b/include/linux/netfilter_ipv4/ip_nat_protocol.h	2004-11-15 22:07:44 +01:00
@@ -18,7 +18,7 @@
 	/* Do a packet translation according to the ip_nat_proto_manip
 	 * and manip type.  Return true if succeeded. */
 	int (*manip_pkt)(struct sk_buff **pskb,
-			 unsigned int hdroff,
+			 unsigned int iphdroff,
 			 const struct ip_conntrack_manip *manip,
 			 enum ip_nat_manip_type maniptype);
net/ipv4/netfilter/ip_nat_core.c +1 -1
diff -Nru a/net/ipv4/netfilter/ip_nat_core.c b/net/ipv4/netfilter/ip_nat_core.c
@@ -687,7 +687,7 @@
 	iph = (void *)(*pskb)->data + iphdroff;
 
 	/* Manipulate protcol part. */
-	if (!ip_nat_find_proto(proto)->manip_pkt(pskb, iphdroff + iph->ihl*4,
+	if (!ip_nat_find_proto(proto)->manip_pkt(pskb, iphdroff,
 	                                         manip, maniptype))
 		return 0;
 
net/ipv4/netfilter/ip_nat_proto_icmp.c +3 -1
diff -Nru a/net/ipv4/netfilter/ip_nat_proto_icmp.c b/net/ipv4/netfilter/ip_nat_proto_icmp.c
@@ -53,11 +53,13 @@
 
 static int
 icmp_manip_pkt(struct sk_buff **pskb,
-	       unsigned int hdroff,
+	       unsigned int iphdroff,
 	       const struct ip_conntrack_manip *manip,
 	       enum ip_nat_manip_type maniptype)
 {
+	struct iphdr *iph = (struct iphdr *)((*pskb)->data + iphdroff);
 	struct icmphdr *hdr;
+	unsigned int hdroff = iphdroff + iph->ihl*4;
 
 	if (!skb_ip_make_writable(pskb, hdroff + sizeof(*hdr)))
 		return 0;
net/ipv4/netfilter/ip_nat_proto_tcp.c +5 -3
diff -Nru a/net/ipv4/netfilter/ip_nat_proto_tcp.c b/net/ipv4/netfilter/ip_nat_proto_tcp.c
@@ -84,11 +84,13 @@
 
 static int
 tcp_manip_pkt(struct sk_buff **pskb,
-	      unsigned int hdroff,
+	      unsigned int iphdroff,
 	      const struct ip_conntrack_manip *manip,
 	      enum ip_nat_manip_type maniptype)
 {
+	struct iphdr *iph = (struct iphdr *)((*pskb)->data + iphdroff);
 	struct tcphdr *hdr;
+	unsigned int hdroff = iphdroff + iph->ihl*4;
 	u_int32_t oldip;
 	u_int16_t *portptr, oldport;
 	int hdrsize = 8; /* TCP connection tracking guarantees this much */
@@ -106,11 +108,11 @@
 
 	if (maniptype == IP_NAT_MANIP_SRC) {
 		/* Get rid of src ip and src pt */
-		oldip = (*pskb)->nh.iph->saddr;
+		oldip = iph->saddr;
 		portptr = &hdr->source;
 	} else {
 		/* Get rid of dst ip and dst pt */
-		oldip = (*pskb)->nh.iph->daddr;
+		oldip = iph->daddr;
 		portptr = &hdr->dest;
 	}
 
net/ipv4/netfilter/ip_nat_proto_udp.c +5 -3
diff -Nru a/net/ipv4/netfilter/ip_nat_proto_udp.c b/net/ipv4/netfilter/ip_nat_proto_udp.c
@@ -83,11 +83,13 @@
 
 static int
 udp_manip_pkt(struct sk_buff **pskb,
-	      unsigned int hdroff,
+	      unsigned int iphdroff,
 	      const struct ip_conntrack_manip *manip,
 	      enum ip_nat_manip_type maniptype)
 {
+	struct iphdr *iph = (struct iphdr *)((*pskb)->data + iphdroff);
 	struct udphdr *hdr;
+	unsigned int hdroff = iphdroff + iph->ihl*4;
 	u_int32_t oldip;
 	u_int16_t *portptr;
 
@@ -97,11 +99,11 @@
 	hdr = (void *)(*pskb)->data + hdroff;
 	if (maniptype == IP_NAT_MANIP_SRC) {
 		/* Get rid of src ip and src pt */
-		oldip = (*pskb)->nh.iph->saddr;
+		oldip = iph->saddr;
 		portptr = &hdr->source;
 	} else {
 		/* Get rid of dst ip and dst pt */
-		oldip = (*pskb)->nh.iph->daddr;
+		oldip = iph->daddr;
 		portptr = &hdr->dest;
 	}
 	if (hdr->check) /* 0 is a special case meaning no checksum */
net/ipv4/netfilter/ip_nat_proto_unknown.c +1 -1
diff -Nru a/net/ipv4/netfilter/ip_nat_proto_unknown.c b/net/ipv4/netfilter/ip_nat_proto_unknown.c
@@ -39,7 +39,7 @@
 
 static int
 unknown_manip_pkt(struct sk_buff **pskb,
-		  unsigned int hdroff,
+		  unsigned int iphdroff,
 		  const struct ip_conntrack_manip *manip,
 		  enum ip_nat_manip_type maniptype)
 {