summaryrefslogtreecommitdiffstats
path: root/br-nf-bds/patches/bridge-nf-0.0.10-dev-pre2.001-against-2.5.42.diff
diff options
context:
space:
mode:
Diffstat (limited to 'br-nf-bds/patches/bridge-nf-0.0.10-dev-pre2.001-against-2.5.42.diff')
-rw-r--r--br-nf-bds/patches/bridge-nf-0.0.10-dev-pre2.001-against-2.5.42.diff555
1 files changed, 555 insertions, 0 deletions
diff --git a/br-nf-bds/patches/bridge-nf-0.0.10-dev-pre2.001-against-2.5.42.diff b/br-nf-bds/patches/bridge-nf-0.0.10-dev-pre2.001-against-2.5.42.diff
new file mode 100644
index 0000000..a3b3e5f
--- /dev/null
+++ b/br-nf-bds/patches/bridge-nf-0.0.10-dev-pre2.001-against-2.5.42.diff
@@ -0,0 +1,555 @@
+bridge-nf-0.0.10-dev-pre2.001-against-2.5.42 - 19 October
+
+--- linux-2.5.42/include/linux/netfilter_bridge.h Sat Oct 19 12:51:50 2002
++++ linux-2.5.42-brnf/include/linux/netfilter_bridge.h Sat Oct 19 12:48:58 2002
+@@ -6,6 +6,7 @@
+
+ #include <linux/config.h>
+ #include <linux/netfilter.h>
++#include <asm/atomic.h>
+
+ /* Bridge Hooks */
+ /* After promisc drops, checksum checks. */
+@@ -22,11 +23,10 @@
+ #define NF_BR_BROUTING 5
+ #define NF_BR_NUMHOOKS 6
+
+-/* Masks for skb->brnfmask */
+ #define BRNF_PKT_TYPE 0x01
+ #define BRNF_BRIDGED_DNAT 0x02
+-#define BRNF_COPY_HEADER 0x04
+-#define BRNF_DONT_TAKE_PARENT 0x08
++#define BRNF_DONT_TAKE_PARENT 0x04
++#define BRNF_COPY_HEADER 0x08
+
+ enum nf_br_hook_priorities {
+ NF_BR_PRI_FIRST = INT_MIN,
+@@ -40,9 +40,24 @@
+ };
+
+ /* Used in br_netfilter.c */
++static inline
++struct nf_bridge_info *nf_bridge_alloc(struct sk_buff *skb)
++{
++ struct nf_bridge_info **nf_bridge = &(skb->nf_bridge);
++
++ if ((*nf_bridge = kmalloc(sizeof(**nf_bridge), GFP_ATOMIC)) != NULL) {
++ atomic_set(&(*nf_bridge)->use, 1);
++ (*nf_bridge)->mask = 0;
++ (*nf_bridge)->physindev = (*nf_bridge)->physoutdev = NULL;
++ }
++
++ return *nf_bridge;
++}
++
+ struct bridge_skb_cb {
+ union {
+ __u32 ipv4;
+ } daddr;
+ };
++
+ #endif
+--- linux-2.5.42/include/linux/skbuff.h Sat Oct 19 12:51:50 2002
++++ linux-2.5.42-brnf/include/linux/skbuff.h Wed Oct 16 20:39:52 2002
+@@ -96,6 +96,14 @@
+ struct nf_ct_info {
+ struct nf_conntrack *master;
+ };
++
++struct nf_bridge_info {
++ atomic_t use;
++ struct net_device *physindev;
++ struct net_device *physoutdev;
++ unsigned int mask;
++ unsigned long hh[16 / sizeof(unsigned long)];
++};
+ #endif
+
+ struct sk_buff_head {
+@@ -140,8 +148,6 @@
+ * @sk: Socket we are owned by
+ * @stamp: Time we arrived
+ * @dev: Device we arrived on/are leaving by
+- * @physindev: Physical device we arrived on - see br_netfilter.c
+- * @physoutdev: Phsical device we will leave by - see br_netfilter.c
+ * @h: Transport layer header
+ * @nh: Network layer header
+ * @mac: Link layer header
+@@ -168,7 +174,7 @@
+ * @nfcache: Cache info
+ * @nfct: Associated connection, if any
+ * @nf_debug: Netfilter debugging
+- * @brnfmask: Info about a bridged frame - see br_netfilter.c
++ * @nf_bridge: Saved data about a bridged frame - see br_netfilter.c
+ * @tc_index: Traffic control index
+ */
+
+@@ -181,8 +187,6 @@
+ struct sock *sk;
+ struct timeval stamp;
+ struct net_device *dev;
+- struct net_device *physindev;
+- struct net_device *physoutdev;
+
+ union {
+ struct tcphdr *th;
+@@ -241,7 +245,7 @@
+ #ifdef CONFIG_NETFILTER_DEBUG
+ unsigned int nf_debug;
+ #endif
+- unsigned int brnfmask;
++ struct nf_bridge_info *nf_bridge;
+ #endif /* CONFIG_NETFILTER */
+ #if defined(CONFIG_HIPPI)
+ union {
+@@ -1142,6 +1146,17 @@
+ {
+ if (nfct)
+ atomic_inc(&nfct->master->use);
++}
++
++static inline void nf_bridge_put(struct nf_bridge_info *nf_bridge)
++{
++ if (nf_bridge && atomic_dec_and_test(&nf_bridge->use))
++ kfree(nf_bridge);
++}
++static inline void nf_bridge_get(struct nf_bridge_info *nf_bridge)
++{
++ if (nf_bridge)
++ atomic_inc(&nf_bridge->use);
+ }
+ #endif
+
+--- linux-2.5.42/net/bridge/br_forward.c Sat Oct 19 12:51:50 2002
++++ linux-2.5.42-brnf/net/bridge/br_forward.c Sat Oct 19 12:23:23 2002
+@@ -33,6 +33,12 @@
+ int br_dev_queue_push_xmit(struct sk_buff *skb)
+ {
+ skb_push(skb, ETH_HLEN);
++
++#ifdef CONFIG_NETFILTER
++ if (skb->nf_bridge->mask & BRNF_COPY_HEADER)
++ memcpy(skb->data - 16, skb->nf_bridge->hh, 16);
++#endif
++
+ dev_queue_xmit(skb);
+
+ return 0;
+@@ -52,7 +58,13 @@
+ #ifdef CONFIG_NETFILTER_DEBUG
+ skb->nf_debug = 0;
+ #endif
+- NF_HOOK(PF_BRIDGE, NF_BR_LOCAL_OUT, skb, NULL, skb->dev,
++#ifdef CONFIG_NETFILTER
++ /* Used by br_netfilter.c */
++ if (!skb->nf_bridge && nf_bridge_alloc(skb) == NULL)
++ kfree_skb(skb);
++ else
++#endif
++ NF_HOOK(PF_BRIDGE, NF_BR_LOCAL_OUT, skb, NULL, skb->dev,
+ br_forward_finish);
+ }
+
+--- linux-2.5.42/net/bridge/br_input.c Sat Oct 19 12:51:50 2002
++++ linux-2.5.42-brnf/net/bridge/br_input.c Sat Oct 19 12:16:10 2002
+@@ -154,8 +154,14 @@
+ return -1;
+ }
+
+- NF_HOOK(PF_BRIDGE, NF_BR_PRE_ROUTING, skb, skb->dev, NULL,
+- br_handle_frame_finish);
++#ifdef CONFIG_NETFILTER
++ /* Used by br_netfilter.c */
++ if (nf_bridge_alloc(skb) == NULL)
++ kfree_skb(skb);
++ else
++#endif
++ NF_HOOK(PF_BRIDGE, NF_BR_PRE_ROUTING, skb, skb->dev,
++ NULL, br_handle_frame_finish);
+ read_unlock(&br->lock);
+ return 0;
+ }
+--- linux-2.5.42/net/core/netfilter.c Sat Oct 19 12:51:50 2002
++++ linux-2.5.42-brnf/net/core/netfilter.c Sat Oct 19 12:36:18 2002
+@@ -418,8 +418,8 @@
+ {
+ int status;
+ struct nf_info *info;
+- struct net_device *physindev;
+- struct net_device *physoutdev;
++ struct net_device *physindev = NULL;
++ struct net_device *physoutdev = NULL;
+
+ if (!queue_handler[pf].outfn) {
+ kfree_skb(skb);
+@@ -442,8 +442,12 @@
+ if (indev) dev_hold(indev);
+ if (outdev) dev_hold(outdev);
+
+- if ((physindev = skb->physindev)) dev_hold(physindev);
+- if ((physoutdev = skb->physoutdev)) dev_hold(physoutdev);
++ if (skb->nf_bridge) {
++ physindev = skb->nf_bridge->physindev;
++ if (physindev) dev_hold(physindev);
++ physoutdev = skb->nf_bridge->physoutdev;
++ if (physoutdev) dev_hold(physoutdev);
++ }
+
+ status = queue_handler[pf].outfn(skb, info, queue_handler[pf].data);
+ if (status < 0) {
+--- linux-2.5.42/net/core/skbuff.c Sat Oct 19 12:51:50 2002
++++ linux-2.5.42-brnf/net/core/skbuff.c Wed Oct 16 21:16:25 2002
+@@ -234,8 +234,6 @@
+ skb->sk = NULL;
+ skb->stamp.tv_sec = 0; /* No idea about time */
+ skb->dev = NULL;
+- skb->physindev = NULL;
+- skb->physoutdev = NULL;
+ skb->dst = NULL;
+ memset(skb->cb, 0, sizeof(skb->cb));
+ skb->pkt_type = PACKET_HOST; /* Default type */
+@@ -250,7 +248,7 @@
+ #ifdef CONFIG_NETFILTER_DEBUG
+ skb->nf_debug = 0;
+ #endif
+- skb->brnfmask = 0;
++ skb->nf_bridge = NULL;
+ #endif
+ #ifdef CONFIG_NET_SCHED
+ skb->tc_index = 0;
+@@ -330,6 +328,7 @@
+ }
+ #ifdef CONFIG_NETFILTER
+ nf_conntrack_put(skb->nfct);
++ nf_bridge_put(skb->nf_bridge);
+ #endif
+ skb_headerinit(skb, NULL, 0); /* clean state */
+ kfree_skbmem(skb);
+@@ -366,8 +365,6 @@
+ n->sk = NULL;
+ C(stamp);
+ C(dev);
+- C(physindev);
+- C(physoutdev);
+ C(h);
+ C(nh);
+ C(mac);
+@@ -397,7 +394,7 @@
+ #ifdef CONFIG_NETFILTER_DEBUG
+ C(nf_debug);
+ #endif
+- C(brnfmask);
++ C(nf_bridge);
+ #endif /*CONFIG_NETFILTER*/
+ #if defined(CONFIG_HIPPI)
+ C(private);
+@@ -410,6 +407,7 @@
+ skb->cloned = 1;
+ #ifdef CONFIG_NETFILTER
+ nf_conntrack_get(skb->nfct);
++ nf_bridge_get(skb->nf_bridge);
+ #endif
+ return n;
+ }
+@@ -424,8 +422,6 @@
+ new->list = NULL;
+ new->sk = NULL;
+ new->dev = old->dev;
+- new->physindev = old->physindev;
+- new->physoutdev = old->physoutdev;
+ new->priority = old->priority;
+ new->protocol = old->protocol;
+ new->dst = dst_clone(old->dst);
+@@ -446,7 +442,8 @@
+ #ifdef CONFIG_NETFILTER_DEBUG
+ new->nf_debug = old->nf_debug;
+ #endif
+- new->brnfmask = old->brnfmask;
++ new->nf_bridge = old->nf_bridge;
++ nf_bridge_get(new->nf_bridge);
+ #endif
+ #ifdef CONFIG_NET_SCHED
+ new->tc_index = old->tc_index;
+--- linux-2.5.42/net/ipv4/netfilter/ip_tables.c Sat Oct 19 12:51:50 2002
++++ linux-2.5.42-brnf/net/ipv4/netfilter/ip_tables.c Thu Oct 17 22:39:25 2002
+@@ -292,8 +292,15 @@
+ datalen = (*pskb)->len - ip->ihl * 4;
+ indev = in ? in->name : nulldevname;
+ outdev = out ? out->name : nulldevname;
+- physindev = (*pskb)->physindev ? (*pskb)->physindev->name : nulldevname;
+- physoutdev = (*pskb)->physoutdev ? (*pskb)->physoutdev->name : nulldevname;
++ if ((*pskb)->nf_bridge) {
++ physindev = (*pskb)->nf_bridge->physindev ?
++ (*pskb)->nf_bridge->physindev->name : nulldevname;
++ physoutdev = (*pskb)->nf_bridge->physoutdev ?
++ (*pskb)->nf_bridge->physoutdev->name : nulldevname;
++ } else {
++ physindev = nulldevname;
++ physoutdev = nulldevname;
++ }
+
+ /* We handle fragments by dealing with the first fragment as
+ * if it was a normal packet. All other fragments are treated
+--- linux-2.5.42/net/ipv4/netfilter/ipt_LOG.c Sat Oct 19 12:51:50 2002
++++ linux-2.5.42-brnf/net/ipv4/netfilter/ipt_LOG.c Wed Oct 16 21:54:13 2002
+@@ -286,11 +286,16 @@
+ spin_lock_bh(&log_lock);
+ printk(level_string);
+ printk("%sIN=%s ", loginfo->prefix, in ? in->name : "");
+- if ((*pskb)->physindev && in != (*pskb)->physindev)
+- printk("PHYSIN=%s ", (*pskb)->physindev->name);
+- printk("OUT=%s ", out ? out->name : "");
+- if ((*pskb)->physoutdev && out != (*pskb)->physoutdev)
+- printk("PHYSOUT=%s ", (*pskb)->physoutdev->name);
++ if ((*pskb)->nf_bridge) {
++ struct net_device *physindev = (*pskb)->nf_bridge->physindev;
++ struct net_device *physoutdev = (*pskb)->nf_bridge->physoutdev;
++
++ if (physindev && in != physindev)
++ printk("PHYSIN=%s ", physindev->name);
++ printk("OUT=%s ", out ? out->name : "");
++ if (physoutdev && out != physoutdev)
++ printk("PHYSOUT=%s ", physoutdev->name);
++ }
+
+ if (in && !out) {
+ /* MAC logging for input chain only. */
+--- linux-2.5.42/net/bridge/br_netfilter.c Sat Oct 19 12:51:50 2002
++++ linux-2.5.42-brnf/net/bridge/br_netfilter.c Sat Oct 19 12:25:10 2002
+@@ -133,7 +133,7 @@
+
+ if (skb->pkt_type == PACKET_OTHERHOST) {
+ skb->pkt_type = PACKET_HOST;
+- skb->brnfmask |= BRNF_PKT_TYPE;
++ skb->nf_bridge->mask |= BRNF_PKT_TYPE;
+ }
+
+ skb->dev = bridge_parent(skb->dev);
+@@ -145,14 +145,15 @@
+ {
+ struct net_device *dev = skb->dev;
+ struct iphdr *iph = skb->nh.iph;
++ struct nf_bridge_info *nf_bridge = skb->nf_bridge;
+
+ #ifdef CONFIG_NETFILTER_DEBUG
+ skb->nf_debug ^= (1 << NF_BR_PRE_ROUTING);
+ #endif
+
+- if (skb->brnfmask & BRNF_PKT_TYPE) {
++ if (nf_bridge->mask & BRNF_PKT_TYPE) {
+ skb->pkt_type = PACKET_OTHERHOST;
+- skb->brnfmask ^= BRNF_PKT_TYPE;
++ nf_bridge->mask ^= BRNF_PKT_TYPE;
+ }
+
+ if (dnat_took_place(skb)) {
+@@ -179,8 +180,8 @@
+ /* Tell br_nf_local_out this is a
+ * bridged frame
+ */
+- skb->brnfmask |= BRNF_BRIDGED_DNAT;
+- skb->dev = skb->physindev;
++ nf_bridge->mask |= BRNF_BRIDGED_DNAT;
++ skb->dev = nf_bridge->physindev;
+ clear_cb(skb);
+ NF_HOOK_THRESH(PF_BRIDGE, NF_BR_PRE_ROUTING,
+ skb, skb->dev, NULL,
+@@ -197,7 +198,7 @@
+ }
+
+ clear_cb(skb);
+- skb->dev = skb->physindev;
++ skb->dev = nf_bridge->physindev;
+ NF_HOOK_THRESH(PF_BRIDGE, NF_BR_PRE_ROUTING, skb, skb->dev, NULL,
+ br_handle_frame_finish, 1);
+
+@@ -217,6 +218,7 @@
+ struct iphdr *iph;
+ __u32 len;
+ struct sk_buff *skb;
++ struct nf_bridge_info *nf_bridge;
+
+ if ((*pskb)->protocol != __constant_htons(ETH_P_IP))
+ return NF_ACCEPT;
+@@ -252,12 +254,13 @@
+ skb->nf_debug ^= (1 << NF_IP_PRE_ROUTING);
+ #endif
+
++ nf_bridge = skb->nf_bridge;
+ if (skb->pkt_type == PACKET_OTHERHOST) {
+ skb->pkt_type = PACKET_HOST;
+- skb->brnfmask |= BRNF_PKT_TYPE;
++ nf_bridge->mask |= BRNF_PKT_TYPE;
+ }
+
+- skb->physindev = skb->dev;
++ nf_bridge->physindev = skb->dev;
+ skb->dev = bridge_parent(skb->dev);
+ store_orig_dstaddr(skb);
+
+@@ -302,16 +305,18 @@
+ /* PF_BRIDGE/FORWARD *************************************************/
+ static int br_nf_forward_finish(struct sk_buff *skb)
+ {
++ struct nf_bridge_info *nf_bridge = skb->nf_bridge;
++
+ #ifdef CONFIG_NETFILTER_DEBUG
+ skb->nf_debug ^= (1 << NF_BR_FORWARD);
+ #endif
+
+- if (skb->brnfmask & BRNF_PKT_TYPE) {
++ if (nf_bridge->mask & BRNF_PKT_TYPE) {
+ skb->pkt_type = PACKET_OTHERHOST;
+- skb->brnfmask ^= BRNF_PKT_TYPE;
++ nf_bridge->mask ^= BRNF_PKT_TYPE;
+ }
+
+- NF_HOOK_THRESH(PF_BRIDGE, NF_BR_FORWARD, skb, skb->physindev,
++ NF_HOOK_THRESH(PF_BRIDGE, NF_BR_FORWARD, skb, nf_bridge->physindev,
+ skb->dev, br_forward_finish, 1);
+
+ return 0;
+@@ -330,6 +335,7 @@
+ int (*okfn)(struct sk_buff *))
+ {
+ struct sk_buff *skb = *pskb;
++ struct nf_bridge_info *nf_bridge;
+
+ if (skb->protocol != __constant_htons(ETH_P_IP))
+ return NF_ACCEPT;
+@@ -338,14 +344,15 @@
+ skb->nf_debug ^= (1 << NF_BR_FORWARD);
+ #endif
+
++ nf_bridge = skb->nf_bridge;
+ if (skb->pkt_type == PACKET_OTHERHOST) {
+ skb->pkt_type = PACKET_HOST;
+- skb->brnfmask |= BRNF_PKT_TYPE;
++ nf_bridge->mask |= BRNF_PKT_TYPE;
+ }
+
+- skb->physoutdev = skb->dev;
++ nf_bridge->physoutdev = skb->dev;
+
+- NF_HOOK(PF_INET, NF_IP_FORWARD, skb, bridge_parent(skb->physindev),
++ NF_HOOK(PF_INET, NF_IP_FORWARD, skb, bridge_parent(nf_bridge->physindev),
+ bridge_parent(skb->dev), br_nf_forward_finish);
+
+ return NF_STOLEN;
+@@ -375,18 +382,18 @@
+ * functions, and give them back later, when we have determined the real
+ * output device. This is done in here.
+ *
+- * If (skb->brnfmask & BRNF_BRIDGED_DNAT) then the packet is bridged
++ * If (nf_bridge->mask & BRNF_BRIDGED_DNAT) then the packet is bridged
+ * and we fake the PF_BRIDGE/FORWARD hook. The function br_nf_forward()
+ * will then fake the PF_INET/FORWARD hook. br_nf_local_out() has priority
+ * NF_BR_PRI_FIRST, so no relevant PF_BRIDGE/INPUT functions have been nor
+ * will be executed.
+- * Otherwise, if skb->physindev is NULL, the bridge-nf code never touched
++ * Otherwise, if nf_bridge->physindev is NULL, the bridge-nf code never touched
+ * this packet before, and so the packet was locally originated. We fake
+ * the PF_INET/LOCAL_OUT hook.
+- * Finally, if skb->physindev isn't NULL, then the packet was IP routed,
++ * Finally, if nf_bridge->physindev isn't NULL, then the packet was IP routed,
+ * so we fake the PF_INET/FORWARD hook. ipv4_sabotage_out() makes sure
+ * even routed packets that didn't arrive on a bridge interface have their
+- * skb->physindev set.
++ * nf_bridge->physindev set.
+ */
+
+ static unsigned int br_nf_local_out(unsigned int hook, struct sk_buff **pskb,
+@@ -396,6 +403,7 @@
+ int (*okfn)(struct sk_buff *skb);
+ struct net_device *realindev;
+ struct sk_buff *skb = *pskb;
++ struct nf_bridge_info *nf_bridge;
+
+ if (skb->protocol != __constant_htons(ETH_P_IP))
+ return NF_ACCEPT;
+@@ -406,19 +414,20 @@
+ if (skb->dst == NULL)
+ return NF_ACCEPT;
+
+- skb->physoutdev = skb->dev;
++ nf_bridge = skb->nf_bridge;
++ nf_bridge->physoutdev = skb->dev;
+
+- realindev = skb->physindev;
++ realindev = nf_bridge->physindev;
+
+ /* Bridged, take PF_BRIDGE/FORWARD.
+ * (see big note in front of br_nf_pre_routing_finish)
+ */
+- if (skb->brnfmask & BRNF_BRIDGED_DNAT) {
++ if (nf_bridge->mask & BRNF_BRIDGED_DNAT) {
+ okfn = br_forward_finish;
+
+- if (skb->brnfmask & BRNF_PKT_TYPE) {
++ if (nf_bridge->mask & BRNF_PKT_TYPE) {
+ skb->pkt_type = PACKET_OTHERHOST;
+- skb->brnfmask ^= BRNF_PKT_TYPE;
++ nf_bridge->mask ^= BRNF_PKT_TYPE;
+ }
+
+ NF_HOOK(PF_BRIDGE, NF_BR_FORWARD, skb, realindev,
+@@ -429,7 +438,7 @@
+ * generated traffic hasn't.
+ */
+ if (realindev != NULL) {
+- if (((skb->brnfmask & BRNF_DONT_TAKE_PARENT) == 0) &&
++ if (((nf_bridge->mask & BRNF_DONT_TAKE_PARENT) == 0) &&
+ has_bridge_parent(realindev))
+ realindev = bridge_parent(realindev);
+
+@@ -457,6 +466,7 @@
+ int (*okfn)(struct sk_buff *))
+ {
+ struct sk_buff *skb = *pskb;
++ struct nf_bridge_info *nf_bridge = (*pskb)->nf_bridge;
+
+ /* Be very paranoid. */
+ if (skb->mac.raw < skb->head || skb->mac.raw + ETH_HLEN > skb->data) {
+@@ -489,13 +499,11 @@
+ */
+ if (skb->pkt_type == PACKET_OTHERHOST) {
+ skb->pkt_type = PACKET_HOST;
+- skb->brnfmask |= BRNF_PKT_TYPE;
++ nf_bridge->mask |= BRNF_PKT_TYPE;
+ }
+
+- /* Fragmented packets need a good Ethernet header, tell this to
+- * ip_output.c::ip_fragment().
+- */
+- skb->brnfmask |= BRNF_COPY_HEADER;
++ memcpy(nf_bridge->hh, skb->data - 16, 16);
++ nf_bridge->mask |= BRNF_COPY_HEADER;
+
+ NF_HOOK(PF_INET, NF_IP_POST_ROUTING, skb, NULL,
+ bridge_parent(skb->dev), br_dev_queue_push_xmit);
+@@ -535,6 +543,12 @@
+ okfn != br_nf_local_out_finish &&
+ okfn != br_dev_queue_push_xmit) {
+ struct sk_buff *skb = *pskb;
++ struct nf_bridge_info *nf_bridge;
++
++ if (!skb->nf_bridge)
++ nf_bridge_alloc(skb);
++
++ nf_bridge = skb->nf_bridge;
+
+ /* This frame will arrive on PF_BRIDGE/LOCAL_OUT and we
+ * will need the indev then. For a brouter, the real indev
+@@ -542,9 +556,9 @@
+ * doesn't use the bridge parent of the indev by using
+ * the BRNF_DONT_TAKE_PARENT mask.
+ */
+- if (hook == NF_IP_FORWARD && skb->physindev == NULL) {
+- skb->brnfmask &= BRNF_DONT_TAKE_PARENT;
+- skb->physindev = (struct net_device *)in;
++ if (hook == NF_IP_FORWARD && nf_bridge->physindev == NULL) {
++ nf_bridge->mask &= BRNF_DONT_TAKE_PARENT;
++ nf_bridge->physindev = (struct net_device *)in;
+ }
+ okfn(skb);
+ return NF_STOLEN;