summaryrefslogtreecommitdiffstats
path: root/net
diff options
context:
space:
mode:
Diffstat (limited to 'net')
-rw-r--r--net/bridge/br_netfilter.c18
1 files changed, 12 insertions, 6 deletions
diff --git a/net/bridge/br_netfilter.c b/net/bridge/br_netfilter.c
index c1757c79dfb..5d8b939eded 100644
--- a/net/bridge/br_netfilter.c
+++ b/net/bridge/br_netfilter.c
@@ -247,8 +247,9 @@ static void __br_dnat_complain(void)
* Let us first consider the case that ip_route_input() succeeds:
*
* If skb->dst->dev equals the logical bridge device the packet
- * came in on, we can consider this bridging. We then call
- * skb->dst->output() which will make the packet enter br_nf_local_out()
+ * came in on, we can consider this bridging. The packet is passed
+ * through the neighbour output function to build a new destination
+ * MAC address, which will make the packet enter br_nf_local_out()
* not much later. In that function it is assured that the iptables
* FORWARD chain is traversed for the packet.
*
@@ -285,12 +286,17 @@ static int br_nf_pre_routing_finish_bridge(struct sk_buff *skb)
skb->nf_bridge->mask ^= BRNF_NF_BRIDGE_PREROUTING;
skb->dev = bridge_parent(skb->dev);
- if (!skb->dev)
- kfree_skb(skb);
- else {
+ if (skb->dev) {
+ struct dst_entry *dst = skb->dst;
+
nf_bridge_pull_encap_header(skb);
- skb->dst->output(skb);
+
+ if (dst->hh)
+ return neigh_hh_output(dst->hh, skb);
+ else if (dst->neighbour)
+ return dst->neighbour->output(skb);
}
+ kfree_skb(skb);
return 0;
}