aboutsummaryrefslogtreecommitdiffstats
path: root/net/bridge
diff options
context:
space:
mode:
authorStephen Hemminger <shemminger@osdl.org>2006-01-06 16:13:29 -0500
committerDavid S. Miller <davem@davemloft.net>2006-01-06 16:13:29 -0500
commitee02b3a613a692a40e0f48a25d9d60cc751ebbe5 (patch)
tree51c034027c96a213ac53cd831dee4cb24fd0ed17 /net/bridge
parenta20a8554796bc4e28879beabd0db4bf3ce77b686 (diff)
[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/bridge')
-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:
394 * target in particular. Save the original destination IP 394 * target in particular. Save the original destination IP
395 * address to be able to detect DNAT afterwards. */ 395 * address to be able to detect DNAT afterwards. */
396static unsigned int br_nf_pre_routing(unsigned int hook, struct sk_buff **pskb, 396static unsigned int br_nf_pre_routing(unsigned int hook, struct sk_buff **pskb,
397 const struct net_device *in, const struct net_device *out, 397 const struct net_device *in,
398 int (*okfn)(struct sk_buff *)) 398 const struct net_device *out,
399 int (*okfn)(struct sk_buff *))
399{ 400{
400 struct iphdr *iph; 401 struct iphdr *iph;
401 __u32 len; 402 __u32 len;
@@ -412,8 +413,10 @@ static unsigned int br_nf_pre_routing(unsigned int hook, struct sk_buff **pskb,
412 goto out; 413 goto out;
413 414
414 if (skb->protocol == __constant_htons(ETH_P_8021Q)) { 415 if (skb->protocol == __constant_htons(ETH_P_8021Q)) {
416 u8 *vhdr = skb->data;
415 skb_pull(skb, VLAN_HLEN); 417 skb_pull(skb, VLAN_HLEN);
416 (skb)->nh.raw += VLAN_HLEN; 418 skb_postpull_rcsum(skb, vhdr, VLAN_HLEN);
419 skb->nh.raw += VLAN_HLEN;
417 } 420 }
418 return br_nf_pre_routing_ipv6(hook, skb, in, out, okfn); 421 return br_nf_pre_routing_ipv6(hook, skb, in, out, okfn);
419 } 422 }
@@ -429,8 +432,10 @@ static unsigned int br_nf_pre_routing(unsigned int hook, struct sk_buff **pskb,
429 goto out; 432 goto out;
430 433
431 if (skb->protocol == __constant_htons(ETH_P_8021Q)) { 434 if (skb->protocol == __constant_htons(ETH_P_8021Q)) {
435 u8 *vhdr = skb->data;
432 skb_pull(skb, VLAN_HLEN); 436 skb_pull(skb, VLAN_HLEN);
433 (skb)->nh.raw += VLAN_HLEN; 437 skb_postpull_rcsum(skb, vhdr, VLAN_HLEN);
438 skb->nh.raw += VLAN_HLEN;
434 } 439 }
435 440
436 if (!pskb_may_pull(skb, sizeof(struct iphdr))) 441 if (!pskb_may_pull(skb, sizeof(struct iphdr)))