blob: 4d296d78027220c80eb7e217a0a1dac4c6b35b61 [file] [log] [blame]
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;