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 #include +#include /* 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 #include #include -#include #include #include @@ -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;