|
@@ -169,7 +169,25 @@ static void send_reset(struct net *net, struct sk_buff *oldskb)
|
|
|
|
|
|
nf_ct_attach(nskb, oldskb);
|
|
|
|
|
|
- ip6_local_out(nskb);
|
|
|
+#ifdef CONFIG_BRIDGE_NETFILTER
|
|
|
+ /* If we use ip6_local_out for bridged traffic, the MAC source on
|
|
|
+ * the RST will be ours, instead of the destination's. This confuses
|
|
|
+ * some routers/firewalls, and they drop the packet. So we need to
|
|
|
+ * build the eth header using the original destination's MAC as the
|
|
|
+ * source, and send the RST packet directly.
|
|
|
+ */
|
|
|
+ if (oldskb->nf_bridge) {
|
|
|
+ struct ethhdr *oeth = eth_hdr(oldskb);
|
|
|
+ nskb->dev = oldskb->nf_bridge->physindev;
|
|
|
+ nskb->protocol = htons(ETH_P_IPV6);
|
|
|
+ ip6h->payload_len = htons(sizeof(struct tcphdr));
|
|
|
+ if (dev_hard_header(nskb, nskb->dev, ntohs(nskb->protocol),
|
|
|
+ oeth->h_source, oeth->h_dest, nskb->len) < 0)
|
|
|
+ return;
|
|
|
+ dev_queue_xmit(nskb);
|
|
|
+ } else
|
|
|
+#endif
|
|
|
+ ip6_local_out(nskb);
|
|
|
}
|
|
|
|
|
|
static inline void
|