Commit ee02b3a6 authored by Stephen Hemminger's avatar Stephen Hemminger Committed by David S. Miller

[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: default avatarStephen Hemminger <shemminger@osdl.org>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent a20a8554
...@@ -394,8 +394,9 @@ static unsigned int br_nf_pre_routing_ipv6(unsigned int hook, ...@@ -394,8 +394,9 @@ static unsigned int br_nf_pre_routing_ipv6(unsigned int hook,
* target in particular. Save the original destination IP * target in particular. Save the original destination IP
* address to be able to detect DNAT afterwards. */ * address to be able to detect DNAT afterwards. */
static unsigned int br_nf_pre_routing(unsigned int hook, struct sk_buff **pskb, static unsigned int br_nf_pre_routing(unsigned int hook, struct sk_buff **pskb,
const struct net_device *in, const struct net_device *out, const struct net_device *in,
int (*okfn)(struct sk_buff *)) const struct net_device *out,
int (*okfn)(struct sk_buff *))
{ {
struct iphdr *iph; struct iphdr *iph;
__u32 len; __u32 len;
...@@ -412,8 +413,10 @@ static unsigned int br_nf_pre_routing(unsigned int hook, struct sk_buff **pskb, ...@@ -412,8 +413,10 @@ static unsigned int br_nf_pre_routing(unsigned int hook, struct sk_buff **pskb,
goto out; goto out;
if (skb->protocol == __constant_htons(ETH_P_8021Q)) { if (skb->protocol == __constant_htons(ETH_P_8021Q)) {
u8 *vhdr = skb->data;
skb_pull(skb, VLAN_HLEN); 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); 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, ...@@ -429,8 +432,10 @@ static unsigned int br_nf_pre_routing(unsigned int hook, struct sk_buff **pskb,
goto out; goto out;
if (skb->protocol == __constant_htons(ETH_P_8021Q)) { if (skb->protocol == __constant_htons(ETH_P_8021Q)) {
u8 *vhdr = skb->data;
skb_pull(skb, VLAN_HLEN); 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))) if (!pskb_may_pull(skb, sizeof(struct iphdr)))
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment