From 222a09d7edba6e8e8e610f3b92a692bcf59615f7 Mon Sep 17 00:00:00 2001 From: Patrick McHardy Date: Sat, 12 Feb 2011 15:38:59 -0500 Subject: [PATCH] [NETFILTER]: bridge: fix double POSTROUTING hook invocations kernel.org commits 81d9ddae856678c45297550e9353c8a5a7fd6438 2948d2ebbb98747b912ac6d0c864b4d02be8a6f5 --- .../linux/linux-2.6/net/bridge/br_netfilter.c | 21 +++++++++++++++------ 1 file changed, 15 insertions(+), 6 deletions(-) diff --git a/release/src-rt/linux/linux-2.6/net/bridge/br_netfilter.c b/release/src-rt/linux/linux-2.6/net/bridge/br_netfilter.c index 280c72feaf..1a8d02790a 100644 --- a/release/src-rt/linux/linux-2.6/net/bridge/br_netfilter.c +++ b/release/src-rt/linux/linux-2.6/net/bridge/br_netfilter.c @@ -264,8 +264,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. * @@ -302,12 +303,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; } @@ -800,6 +806,9 @@ static unsigned int br_nf_post_routing(unsigned int hook, struct sk_buff **pskb, if (!nf_bridge) return NF_ACCEPT; + if (!(nf_bridge->mask & (BRNF_BRIDGED | BRNF_BRIDGED_DNAT))) + return NF_ACCEPT; + if (!realoutdev) return NF_DROP; -- 2.11.4.GIT