Patchwork bridge: Pseudo-header required for the checksum of ICMPv6

login
register
mail settings
Submitter Yan, Zheng
Date Aug. 24, 2011, 8:54 a.m.
Message ID <4E54BC49.6090506@intel.com>
Download mbox | patch
Permalink /patch/111276/
State Accepted
Delegated to: David Miller
Headers show

Comments

Yan, Zheng - Aug. 24, 2011, 8:54 a.m.
Checksum of ICMPv6 is not properly computed because the pseudo header is not used.
Thus, the MLD packet gets dropped by the bridge.

Signed-off-by: Zheng Yan <zheng.z.yan@intel.com>
Reported-by: Ang Way Chuang <wcang@sfc.wide.ad.jp>

---
--
To unsubscribe from this list: send the line "unsubscribe netdev" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
David Miller - Aug. 25, 2011, 12:51 a.m.
From: "Yan, Zheng" <zheng.z.yan@intel.com>
Date: Wed, 24 Aug 2011 16:54:33 +0800

> Checksum of ICMPv6 is not properly computed because the pseudo header is not used.
> Thus, the MLD packet gets dropped by the bridge.
> 
> Signed-off-by: Zheng Yan <zheng.z.yan@intel.com>
> Reported-by: Ang Way Chuang <wcang@sfc.wide.ad.jp>

Applied.
--
To unsubscribe from this list: send the line "unsubscribe netdev" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

Patch

diff --git a/net/bridge/br_multicast.c b/net/bridge/br_multicast.c
index 2d85ca7..22d2d1a 100644
--- a/net/bridge/br_multicast.c
+++ b/net/bridge/br_multicast.c
@@ -1520,16 +1520,23 @@  static int br_multicast_ipv6_rcv(struct net_bridge *br,
 		err = pskb_trim_rcsum(skb2, len);
 		if (err)
 			goto out;
+		err = -EINVAL;
 	}
 
+	ip6h = ipv6_hdr(skb2);
+
 	switch (skb2->ip_summed) {
 	case CHECKSUM_COMPLETE:
-		if (!csum_fold(skb2->csum))
+		if (!csum_ipv6_magic(&ip6h->saddr, &ip6h->daddr, skb2->len,
+					IPPROTO_ICMPV6, skb2->csum))
 			break;
 		/*FALLTHROUGH*/
 	case CHECKSUM_NONE:
-		skb2->csum = 0;
-		if (skb_checksum_complete(skb2))
+		skb2->csum = ~csum_unfold(csum_ipv6_magic(&ip6h->saddr,
+							&ip6h->daddr,
+							skb2->len,
+							IPPROTO_ICMPV6, 0));
+		if (__skb_checksum_complete(skb2))
 			goto out;
 	}