Linux-2.6.12-rc2

Initial git repository build. I'm not bothering with the full history,
even though we have it. We can create a separate "historical" git
archive of that later if we want to, and in the meantime it's about
3.2GB when imported into git - space that would just make the early
git days unnecessarily complicated, when we don't have a lot of good
infrastructure for it.

Let it rip!
diff --git a/net/bridge/br_input.c b/net/bridge/br_input.c
new file mode 100644
index 0000000..2b1cce4
--- /dev/null
+++ b/net/bridge/br_input.c
@@ -0,0 +1,144 @@
+/*
+ *	Handle incoming frames
+ *	Linux ethernet bridge
+ *
+ *	Authors:
+ *	Lennert Buytenhek		<buytenh@gnu.org>
+ *
+ *	$Id: br_input.c,v 1.10 2001/12/24 04:50:20 davem Exp $
+ *
+ *	This program is free software; you can redistribute it and/or
+ *	modify it under the terms of the GNU General Public License
+ *	as published by the Free Software Foundation; either version
+ *	2 of the License, or (at your option) any later version.
+ */
+
+#include <linux/kernel.h>
+#include <linux/netdevice.h>
+#include <linux/etherdevice.h>
+#include <linux/netfilter_bridge.h>
+#include "br_private.h"
+
+const unsigned char bridge_ula[6] = { 0x01, 0x80, 0xc2, 0x00, 0x00, 0x00 };
+
+static int br_pass_frame_up_finish(struct sk_buff *skb)
+{
+#ifdef CONFIG_NETFILTER_DEBUG
+	skb->nf_debug = 0;
+#endif
+	netif_rx(skb);
+
+	return 0;
+}
+
+static void br_pass_frame_up(struct net_bridge *br, struct sk_buff *skb)
+{
+	struct net_device *indev;
+
+	br->statistics.rx_packets++;
+	br->statistics.rx_bytes += skb->len;
+
+	indev = skb->dev;
+	skb->dev = br->dev;
+
+	NF_HOOK(PF_BRIDGE, NF_BR_LOCAL_IN, skb, indev, NULL,
+			br_pass_frame_up_finish);
+}
+
+/* note: already called with rcu_read_lock (preempt_disabled) */
+int br_handle_frame_finish(struct sk_buff *skb)
+{
+	const unsigned char *dest = eth_hdr(skb)->h_dest;
+	struct net_bridge_port *p = skb->dev->br_port;
+	struct net_bridge *br = p->br;
+	struct net_bridge_fdb_entry *dst;
+	int passedup = 0;
+
+	if (br->dev->flags & IFF_PROMISC) {
+		struct sk_buff *skb2;
+
+		skb2 = skb_clone(skb, GFP_ATOMIC);
+		if (skb2 != NULL) {
+			passedup = 1;
+			br_pass_frame_up(br, skb2);
+		}
+	}
+
+	if (dest[0] & 1) {
+		br_flood_forward(br, skb, !passedup);
+		if (!passedup)
+			br_pass_frame_up(br, skb);
+		goto out;
+	}
+
+	dst = __br_fdb_get(br, dest);
+	if (dst != NULL && dst->is_local) {
+		if (!passedup)
+			br_pass_frame_up(br, skb);
+		else
+			kfree_skb(skb);
+		goto out;
+	}
+
+	if (dst != NULL) {
+		br_forward(dst->dst, skb);
+		goto out;
+	}
+
+	br_flood_forward(br, skb, 0);
+
+out:
+	return 0;
+}
+
+/*
+ * Called via br_handle_frame_hook.
+ * Return 0 if *pskb should be processed furthur
+ *	  1 if *pskb is handled
+ * note: already called with rcu_read_lock (preempt_disabled) 
+ */
+int br_handle_frame(struct net_bridge_port *p, struct sk_buff **pskb)
+{
+	struct sk_buff *skb = *pskb;
+	const unsigned char *dest = eth_hdr(skb)->h_dest;
+
+	if (p->state == BR_STATE_DISABLED)
+		goto err;
+
+	if (!is_valid_ether_addr(eth_hdr(skb)->h_source))
+		goto err;
+
+	if (p->state == BR_STATE_LEARNING ||
+	    p->state == BR_STATE_FORWARDING)
+		br_fdb_update(p->br, p, eth_hdr(skb)->h_source);
+
+	if (p->br->stp_enabled &&
+	    !memcmp(dest, bridge_ula, 5) &&
+	    !(dest[5] & 0xF0)) {
+		if (!dest[5]) {
+			NF_HOOK(PF_BRIDGE, NF_BR_LOCAL_IN, skb, skb->dev, 
+				NULL, br_stp_handle_bpdu);
+			return 1;
+		}
+	}
+
+	else if (p->state == BR_STATE_FORWARDING) {
+		if (br_should_route_hook) {
+			if (br_should_route_hook(pskb)) 
+				return 0;
+			skb = *pskb;
+			dest = eth_hdr(skb)->h_dest;
+		}
+
+		if (!memcmp(p->br->dev->dev_addr, dest, ETH_ALEN))
+			skb->pkt_type = PACKET_HOST;
+
+		NF_HOOK(PF_BRIDGE, NF_BR_PRE_ROUTING, skb, skb->dev, NULL,
+			br_handle_frame_finish);
+		return 1;
+	}
+
+err:
+	kfree_skb(skb);
+	return 1;
+}