All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH][RFC][resend] xfrm: Fix up TCP/UDP checksum for UDP encap. ESP4 packets in transport mode
@ 2009-04-27  8:30 Christophe Saout
  2009-04-27  9:24 ` David Miller
  0 siblings, 1 reply; 2+ messages in thread
From: Christophe Saout @ 2009-04-27  8:30 UTC (permalink / raw)
  To: netdev

Hello,

I was happily running an transport-mode IPSEC connection where I was
running NAT at one endpoint.  This means that decrypted packets can be
forwarded to another machine, as opposed to being delivered to a local
application.

Later I was forced to encapsulate the IPSEC traffic into UDP because I
had no choice but pass through a NAT device.  Then, unfortunately,
things started to break.  The machine that would receive the answer to a
TCP/SYN packet from the gateway box (that decrypts the packed and then
forwards it) discarded the packets because of a wrong TCP checksum.

I checked the kernel code - esp4.c is just setting CHECKSUM_UNNECESSARY
on these packets, so that they are accepted by local applications.
However, when the packages leaves the machine via a NIC, the packet
still carries the broken checksum.  I checked the RFC on the issue and
one of the suggestions is to recompute the checksum for carried TCP/UDP
packets.

I have a working (but possibly inelegant version), which I am proposing.
I know there are obvious things that can be improved, but I'm just
posting it here for discussion.  Also, I'm not sure my skb handling is
fully correct.

diff --git a/net/ipv4/esp4.c b/net/ipv4/esp4.c
index 18bb383..b0eba8f 100644
--- a/net/ipv4/esp4.c
+++ b/net/ipv4/esp4.c
@@ -295,6 +295,33 @@ static int esp_input_done2(struct sk_buff *skb, int err)
 			skb->ip_summed = CHECKSUM_UNNECESSARY;
 	}
 
+	if (x->encap && x->props.mode == XFRM_MODE_TRANSPORT &&
+	    (nexthdr[1] == IPPROTO_TCP || nexthdr[1] == IPPROTO_UDP)) {
+		int datalen, thlen;
+		unsigned char *th;
+
+		if (nexthdr[1] == IPPROTO_TCP) {
+			thlen = sizeof(struct tcphdr);
+			skb->csum_offset = offsetof(struct tcphdr, check);
+		} else {
+			thlen = sizeof(struct udphdr);
+			skb->csum_offset = offsetof(struct udphdr, check);
+		}
+
+		datalen = skb->len - alen - padlen - 2 - hlen;
+		if (datalen < 0 || !pskb_may_pull(skb, hlen + thlen))
+			goto out;
+
+		iph = ip_hdr(skb);
+		th = skb_transport_header(skb) + hlen;
+
+		skb->ip_summed = CHECKSUM_PARTIAL;
+		skb->csum_start = th - skb->head;
+		*(__u16 *)(th + skb->csum_offset) =
+				~csum_tcpudp_magic(iph->saddr, iph->daddr,
+				                   datalen, nexthdr[1], 0);
+	}
+
 	pskb_trim(skb, skb->len - alen - padlen - 2);
 	__skb_pull(skb, hlen);
 	skb_set_transport_header(skb, -ihl);



^ permalink raw reply related	[flat|nested] 2+ messages in thread

* Re: [PATCH][RFC][resend] xfrm: Fix up TCP/UDP checksum for UDP encap. ESP4 packets in transport mode
  2009-04-27  8:30 [PATCH][RFC][resend] xfrm: Fix up TCP/UDP checksum for UDP encap. ESP4 packets in transport mode Christophe Saout
@ 2009-04-27  9:24 ` David Miller
  0 siblings, 0 replies; 2+ messages in thread
From: David Miller @ 2009-04-27  9:24 UTC (permalink / raw)
  To: christophe; +Cc: netdev


We all saw your patch the first time.

Silence doesn't mean lack of reception, please be patient.

Most of us are simply backlogged with the patches that
don't require feedback, that's why we haven't gotten to
your's yet.

^ permalink raw reply	[flat|nested] 2+ messages in thread

end of thread, other threads:[~2009-04-27  9:24 UTC | newest]

Thread overview: 2+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2009-04-27  8:30 [PATCH][RFC][resend] xfrm: Fix up TCP/UDP checksum for UDP encap. ESP4 packets in transport mode Christophe Saout
2009-04-27  9:24 ` David Miller

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.