Browse Source

xfrm: Fix pmtu discovery for local generated packets.

Commit 044a832a777 ("xfrm: Fix local error reporting crash
with interfamily tunnels") moved the setting of skb->protocol
behind the last access of the inner mode family to fix an
interfamily crash. Unfortunately now skb->protocol might not
be set at all, so we fail dispatch to the inner address family.
As a reault, the local error handler is not called and the
mtu value is not reported back to userspace.

We fix this by setting skb->protocol on message size errors
before we call xfrm_local_error.

Fixes: 044a832a7779c ("xfrm: Fix local error reporting crash with interfamily tunnels")
Signed-off-by: Steffen Klassert <steffen.klassert@secunet.com>
Steffen Klassert 9 years ago
parent
commit
ca064bd893
2 changed files with 3 additions and 0 deletions
  1. 2 0
      net/ipv4/xfrm4_output.c
  2. 1 0
      net/ipv6/xfrm6_output.c

+ 2 - 0
net/ipv4/xfrm4_output.c

@@ -30,6 +30,8 @@ static int xfrm4_tunnel_check_size(struct sk_buff *skb)
 
 
 	mtu = dst_mtu(skb_dst(skb));
 	mtu = dst_mtu(skb_dst(skb));
 	if (skb->len > mtu) {
 	if (skb->len > mtu) {
+		skb->protocol = htons(ETH_P_IP);
+
 		if (skb->sk)
 		if (skb->sk)
 			xfrm_local_error(skb, mtu);
 			xfrm_local_error(skb, mtu);
 		else
 		else

+ 1 - 0
net/ipv6/xfrm6_output.c

@@ -79,6 +79,7 @@ static int xfrm6_tunnel_check_size(struct sk_buff *skb)
 
 
 	if (!skb->ignore_df && skb->len > mtu) {
 	if (!skb->ignore_df && skb->len > mtu) {
 		skb->dev = dst->dev;
 		skb->dev = dst->dev;
+		skb->protocol = htons(ETH_P_IPV6);
 
 
 		if (xfrm6_local_dontfrag(skb))
 		if (xfrm6_local_dontfrag(skb))
 			xfrm6_local_rxpmtu(skb, mtu);
 			xfrm6_local_rxpmtu(skb, mtu);