Commit 2831834d authored by Bart De Schuymer's avatar Bart De Schuymer Committed by David S. Miller

[BRIDGE]: Fix loopback over bridge port.

When sending a broadcast from a Linux bridge over a bridge port,
net/ipv4/ip_output.c::ip_dev_loopback_xmit() will send the packet back
to the bridge port. Currently, the bridge code will intercept this
loopback packet and try to bridge it. This is not right, the loopback
packet doesn't even have an Ethernet header. This loopback packet is
intended for the bridge port and should not be stolen by the bridge code.
The patch below fixes this by adding a check in __handle_bridge().
It also changes br_netfilter.c by only doing the paranoid checks of
br_nf_post_routing() when CONFIG_NETFILTER_DEBUG is set. I think the
loopback fix will get rid of any skbuffs matching those paranoid checks.

The patch also introduces/removes some whitespace in br_netfilter.c.
parent 0bbe34be
......@@ -356,6 +356,7 @@ static unsigned int br_nf_local_in(unsigned int hook, struct sk_buff **pskb,
return NF_ACCEPT;
}
/* PF_BRIDGE/FORWARD *************************************************/
static int br_nf_forward_finish(struct sk_buff *skb)
{
......@@ -466,6 +467,7 @@ static unsigned int br_nf_forward_arp(unsigned int hook, struct sk_buff **pskb,
return NF_STOLEN;
}
/* PF_BRIDGE/LOCAL_OUT ***********************************************/
static int br_nf_local_out_finish(struct sk_buff *skb)
{
......@@ -531,9 +533,7 @@ static unsigned int br_nf_local_out(unsigned int hook, struct sk_buff **pskb,
return NF_ACCEPT;
nf_bridge = skb->nf_bridge;
nf_bridge->physoutdev = skb->dev;
realindev = nf_bridge->physindev;
/* Bridged, take PF_BRIDGE/FORWARD.
......@@ -601,18 +601,15 @@ static unsigned int br_nf_post_routing(unsigned int hook, struct sk_buff **pskb,
struct vlan_ethhdr *hdr = (struct vlan_ethhdr *)(skb->mac.ethernet);
struct net_device *realoutdev = bridge_parent(skb->dev);
/* Be very paranoid. Must be a device driver bug. */
#ifdef CONFIG_NETFILTER_DEBUG
/* Be very paranoid. This probably won't happen anymore, but let's
* keep the check just to be sure... */
if (skb->mac.raw < skb->head || skb->mac.raw + ETH_HLEN > skb->data) {
printk(KERN_CRIT "br_netfilter: Argh!! br_nf_post_routing: "
"bad mac.raw pointer.");
if (skb->dev != NULL) {
printk("[%s]", skb->dev->name);
if (has_bridge_parent(skb->dev))
printk("[%s]", bridge_parent(skb->dev)->name);
}
printk(" head:%p, raw:%p\n", skb->head, skb->mac.raw);
return NF_ACCEPT;
goto print_error;
}
#endif
#ifdef CONFIG_SYSCTL
if (!nf_bridge)
......@@ -622,13 +619,16 @@ static unsigned int br_nf_post_routing(unsigned int hook, struct sk_buff **pskb,
if (skb->protocol != __constant_htons(ETH_P_IP) && !IS_VLAN_IP)
return NF_ACCEPT;
#ifdef CONFIG_NETFILTER_DEBUG
/* Sometimes we get packets with NULL ->dst here (for example,
* running a dhcp client daemon triggers this).
* running a dhcp client daemon triggers this). This should now
* be fixed, but let's keep the check around.
*/
if (skb->dst == NULL)
return NF_ACCEPT;
if (skb->dst == NULL) {
printk(KERN_CRIT "br_netfilter: skb->dst == NULL.");
goto print_error;
}
#ifdef CONFIG_NETFILTER_DEBUG
skb->nf_debug ^= (1 << NF_IP_POST_ROUTING);
#endif
......@@ -655,6 +655,18 @@ static unsigned int br_nf_post_routing(unsigned int hook, struct sk_buff **pskb,
realoutdev, br_dev_queue_push_xmit);
return NF_STOLEN;
#ifdef CONFIG_NETFILTER_DEBUG
print_error:
if (skb->dev != NULL) {
printk("[%s]", skb->dev->name);
if (has_bridge_parent(skb->dev))
printk("[%s]", bridge_parent(skb->dev)->name);
}
printk(" head:%p, raw:%p, data:%p\n", skb->head, skb->mac.raw,
skb->data);
return NF_ACCEPT;
#endif
}
......
......@@ -1543,7 +1543,7 @@ static inline int __handle_bridge(struct sk_buff *skb,
struct packet_type **pt_prev, int *ret)
{
#if defined(CONFIG_BRIDGE) || defined(CONFIG_BRIDGE_MODULE)
if (skb->dev->br_port) {
if (skb->dev->br_port && skb->pkt_type != PACKET_LOOPBACK) {
*ret = handle_bridge(skb, *pt_prev);
if (br_handle_frame_hook(skb) == 0)
return 1;
......
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