| bridge-nf-0.0.10-dev-pre2.001-against-2.5.42 - 20 October |
| |
| --- linux-2.5.42/include/linux/netfilter_bridge.h Sun Oct 20 21:27:40 2002 |
| +++ linux-2.5.42-brnf/include/linux/netfilter_bridge.h Sun Oct 20 21:20:53 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,9 @@ |
| #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 |
| |
| enum nf_br_hook_priorities { |
| NF_BR_PRI_FIRST = INT_MIN, |
| @@ -39,10 +38,24 @@ |
| NF_BR_PRI_LAST = INT_MAX, |
| }; |
| |
| -/* 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 Sun Oct 20 21:27:40 2002 |
| +++ linux-2.5.42-brnf/include/linux/skbuff.h Sun Oct 20 15:33:11 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.c Sun Oct 20 21:27:40 2002 |
| +++ linux-2.5.42-brnf/net/bridge/br.c Sun Oct 20 21:24:42 2002 |
| @@ -45,8 +45,10 @@ |
| { |
| printk(KERN_INFO "NET4: Ethernet Bridge 008 for NET4.0\n"); |
| |
| +#ifdef CONFIG_NETFILTER |
| if (br_netfilter_init()) |
| return 1; |
| +#endif |
| br_handle_frame_hook = br_handle_frame; |
| br_ioctl_hook = br_ioctl_deviceless_stub; |
| #if defined(CONFIG_ATM_LANE) || defined(CONFIG_ATM_LANE_MODULE) |
| @@ -65,7 +67,9 @@ |
| |
| static void __exit br_deinit(void) |
| { |
| +#ifdef CONFIG_NETFILTER |
| br_netfilter_fini(); |
| +#endif |
| unregister_netdevice_notifier(&br_device_notifier); |
| br_call_ioctl_atomic(__br_clear_ioctl_hook); |
| |
| --- linux-2.5.42/net/bridge/br_forward.c Sun Oct 20 21:27:40 2002 |
| +++ linux-2.5.42-brnf/net/bridge/br_forward.c Sun Oct 20 21:22:52 2002 |
| @@ -32,7 +32,12 @@ |
| |
| int br_dev_queue_push_xmit(struct sk_buff *skb) |
| { |
| +#ifdef CONFIG_NETFILTER |
| + if (skb->nf_bridge) |
| + memcpy(skb->data - 16, skb->nf_bridge->hh, 16); |
| +#endif |
| skb_push(skb, ETH_HLEN); |
| + |
| dev_queue_xmit(skb); |
| |
| return 0; |
| --- linux-2.5.42/net/core/netfilter.c Sun Oct 20 21:27:40 2002 |
| +++ linux-2.5.42-brnf/net/core/netfilter.c Sun Oct 20 15:33:11 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 Sun Oct 20 21:27:40 2002 |
| +++ linux-2.5.42-brnf/net/core/skbuff.c Sun Oct 20 15:33:11 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/ip_output.c Sun Oct 20 21:27:40 2002 |
| +++ linux-2.5.42-brnf/net/ipv4/ip_output.c Sun Oct 20 16:15:47 2002 |
| @@ -75,7 +75,6 @@ |
| #include <net/inetpeer.h> |
| #include <linux/igmp.h> |
| #include <linux/netfilter_ipv4.h> |
| -#include <linux/netfilter_bridge.h> |
| #include <linux/mroute.h> |
| #include <linux/netlink.h> |
| |
| @@ -895,6 +894,8 @@ |
| /* Connection association is same as pre-frag packet */ |
| skb2->nfct = skb->nfct; |
| nf_conntrack_get(skb2->nfct); |
| + skb2->nf_bridge = skb->nf_bridge; |
| + nf_bridge_get(skb2->nf_bridge); |
| #ifdef CONFIG_NETFILTER_DEBUG |
| skb2->nf_debug = skb->nf_debug; |
| #endif |
| @@ -909,18 +910,6 @@ |
| iph->tot_len = htons(len + hlen); |
| |
| ip_send_check(iph); |
| - |
| - /* |
| - * Fragments with a bridge device destination need |
| - * to get the Ethernet header copied here, as |
| - * br_dev_queue_push_xmit() can't do this. |
| - * See net/bridge/br_netfilter.c |
| - */ |
| - |
| -#ifdef CONFIG_NETFILTER |
| - if (skb->brnfmask & BRNF_COPY_HEADER) |
| - memcpy(skb2->data - 16, skb->data - 16, 16); |
| -#endif |
| |
| err = output(skb2); |
| if (err) |
| --- linux-2.5.42/net/ipv4/netfilter/ip_tables.c Sun Oct 20 21:27:40 2002 |
| +++ linux-2.5.42-brnf/net/ipv4/netfilter/ip_tables.c Sun Oct 20 15:33:11 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 Sun Oct 20 21:27:40 2002 |
| +++ linux-2.5.42-brnf/net/ipv4/netfilter/ipt_LOG.c Sun Oct 20 15:33:11 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 Sun Oct 20 21:27:40 2002 |
| +++ linux-2.5.42-brnf/net/bridge/br_netfilter.c Sun Oct 20 21:37:15 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; |
| @@ -251,13 +253,15 @@ |
| #ifdef CONFIG_NETFILTER_DEBUG |
| skb->nf_debug ^= (1 << NF_IP_PRE_ROUTING); |
| #endif |
| + if ((nf_bridge = nf_bridge_alloc(skb)) == NULL) |
| + return NF_DROP; |
| |
| 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 +306,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 +336,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 +345,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 +383,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 +404,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 +415,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 +439,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 +467,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 +500,10 @@ |
| */ |
| 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_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)) |
| + return NF_DROP; |
| + |
| + 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; |