summary refs log tree commit diff
path: root/net
diff options
context:
space:
mode:
authorStephen Hemminger <shemminger@osdl.org>2006-01-06 13:13:29 -0800
committerDavid S. Miller <davem@davemloft.net>2006-01-06 13:13:29 -0800
commitee02b3a613a692a40e0f48a25d9d60cc751ebbe5 (patch)
tree51c034027c96a213ac53cd831dee4cb24fd0ed17 /net
parenta20a8554796bc4e28879beabd0db4bf3ce77b686 (diff)
downloadlinux-ee02b3a613a692a40e0f48a25d9d60cc751ebbe5.tar.gz
[BRIDGE] netfilter: vlan + hw checksum = bug?
It looks like the bridge netfilter code does not correctly update
the hardware checksum after popping off the VLAN header.

This is by inspection, I have *not* tested this.
To test you would need to set up a filtering bridge with vlans
and a device the does hardware receive checksum (skge, or sungem)

Signed-off-by: Stephen Hemminger <shemminger@osdl.org>
Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'net')
-rw-r--r--net/bridge/br_netfilter.c13
1 files changed, 9 insertions, 4 deletions
diff --git a/net/bridge/br_netfilter.c b/net/bridge/br_netfilter.c
index 223f8270daee..7cac3fb9f809 100644
--- a/net/bridge/br_netfilter.c
+++ b/net/bridge/br_netfilter.c
@@ -394,8 +394,9 @@ inhdr_error:
  * target in particular.  Save the original destination IP
  * address to be able to detect DNAT afterwards. */
 static unsigned int br_nf_pre_routing(unsigned int hook, struct sk_buff **pskb,
-   const struct net_device *in, const struct net_device *out,
-   int (*okfn)(struct sk_buff *))
+				      const struct net_device *in,
+				      const struct net_device *out,
+				      int (*okfn)(struct sk_buff *))
 {
 	struct iphdr *iph;
 	__u32 len;
@@ -412,8 +413,10 @@ static unsigned int br_nf_pre_routing(unsigned int hook, struct sk_buff **pskb,
 			goto out;
 
 		if (skb->protocol == __constant_htons(ETH_P_8021Q)) {
+			u8 *vhdr = skb->data;
 			skb_pull(skb, VLAN_HLEN);
-			(skb)->nh.raw += VLAN_HLEN;
+			skb_postpull_rcsum(skb, vhdr, VLAN_HLEN);
+			skb->nh.raw += VLAN_HLEN;
 		}
 		return br_nf_pre_routing_ipv6(hook, skb, in, out, okfn);
 	}
@@ -429,8 +432,10 @@ static unsigned int br_nf_pre_routing(unsigned int hook, struct sk_buff **pskb,
 		goto out;
 
 	if (skb->protocol == __constant_htons(ETH_P_8021Q)) {
+		u8 *vhdr = skb->data;
 		skb_pull(skb, VLAN_HLEN);
-		(skb)->nh.raw += VLAN_HLEN;
+		skb_postpull_rcsum(skb, vhdr, VLAN_HLEN);
+		skb->nh.raw += VLAN_HLEN;
 	}
 
 	if (!pskb_may_pull(skb, sizeof(struct iphdr)))