return 0;
}
#endif
-diff -Nur old/vmware-any-any-update117d/vmnet-only/bridge.c~ new/vmware-any-any-update117d/vmnet-only/bridge.c~
---- old/vmware-any-any-update117d/vmnet-only/bridge.c~ 1970-01-01 00:00:00.000000000 +0000
-+++ new/vmware-any-any-update117d/vmnet-only/bridge.c~ 2008-08-30 15:57:32.192483250 +0000
-@@ -0,0 +1,1550 @@
-+/* **********************************************************
-+ * Copyright 1998 VMware, Inc. All rights reserved. -- VMware Confidential
-+ * **********************************************************/
-+
-+#include "driver-config.h"
-+
-+#define EXPORT_SYMTAB
-+
-+#include <linux/kernel.h>
-+#include <linux/version.h>
-+#include <linux/sched.h>
-+#ifdef KERNEL_2_2
-+# include <linux/slab.h>
-+#else
-+# include <linux/malloc.h>
-+#endif
-+#include <linux/poll.h>
-+
-+#include <linux/netdevice.h>
-+#include <linux/etherdevice.h>
-+#include <linux/mm.h>
-+#include "compat_skbuff.h"
-+#include <linux/sockios.h>
-+#include "compat_sock.h"
-+
-+#define __KERNEL_SYSCALLS__
-+#include <asm/io.h>
-+
-+#include <linux/proc_fs.h>
-+#include <linux/file.h>
-+#include <linux/ip.h>
-+#include <linux/tcp.h>
-+#include <net/tcp.h>
-+
-+#ifdef CONFIG_NET_RADIO
-+# include <linux/wireless.h>
-+#endif
-+#include "vmnetInt.h"
-+#include "compat_spinlock.h"
-+#include "compat_netdevice.h"
-+#include "vnetInt.h"
-+#include "smac.h"
-+
-+#define VNET_BRIDGE_HISTORY 48
-+
-+/*
-+ * Bytes reserved before start of packet. As Ethernet header has 14 bytes,
-+ * to get aligned IP header we must skip 2 bytes before packet. Not that it
-+ * matters a lot for us, but using 2 is compatible with what newer 2.6.x
-+ * kernels do.
-+ */
-+#ifndef NET_IP_ALIGN
-+#define NET_IP_ALIGN 2
-+#endif
-+
-+#if LOGLEVEL >= 4
-+static struct timeval vnetTime;
-+#endif
-+
-+typedef struct VNetBridge VNetBridge;
-+
-+struct VNetBridge {
-+ struct notifier_block notifier; // for device state changes
-+ char name[VNET_NAME_LEN]; // name of net device (e.g., "eth0")
-+ struct net_device *dev; // device structure for 'name'
-+ struct sock *sk; // socket associated with skb's
-+ struct packet_type pt; // used to add packet handler
-+ Bool enabledPromisc; // track if promisc enabled
-+ Bool warnPromisc; // tracks if warning has been logged
-+ struct sk_buff *history[VNET_BRIDGE_HISTORY]; // avoid duplicate packets
-+ spinlock_t historyLock; // protects 'history'
-+ VNetPort port; // connection to virtual hub
-+ Bool wirelessAdapter; // connected to wireless adapter?
-+ struct SMACState *smac; // device structure for wireless
-+#ifdef VMW_NETDEV_HAS_NET
-+ struct net_device *internalDev;
-+#endif
-+};
-+
-+typedef PacketStatus (* SMACINT SMACFunc)(struct SMACState *, SMACPackets *);
-+
-+static int VNetBridgeUp(VNetBridge *bridge, Bool rtnlLock);
-+static void VNetBridgeDown(VNetBridge *bridge, Bool rtnlLock);
-+
-+static int VNetBridgeNotify(struct notifier_block *this, u_long msg,
-+ void *data);
-+#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 14) && \
-+ !defined(VMW_TL10S64_WORKAROUND)
-+static int VNetBridgeReceiveFromDev(struct sk_buff *skb,
-+ struct net_device *dev,
-+ struct packet_type *pt);
-+#else
-+static int VNetBridgeReceiveFromDev(struct sk_buff *skb,
-+ struct net_device *dev,
-+ struct packet_type *pt,
-+ struct net_device *real_dev);
-+#endif
-+
-+static void VNetBridgeFree(VNetJack *this);
-+static void VNetBridgeReceiveFromVNet(VNetJack *this, struct sk_buff *skb);
-+static Bool VNetBridgeCycleDetect(VNetJack *this, int generation);
-+static Bool VNetBridgeIsDeviceWireless(struct net_device *dev);
-+static void VNetBridgePortsChanged(VNetJack *this);
-+static int VNetBridgeIsBridged(VNetJack *this);
-+static int VNetBridgeProcRead(char *page, char **start, off_t off,
-+ int count, int *eof, void *data);
-+
-+
-+/*
-+ *----------------------------------------------------------------------
-+ *
-+ * VNetBridgeStartPromisc --
-+ *
-+ * Set IFF_PROMISC on the peer interface.
-+ *
-+ * Results:
-+ * None.
-+ *
-+ * Side effects:
-+ * The peer interface IFF_PROMISC flag may be changed.
-+ *
-+ *----------------------------------------------------------------------
-+ */
-+
-+static void
-+VNetBridgeStartPromisc(VNetBridge *bridge, // IN:
-+ Bool rtnlLock) // IN: Acquire RTNL lock
-+{
-+ struct net_device *dev = bridge->dev;
-+
-+ /*
-+ * Disable wireless cards from going into promiscous mode because those
-+ * cards which do support RF monitoring would not be able to function
-+ * correctly i.e. they would not be able to send data packets.
-+ */
-+ if (rtnlLock) {
-+ rtnl_lock();
-+ }
-+ if (!bridge->enabledPromisc && !bridge->wirelessAdapter) {
-+ dev_set_promiscuity(dev, 1);
-+ bridge->enabledPromisc = TRUE;
-+ bridge->warnPromisc = FALSE;
-+ LOG(0, (KERN_NOTICE "bridge-%s: enabled promiscuous mode\n",
-+ bridge->name));
-+ }
-+ if (rtnlLock) {
-+ rtnl_unlock();
-+ }
-+}
-+
-+
-+/*
-+ *----------------------------------------------------------------------
-+ *
-+ * VNetBridgeStopPromisc --
-+ *
-+ * Restore saved IFF_PROMISC on the peer interface.
-+ *
-+ * Results:
-+ * None.
-+ *
-+ * Side effects:
-+ * The peer interface IFF_PROMISC flag may be changed.
-+ *
-+ *----------------------------------------------------------------------
-+ */
-+
-+static void
-+VNetBridgeStopPromisc(VNetBridge *bridge, // IN:
-+ Bool rtnlLock) // IN: Acquire RTNL lock
-+{
-+ struct net_device *dev = bridge->dev;
-+
-+ if (rtnlLock) {
-+ rtnl_lock();
-+ }
-+ if (bridge->enabledPromisc && !bridge->wirelessAdapter) {
-+ dev_set_promiscuity(dev, -1);
-+ bridge->enabledPromisc = FALSE;
-+ LOG(0, (KERN_NOTICE "bridge-%s: disabled promiscuous mode\n",
-+ bridge->name));
-+ }
-+ if (rtnlLock) {
-+ rtnl_unlock();
-+ }
-+}
-+
-+
-+/*
-+ *----------------------------------------------------------------------
-+ *
-+ * VNetBridgeCheckPromisc --
-+ *
-+ * Make sure IFF_PROMISC on the peer interface is set.
-+ *
-+ * This can be called periodically.
-+ *
-+ * Results:
-+ * None.
-+ *
-+ * Side effects:
-+ * Hopefully enables promiscuous mode again if it should have been enabled.
-+ *
-+ *----------------------------------------------------------------------
-+ */
-+
-+static INLINE_SINGLE_CALLER void
-+VNetBridgeCheckPromisc(VNetBridge *bridge)
-+{
-+#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 0)
-+ if (bridge->enabledPromisc && !bridge->wirelessAdapter) {
-+ struct net_device *dev = bridge->dev;
-+ Bool devPromisc = (dev->flags & IFF_PROMISC) != 0;
-+
-+ if (!devPromisc) {
-+ if (!bridge->warnPromisc) {
-+ bridge->warnPromisc = TRUE;
-+ LOG(0, (KERN_NOTICE "bridge-%s: someone disabled promiscuous mode\n"
-+ "Your Ethernet driver is not compatible with VMware's bridged networking.\n",
-+ bridge->name));
-+ }
-+ rtnl_lock();
-+ dev_set_promiscuity(dev, 0);
-+ rtnl_unlock();
-+ }
-+ }
-+#endif
-+}
-+
-+
-+#ifdef VMW_NETDEV_HAS_NET
-+/*
-+ *----------------------------------------------------------------------
-+ *
-+ * VNetBridgeInternalSetup --
-+ *
-+ * Setup callback for our bridge internal device. Nothing to do,
-+ * generic code sets up everything we expect from device.
-+ *
-+ * Results:
-+ * None.
-+ *
-+ * Side effects:
-+ * None.
-+ *
-+ *----------------------------------------------------------------------
-+ */
-+
-+static void
-+VNetBridgeInternalSetup(struct net_device *net)
-+{
-+ /* Do nothing. */
-+}
-+#endif
-+
-+
-+/*
-+ *----------------------------------------------------------------------
-+ *
-+ * VNetBridgeDevCompatible --
-+ *
-+ * Check whether bridge and network device are compatible.
-+ *
-+ * Results:
-+ * Non-zero if device is good enough for bridge. Zero otherwise.
-+ *
-+ * Side effects:
-+ * None.
-+ *
-+ *----------------------------------------------------------------------
-+ */
-+
-+static INLINE_SINGLE_CALLER int
-+VNetBridgeDevCompatible(VNetBridge *bridge, // IN: Bridge
-+ struct net_device *net) // IN: Network device
-+{
-+#ifdef VMW_NETDEV_HAS_NET
-+ if (net->nd_net != bridge->internalDev->nd_net)) {
-+ return 0;
-+ }
-+#endif
-+ return strcmp(net->name, bridge->name) == 0;
-+}
-+
-+
-+/*
-+ *----------------------------------------------------------------------
-+ *
-+ * VNetBridge_Create --
-+ *
-+ * Create a bridge. Allocates/initializes struct, registers
-+ * with kernel for device state changes, connects to virtual
-+ * hub, initializes port/jack, and creates a proc entry.
-+ *
-+ * Results:
-+ * Errno. Also returns an allocated jack to connect to,
-+ * NULL on error.
-+ *
-+ * Side effects:
-+ * None.
-+ *
-+ *----------------------------------------------------------------------
-+ */
-+
-+int
-+VNetBridge_Create(char *devName, // IN: name of device (e.g., "eth0")
-+ VNetPort **ret) // OUT: port to virtual hub
-+{
-+ VNetBridge *bridge = NULL;
-+ static unsigned id = 0;
-+ int retval = 0;
-+
-+ *ret = NULL;
-+
-+ /*
-+ * Its an error if device name is empty.
-+ */
-+
-+ if (devName[0] == '\0') {
-+ retval = -EINVAL;
-+ goto out;
-+ }
-+
-+ /*
-+ * Allocate bridge structure
-+ */
-+
-+ bridge = kmalloc(sizeof *bridge, GFP_USER);
-+ if (bridge == NULL) {
-+ retval = -ENOMEM;
-+ goto out;
-+ }
-+ memset(bridge, 0, sizeof *bridge);
-+ spin_lock_init(&bridge->historyLock);
-+ memcpy(bridge->name, devName, sizeof bridge->name);
-+ NULL_TERMINATE_STRING(bridge->name);
-+
-+#ifdef VMW_NETDEV_HAS_NET
-+ bridge->internalDev = compat_alloc_netdev(0, "vmnetX", VNetBridgeInternalSetup);
-+ if (!bridge->internalDev) {
-+ retval = -ENOMEM;
-+ goto out;
-+ }
-+#endif
-+
-+ /*
-+ * Set up notifier for network device state change
-+ */
-+
-+ bridge->notifier.notifier_call = VNetBridgeNotify;
-+ bridge->notifier.priority = 0;
-+ register_netdevice_notifier(&bridge->notifier);
-+
-+ /*
-+ * Try to bring it up
-+ */
-+
-+ retval = VNetBridgeUp(bridge, TRUE);
-+ if (retval == -ENODEV) {
-+ LOG(1, (KERN_DEBUG "bridge-%s: peer interface %s not found, "
-+ "will wait for it to come up\n",
-+ bridge->name, devName));
-+ retval = 0;
-+ }
-+ if (retval != 0) {
-+ goto out;
-+ }
-+
-+ /*
-+ * Initialize jack
-+ */
-+
-+ bridge->port.id = id++;
-+ bridge->port.next = NULL;
-+
-+ bridge->port.jack.peer = NULL;
-+ bridge->port.jack.numPorts = 1;
-+ VNetSnprintf(bridge->port.jack.name, sizeof bridge->port.jack.name,
-+ "bridge%u", bridge->port.id);
-+ bridge->port.jack.private = bridge;
-+ bridge->port.jack.index = 0;
-+ bridge->port.jack.procEntry = NULL;
-+ bridge->port.jack.free = VNetBridgeFree;
-+ bridge->port.jack.rcv = VNetBridgeReceiveFromVNet;
-+ bridge->port.jack.cycleDetect = VNetBridgeCycleDetect;
-+ bridge->port.jack.portsChanged = VNetBridgePortsChanged;
-+ bridge->port.jack.isBridged = VNetBridgeIsBridged;
-+
-+ /*
-+ * Make proc entry for this jack.
-+ */
-+
-+ retval = VNetProc_MakeEntry(NULL, bridge->port.jack.name, S_IFREG,
-+ &bridge->port.jack.procEntry);
-+ if (retval) {
-+ if (retval == -ENXIO) {
-+ bridge->port.jack.procEntry = NULL;
-+ } else {
-+ goto out;
-+ }
-+ } else {
-+ bridge->port.jack.procEntry->read_proc = VNetBridgeProcRead;
-+ bridge->port.jack.procEntry->data = bridge;
-+ }
-+
-+ /*
-+ * Rest of fields.
-+ */
-+
-+ bridge->port.flags = IFF_RUNNING;
-+
-+ memset(bridge->port.paddr, 0, sizeof bridge->port.paddr);
-+ memset(bridge->port.ladrf, 0, sizeof bridge->port.ladrf);
-+
-+ bridge->port.paddr[0] = VMX86_STATIC_OUI0;
-+ bridge->port.paddr[1] = VMX86_STATIC_OUI1;
-+ bridge->port.paddr[2] = VMX86_STATIC_OUI2;
-+
-+ bridge->port.fileOpRead = NULL;
-+ bridge->port.fileOpWrite = NULL;
-+ bridge->port.fileOpIoctl = NULL;
-+ bridge->port.fileOpPoll = NULL;
-+
-+ *ret = &bridge->port;
-+
-+ LOG(1, (KERN_DEBUG "bridge-%s: attached\n", bridge->name));
-+ return 0;
-+
-+out:
-+ if (bridge != NULL) {
-+ if (bridge->notifier.notifier_call != NULL) {
-+ unregister_netdevice_notifier(&bridge->notifier);
-+ }
-+#ifdef VMW_NETDEV_HAS_NET
-+ if (bridge->internalDev) {
-+ compat_free_netdev(bridge->internalDev);
-+ }
-+#endif
-+ kfree(bridge);
-+ }
-+ return retval;
-+}
-+
-+
-+/*
-+ *----------------------------------------------------------------------
-+ *
-+ * VNetBridgeFree --
-+ *
-+ * Disconnect the bridge, unregister from device state
-+ * notifications, remove proc entry, and deallocate struct.
-+ *
-+ * Results:
-+ * None.
-+ *
-+ * Side effects:
-+ * None.
-+ *
-+ *----------------------------------------------------------------------
-+ */
-+
-+void
-+VNetBridgeFree(VNetJack *this) // IN: jack to free
-+{
-+ VNetBridge *bridge = (VNetBridge*)this->private;
-+
-+ if (bridge->dev != NULL) {
-+ VNetBridgeDown(bridge, TRUE);
-+ }
-+
-+ unregister_netdevice_notifier(&bridge->notifier);
-+
-+#ifdef VMW_NETDEV_HAS_NET
-+ if (bridge->internalDev) {
-+ compat_free_netdev(bridge->internalDev);
-+ }
-+#endif
-+
-+ if (this->procEntry) {
-+ VNetProc_RemoveEntry(this->procEntry, NULL);
-+ }
-+
-+ if (bridge->smac){
-+ SMAC_CleanupState(&(bridge->smac));
-+ }
-+
-+ LOG(1, (KERN_DEBUG "bridge-%s: detached\n", bridge->name));
-+ kfree(bridge);
-+}
-+
-+
-+/*
-+ *----------------------------------------------------------------------
-+ *
-+ * VNetCallSMACFunc --
-+ *
-+ * Wrapper for SMAC functions.
-+ *
-+ * Results:
-+ * Packet Status.
-+ *
-+ * Side effects:
-+ * The skb buffer is freed if not succesfull otherwise it points to
-+ * the clone.
-+ *
-+ *----------------------------------------------------------------------
-+ */
-+
-+PacketStatus
-+VNetCallSMACFunc(struct SMACState *state, // IN: pointer to state
-+ struct sk_buff **skb, // IN/OUT: packet to process
-+ void *startOfData, // IN: points to start of data
-+ SMACFunc func) // IN: function to be called
-+{
-+ SMACPackets packets = { {0} };
-+ PacketStatus status;
-+
-+ packets.orig.skb = *skb;
-+ packets.orig.startOfData = startOfData;
-+
-+ status = func(state, &packets);
-+ if (status != PacketStatusForwardPacket) {
-+ dev_kfree_skb(*skb);
-+ return status;
-+ }
-+
-+ if (packets.clone.skb) {
-+ dev_kfree_skb(*skb);
-+ *skb = packets.clone.skb;
-+ }
-+ return status;
-+}
-+
-+
-+/*
-+ *----------------------------------------------------------------------
-+ *
-+ * VNetBridgeReceiveFromVNet --
-+ *
-+ * This jack is receiving a packet from a vnet. This function
-+ * sends down (i.e., out on the host net device) if the packet
-+ * isn't destined for the host, and it sends up (i.e.,
-+ * simulates a receive for the host) if the packet
-+ * satisfies the host's packet filter.
-+ *
-+ * When the function sends up it keeps a reference to the
-+ * packet in a history list so that we can avoid handing
-+ * a VM a copy of its own packet.
-+ *
-+ * Results:
-+ * None.
-+ *
-+ * Side effects:
-+ * Frees skb. Checks if host device is still using
-+ * promiscuous mode.
-+ *
-+ *----------------------------------------------------------------------
-+ */
-+
-+void
-+VNetBridgeReceiveFromVNet(VNetJack *this, // IN: jack
-+ struct sk_buff *skb) // IN: pkt to receive
-+{
-+ VNetBridge *bridge = (VNetBridge*)this->private;
-+ struct net_device *dev = bridge->dev;
-+ uint8 dest[ETH_ALEN];
-+ struct sk_buff *clone;
-+
-+ LOG(3, (KERN_DEBUG "bridge-%s: transmit %d\n",
-+ bridge->name, (int) skb->len));
-+
-+ if (!dev) {
-+ dev_kfree_skb(skb);
-+ return;
-+ }
-+
-+ /*
-+ * skb might be freed by wireless code, so need to keep
-+ * a local copy of the MAC rather than a pointer to it.
-+ */
-+
-+ memcpy(dest, SKB_2_DESTMAC(skb), ETH_ALEN);
-+
-+ /*
-+ * Check promiscuous bit periodically
-+ */
-+
-+ VNetBridgeCheckPromisc(bridge);
-+
-+#ifdef notdef
-+ // xxx;
-+ /*
-+ * We need to send the packet both up to the host and down
-+ * to the interface.
-+ * However, we ignore packets destined only for this hub.
-+ */
-+
-+ for (i = 0; i < VNET_PORTS_PER_HUB; i++) {
-+ VNetPort *p = &port->hub->port[i];
-+ if (UP_AND_RUNNING(p->flags) && MAC_EQ(dest, p->paddr)) {
-+ return;
-+ }
-+ }
-+#endif
-+
-+ /*
-+ * Wireless processing
-+ */
-+
-+ if (bridge->smac) {
-+ if (VNetCallSMACFunc(bridge->smac, &skb, skb->data,
-+ SMAC_CheckPacketToHost) !=
-+ PacketStatusForwardPacket) {
-+ LOG(4, (KERN_NOTICE "bridge-%s: packet dropped .\n",
-+ bridge->name));
-+ return;
-+ }
-+ }
-+
-+ /*
-+ * Send down (imitate packet_sendmsg)
-+ *
-+ * Do this only if the packet is not addressed to the peer,
-+ * and the packet size is not too big.
-+ */
-+
-+ dev_lock_list();
-+ if (MAC_EQ(dest, dev->dev_addr) ||
-+ skb->len > dev->mtu + dev->hard_header_len) {
-+ dev_unlock_list();
-+ } else {
-+# if 0 // XXX we should do header translation
-+ if ((dev->flags & IFF_SOFTHEADERS) != 0) {
-+ if (skb->len > dev->mtu) {
-+ clone = NULL;
-+ } else {
-+ clone = dev_alloc_skb(skb->len + dev->hard_header_len, GFP_ATOMIC);
-+ }
-+ if (clone != NULL) {
-+ skb_reserve(clone, dev->hard_header_len);
-+ if (dev->hard_header != NULL) {
-+ dev->hard_header(clone, dev, ETH_P_IP, NULL, NULL, skb->len);
-+ }
-+ memcpy(skb_put(clone, skb->len), skb->data, skb->len);
-+ }
-+ }
-+# endif
-+ clone = skb_clone(skb, GFP_ATOMIC);
-+ if (clone == NULL) {
-+ dev_unlock_list();
-+ } else {
-+ struct sock *sk = bridge->sk;
-+ atomic_add(skb->truesize, &sk->sk_wmem_alloc);
-+ clone->sk = sk;
-+ clone->protocol = ((struct ethhdr *)skb->data)->h_proto; // XXX
-+ if ((dev->flags & IFF_UP) != 0) {
-+ dev_unlock_list();
-+ DEV_QUEUE_XMIT(clone, dev, 0);
-+ } else {
-+ dev_unlock_list();
-+ dev_kfree_skb(clone);
-+ }
-+ }
-+ }
-+
-+ /*
-+ * Send up (imitate Ethernet receive)
-+ *
-+ * Do this if the packet is addressed to the peer (or is broadcast, etc.).
-+ *
-+ * This packet will get back to us, via VNetBridgeReceive.
-+ * We save it so we can recognize it (and its clones) again.
-+ */
-+
-+ if (VNetPacketMatch(dest, dev->dev_addr, (uint8 *)&AllMultiFilter, dev->flags)) {
-+ clone = skb_clone(skb, GFP_ATOMIC);
-+ if (clone) {
-+ unsigned long flags;
-+ int i;
-+
-+ atomic_inc(&clone->users);
-+
-+ clone->dev = dev;
-+ clone->protocol = eth_type_trans(clone, dev);
-+ spin_lock_irqsave(&bridge->historyLock, flags);
-+ for (i = 0; i < VNET_BRIDGE_HISTORY; i++) {
-+ if (bridge->history[i] == NULL) {
-+ bridge->history[i] = clone;
-+# if LOGLEVEL >= 3
-+ {
-+ int j;
-+ int count = 0;
-+ for (j = 0; j < VNET_BRIDGE_HISTORY; j++) {
-+ if (bridge->history[j] != NULL) {
-+ count++;
-+ }
-+ }
-+ LOG(3, (KERN_DEBUG "bridge-%s: host slot %d history %d\n",
-+ bridge->name, i, count));
-+ }
-+# endif
-+ break;
-+ }
-+ }
-+ if (i >= VNET_BRIDGE_HISTORY) {
-+ LOG(1, (KERN_NOTICE "bridge-%s: history full\n",
-+ bridge->name));
-+
-+ for (i = 0; i < VNET_BRIDGE_HISTORY; i++) {
-+ struct sk_buff *s = bridge->history[i];
-+
-+ /*
-+ * We special case 0 to avoid races with another thread on
-+ * another cpu wanting to use the 0 entry. This could happen
-+ * when we release the lock to free the former entry.
-+ * See bug 11231 for details.
-+ */
-+ if (i == 0) {
-+ bridge->history[0] = clone;
-+ } else {
-+ bridge->history[i] = NULL;
-+ }
-+ if (s) {
-+ spin_unlock_irqrestore(&bridge->historyLock, flags);
-+ dev_kfree_skb(s);
-+ spin_lock_irqsave(&bridge->historyLock, flags);
-+ }
-+ }
-+ }
-+ spin_unlock_irqrestore(&bridge->historyLock, flags);
-+
-+ /*
-+ * We used to cli() before calling netif_rx() here. It was probably
-+ * unneeded (as we never did it in netif.c, and the code worked). In
-+ * any case, now that we are using netif_rx_ni(), we should certainly
-+ * not do it, or netif_rx_ni() will deadlock on the cli() lock --hpreg
-+ */
-+
-+ netif_rx_ni(clone);
-+# if LOGLEVEL >= 4
-+ do_gettimeofday(&vnetTime);
-+# endif
-+ }
-+ }
-+
-+ // xxx;
-+ dev_kfree_skb(skb);
-+}
-+
-+
-+/*
-+ *----------------------------------------------------------------------
-+ *
-+ * VNetBridgeCycleDetect --
-+ *
-+ * Cycle detection algorithm.
-+ *
-+ * Results:
-+ * TRUE if a cycle was detected, FALSE otherwise.
-+ *
-+ * Side effects:
-+ * None.
-+ *
-+ *----------------------------------------------------------------------
-+ */
-+
-+Bool
-+VNetBridgeCycleDetect(VNetJack *this, // IN: jack
-+ int generation) // IN: generation
-+{
-+ VNetBridge *bridge = (VNetBridge*)this->private;
-+ return VNetCycleDetectIf(bridge->name, generation);
-+}
-+
-+
-+/*
-+ *----------------------------------------------------------------------
-+ *
-+ * VNetBridgePortsChanged --
-+ *
-+ * The number of ports connected to this jack has change, react
-+ * accordingly by starting/stopping promiscuous mode based on
-+ * whether any peers exist.
-+ *
-+ * Results:
-+ * None.
-+ *
-+ * Side effects:
-+ * Promiscuous mode may be started or stopped.
-+ *
-+ *----------------------------------------------------------------------
-+ */
-+
-+void
-+VNetBridgePortsChanged(VNetJack *this) // IN: jack
-+{
-+ VNetBridge *bridge = (VNetBridge*)this->private;
-+ if (bridge->dev) {
-+ if (VNetGetAttachedPorts(this)) {
-+ VNetBridgeStartPromisc(bridge, TRUE);
-+ } else {
-+ VNetBridgeStopPromisc(bridge, TRUE);
-+ }
-+ }
-+}
-+
-+
-+/*
-+ *----------------------------------------------------------------------
-+ *
-+ * VNetBridgeIsBridged --
-+ *
-+ * Reports if the bridged interface is up or down.
-+ *
-+ * Results:
-+ * 1 - we are bridged but the interface is not up
-+ * 2 - we are bridged and the interface is up
-+ *
-+ * Side effects:
-+ * None.
-+ *
-+ *----------------------------------------------------------------------
-+ */
-+
-+int
-+VNetBridgeIsBridged(VNetJack *this) // IN: jack
-+{
-+ VNetBridge *bridge = (VNetBridge*)this->private;
-+ if (bridge->dev) {
-+ return 2;
-+ } else {
-+ return 1;
-+ }
-+}
-+
-+/*
-+ *----------------------------------------------------------------------
-+ *
-+ * VNetBridgeIsDeviceWireless --
-+ *
-+ * Check if the device is a wireless adapter, depending on the version
-+ * of the wireless extension present in the kernel.
-+ *
-+ * Results:
-+ * TRUE if the device is wireless, FALSE otherwise.
-+ *
-+ * Side effects:
-+ * None.
-+ *
-+ *----------------------------------------------------------------------
-+ */
-+
-+static Bool
-+VNetBridgeIsDeviceWireless(struct net_device *dev) //IN: sock
-+{
-+#if !defined(CONFIG_NET_RADIO)
-+ return FALSE;
-+#elif WIRELESS_EXT > 19
-+ return dev->wireless_handlers != NULL;
-+#elif WIRELESS_EXT > 12
-+ return dev->wireless_handlers != NULL || dev->get_wireless_stats != NULL;
-+#else
-+ return dev->get_wireless_stats != NULL;
-+#endif
-+}
-+
-+/*
-+ *----------------------------------------------------------------------
-+ *
-+ * VNetBridgeUp --
-+ *
-+ * Bring a bridge up. Gets peer's device structure, verifies
-+ * that interface is up, checks the header length,
-+ * allocates a socket, adds a packet handler to the network
-+ * stack, and then places the peer's device in promiscuous
-+ * mode.
-+ *
-+ * Results:
-+ * errno.
-+ *
-+ * Side effects:
-+ * Bridging may be brought up with a peer interface.
-+ *
-+ *----------------------------------------------------------------------
-+ */
-+
-+int
-+VNetBridgeUp(VNetBridge *bridge, // IN: bridge struct
-+ Bool rtnlLock) // IN: acquire RTNL lock
-+{
-+ int retval = 0;
-+
-+ if (bridge->dev != NULL) {
-+ LOG(0, (KERN_NOTICE "bridge-%s: already up\n", bridge->name));
-+ goto out;
-+ }
-+
-+ /*
-+ * Get peer device structure
-+ */
-+
-+ dev_lock_list();
-+ bridge->dev = DEV_GET(bridge);
-+ LOG(2, (KERN_DEBUG "bridge-%s: got dev %p\n",
-+ bridge->name, bridge->dev));
-+ if (bridge->dev == NULL) {
-+ dev_unlock_list();
-+ retval = -ENODEV;
-+ goto out;
-+ }
-+ if (!(bridge->dev->flags & IFF_UP)) {
-+ LOG(2, (KERN_DEBUG "bridge-%s: interface %s is not up\n",
-+ bridge->name, bridge->dev->name));
-+ dev_unlock_list();
-+ retval = -ENODEV;
-+ goto out;
-+ }
-+
-+ /*
-+ * At a minimum, the header size should be the same as ours.
-+ *
-+ * XXX we should either do header translation or ensure this
-+ * is an Ethernet.
-+ */
-+
-+ if (bridge->dev->hard_header_len != ETH_HLEN) {
-+ LOG(1, (KERN_DEBUG "bridge-%s: can't bridge with %s, bad header length %d\n",
-+ bridge->name, bridge->dev->name, bridge->dev->hard_header_len));
-+ dev_unlock_list();
-+ retval = -EINVAL;
-+ goto out;
-+ }
-+
-+ /*
-+ * Get a socket to play with
-+ *
-+ * We set the dead field so we don't get a call back from dev_kfree_skb().
-+ * (The alternative is to support the callback.)
-+ */
-+
-+ bridge->sk = compat_sk_alloc(bridge, GFP_ATOMIC);
-+ if (bridge->sk == NULL) {
-+ dev_unlock_list();
-+ retval = -ENOMEM;
-+ goto out;
-+ }
-+ SET_SK_DEAD(bridge->sk);
-+
-+ bridge->wirelessAdapter = VNetBridgeIsDeviceWireless(bridge->dev);
-+
-+ /*
-+ * If it is a wireless adapter initialize smac struct.
-+ */
-+
-+ if (bridge->wirelessAdapter) {
-+
-+ LOG(1, (KERN_NOTICE "bridge-%s: is a Wireless Adapter\n", bridge->name));
-+ SMAC_InitState(&(bridge->smac));
-+ if (bridge->smac) {
-+ /*
-+ * Store the MAC address of the adapter
-+ */
-+
-+ SMAC_SetMac(bridge->smac, bridge->dev->dev_addr);
-+ }
-+ }
-+
-+ /*
-+ * Link up with the peer device by adding a
-+ * packet handler to the networking stack.
-+ */
-+
-+ bridge->pt.func = VNetBridgeReceiveFromDev;
-+ bridge->pt.type = htons(ETH_P_ALL);
-+ bridge->pt.dev = bridge->dev;
-+
-+ /*
-+ * TurboLinux10 uses 2.6.0-test5, which we do not support, so special case it,
-+ * 2.6.0 with tl_kernel_version_h is 2.6.0-pre5...
-+ */
-+#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 0) || \
-+ (LINUX_VERSION_CODE == KERNEL_VERSION(2, 6, 0) && defined(__tl_kernel_version_h__))
-+ bridge->pt.data = bridge->sk;
-+#else
-+ bridge->pt.af_packet_priv = bridge->sk;
-+#endif
-+ bridge->enabledPromisc = FALSE;
-+ bridge->warnPromisc = FALSE;
-+ dev_add_pack(&bridge->pt);
-+ dev_unlock_list();
-+
-+ /*
-+ * Put in promiscuous mode if need be.
-+ */
-+
-+ down(&vnetStructureSemaphore);
-+ if (VNetGetAttachedPorts(&bridge->port.jack)) {
-+ VNetBridgeStartPromisc(bridge, rtnlLock);
-+ }
-+ up(&vnetStructureSemaphore);
-+
-+ /*
-+ * Finish up
-+ */
-+
-+ LOG(1, (KERN_DEBUG "bridge-%s: up\n", bridge->name));
-+
-+ /*
-+ * Return
-+ */
-+
-+out:
-+ if (retval != 0) {
-+ if (bridge->sk != NULL) {
-+ sk_free(bridge->sk);
-+ bridge->sk = NULL;
-+ }
-+ bridge->dev = NULL;
-+ }
-+ return retval;
-+}
-+
-+
-+/*
-+ *----------------------------------------------------------------------
-+ *
-+ * VNetBridgeDown --
-+ *
-+ * Bring a bridge down. Stops promiscuous mode, removes the
-+ * packet handler from the network stack, and frees the
-+ * socket.
-+ *
-+ * Results:
-+ * None.
-+ *
-+ * Side effects:
-+ * Bridging is brought down.
-+ *
-+ *----------------------------------------------------------------------
-+ */
-+
-+void
-+VNetBridgeDown(VNetBridge *bridge, // IN: bridge
-+ Bool rtnlLock) // IN: acquire RTNL lock
-+{
-+ if (bridge->dev == NULL) {
-+ LOG(0, (KERN_NOTICE "bridge-%s: already down\n", bridge->name));
-+ return;
-+ }
-+
-+ VNetBridgeStopPromisc(bridge, rtnlLock);
-+ if (bridge->smac){
-+ SMAC_SetMac(bridge->smac, NULL);
-+ }
-+ bridge->dev = NULL;
-+ dev_remove_pack(&bridge->pt);
-+ sk_free(bridge->sk);
-+ bridge->sk = NULL;
-+ LOG(1, (KERN_DEBUG "bridge-%s: down\n", bridge->name));
-+}
-+
-+
-+/*
-+ *-----------------------------------------------------------------------------
-+ *
-+ * VNetBridgeNotify --
-+ *
-+ * Callback on peer device state change. The function brings
-+ * the bridge up/down in response to changes in the peer device.
-+ *
-+ * Results:
-+ * NOTIFY_DONE
-+ *
-+ * Side effects:
-+ * Promiscuous mode is changed when bridge brought up/down.
-+ *
-+ *-----------------------------------------------------------------------------
-+ */
-+
-+int
-+VNetBridgeNotify(struct notifier_block *this, // IN: callback data (bridge)
-+ u_long msg, // IN: type of event
-+ void *data) // IN: device pertaining to event
-+{
-+ VNetBridge *bridge = list_entry(this, VNetBridge, notifier);
-+ struct net_device *dev = (struct net_device *) data;
-+
-+ switch (msg) {
-+ case NETDEV_UNREGISTER:
-+ LOG(2, (KERN_DEBUG "bridge-%s: interface %s is unregistering\n",
-+ bridge->name, dev->name));
-+ if (dev == bridge->dev) {
-+ /* This should never happen --hpreg */
-+ LOG(0, (KERN_WARNING "bridge-%s: interface %s unregistered without "
-+ "going down! Disabling the bridge\n", bridge->name,
-+ dev->name));
-+ VNetBridgeDown(bridge, FALSE);
-+ }
-+ break;
-+
-+ case NETDEV_DOWN:
-+ LOG(2, (KERN_DEBUG "bridge-%s: interface %s is going down\n",
-+ bridge->name, dev->name));
-+ if (dev == bridge->dev) {
-+ LOG(1, (KERN_DEBUG "bridge-%s: disabling the bridge\n",
-+ bridge->name));
-+ VNetBridgeDown(bridge, FALSE);
-+ }
-+ break;
-+
-+ case NETDEV_UP:
-+ LOG(2, (KERN_DEBUG "bridge-%s: interface %s is going up\n",
-+ bridge->name, dev->name));
-+ if (bridge->dev == NULL && VNetBridgeDevCompatible(bridge, dev)) {
-+ int errno;
-+
-+ LOG(1, (KERN_DEBUG "bridge-%s: enabling the bridge\n", bridge->name));
-+ errno = VNetBridgeUp(bridge, FALSE);
-+ switch (-errno) {
-+ case 0:
-+ break;
-+
-+ case ENODEV:
-+ LOG(0, (KERN_WARNING "bridge-%s: interface %s not found or not "
-+ "up\n", bridge->name, dev->name));
-+ break;
-+
-+ case EINVAL:
-+ LOG(0, (KERN_WARNING "bridge-%s: interface %s is not a valid "
-+ "Ethernet interface\n", bridge->name, dev->name));
-+ break;
-+
-+ case ENOMEM:
-+ LOG(0, (KERN_WARNING "bridge-%s: failed to allocate memory\n",
-+ bridge->name));
-+ break;
-+
-+ default:
-+ /* This should never happen --hpreg */
-+ LOG(0, (KERN_WARNING "bridge-%s: failed to enable the bridge to "
-+ "interface %s (error %d)\n", bridge->name, dev->name,
-+ -errno));
-+ break;
-+ }
-+ }
-+ break;
-+
-+ default:
-+ LOG(2, (KERN_DEBUG "bridge-%s: interface %s is sending notification "
-+ "0x%lx\n", bridge->name, dev->name, msg));
-+ break;
-+ }
-+
-+ return NOTIFY_DONE;
-+}
-+
-+
-+/*
-+ *----------------------------------------------------------------------
-+ *
-+ * VNetBridgeComputeHeaderPos --
-+ *
-+ * Compute correct position for UDP/TCP header.
-+ *
-+ * Results:
-+ * None.
-+ *
-+ * Side effects:
-+ * transport header pointer updated to point to the tcp/udp header.
-+ *
-+ *----------------------------------------------------------------------
-+ */
-+
-+static INLINE_SINGLE_CALLER void
-+VNetBridgeComputeHeaderPos(struct sk_buff *skb) // IN: buffer to examine
-+{
-+ /* Maybe some kernel gets it right... */
-+ if (compat_skb_network_header_len(skb)) {
-+ return;
-+ }
-+ switch (be16_to_cpu(skb->protocol)) {
-+ case ETH_P_IP: {
-+ struct iphdr *ipHdr = compat_skb_ip_header(skb);
-+
-+ compat_skb_set_transport_header(skb, compat_skb_network_offset(skb) +
-+ ipHdr->ihl * 4);
-+ }
-+ return;
-+ default:
-+ LOG(3, (KERN_DEBUG "Unknown EII protocol %04X: csum at %d\n",
-+ be16_to_cpu(skb->protocol), compat_skb_csum_offset(skb)));
-+ break;
-+ }
-+ return;
-+}
-+
-+
-+/*
-+ * We deal with three types of kernels:
-+ * New kernels: skb_shinfo() has gso_size member, and there is
-+ * skb_gso_segment() helper to split GSO skb into flat ones.
-+ * Older kernels: skb_shinfo() has tso_size member, and there is
-+ * no helper.
-+ * Oldest kernels: without any segmentation offload support.
-+ */
-+#if defined(NETIF_F_GSO) || LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 18)
-+#define VNetBridgeIsGSO(skb) skb_shinfo(skb)->gso_size
-+#define VNetBridgeGSOSegment(skb) skb_gso_segment(skb, 0)
-+#elif defined(NETIF_F_TSO)
-+#define VNetBridgeIsGSO(skb) skb_shinfo(skb)->tso_size
-+
-+
-+/*
-+ *----------------------------------------------------------------------
-+ *
-+ * VNetBridgeGSOSegment --
-+ *
-+ * Split a large TCP/IPv4 sk_buff into multiple sk_buffs of
-+ * size skb_shinfo(skb)->tso_size
-+ * Called from VNetBridgeSendLargePacket().
-+ *
-+ * Results:
-+ * List of skbs created.
-+ *
-+ * Side effects:
-+ * The incoming packet is split into multiple packets.
-+ *
-+ *----------------------------------------------------------------------
-+ */
-+
-+static struct sk_buff *
-+VNetBridgeGSOSegment(struct sk_buff *skb) // IN: packet to split
-+{
-+ struct sk_buff *segs = NULL;
-+ struct sk_buff **next = &segs;
-+ int bytesPerPacket, bytesLeft;
-+ int macHdrLen, ipHdrLen, tcpHdrLen, allHdrLen;
-+ int curByteOffset;
-+ uint16 ipID;
-+ uint32 seqNo;
-+
-+ if (((struct ethhdr *)compat_skb_mac_header(skb))->h_proto != htons(ETH_P_IP)) {
-+ return ERR_PTR(-EPFNOSUPPORT);
-+ }
-+
-+ if (compat_skb_ip_header(skb)->protocol != IPPROTO_TCP) {
-+ return ERR_PTR(-EPROTONOSUPPORT);
-+ }
-+
-+ macHdrLen = compat_skb_network_header(skb) - compat_skb_mac_header(skb);
-+ ipHdrLen = compat_skb_ip_header(skb)->ihl << 2;
-+ tcpHdrLen = compat_skb_tcp_header(skb)->doff << 2;
-+ allHdrLen = macHdrLen + ipHdrLen + tcpHdrLen;
-+
-+ ipID = ntohs(compat_skb_ip_header(skb)->id);
-+ seqNo = ntohl(compat_skb_tcp_header(skb)->seq);
-+
-+ /* Host TCP stack populated this (MSS) for the host NIC driver */
-+ bytesPerPacket = skb_shinfo(skb)->tso_size;
-+
-+ bytesLeft = skb->len - allHdrLen;
-+ curByteOffset = allHdrLen;
-+
-+ while (bytesLeft) {
-+ struct sk_buff *newSkb;
-+ int payloadSize = (bytesLeft < bytesPerPacket) ? bytesLeft : bytesPerPacket;
-+
-+ newSkb = dev_alloc_skb(payloadSize + allHdrLen + NET_IP_ALIGN);
-+ if (!newSkb) {
-+ while (segs) {
-+ newSkb = segs;
-+ segs = segs->next;
-+ newSkb->next = NULL;
-+ dev_kfree_skb(newSkb);
-+ }
-+ return ERR_PTR(-ENOMEM);
-+ }
-+ skb_reserve(newSkb, NET_IP_ALIGN);
-+ newSkb->dev = skb->dev;
-+ newSkb->protocol = skb->protocol;
-+ newSkb->pkt_type = skb->pkt_type;
-+ newSkb->ip_summed = VM_CHECKSUM_PARTIAL;
-+
-+ /*
-+ * MAC+IP+TCP copy
-+ * This implies that ALL fields in the IP and TCP headers are copied from
-+ * the original skb. This is convenient: we'll only fix up fields that
-+ * need to be changed below
-+ */
-+ memcpy(skb_put(newSkb, allHdrLen), skb->data, allHdrLen);
-+
-+ /* Fix up pointers to different layers */
-+ compat_skb_reset_mac_header(newSkb);
-+ compat_skb_set_network_header(newSkb, macHdrLen);
-+ compat_skb_set_transport_header(newSkb, macHdrLen + ipHdrLen);
-+
-+ /* Payload copy */
-+ skb_copy_bits(skb, curByteOffset, compat_skb_tail_pointer(newSkb), payloadSize);
-+ skb_put(newSkb, payloadSize);
-+
-+ curByteOffset+=payloadSize;
-+ bytesLeft -= payloadSize;
-+
-+ /* Fix up IP hdr */
-+ compat_skb_ip_header(newSkb)->tot_len = htons(payloadSize + tcpHdrLen + ipHdrLen);
-+ compat_skb_ip_header(newSkb)->id = htons(ipID);
-+ compat_skb_ip_header(newSkb)->check = 0;
-+ /* Recompute new IP checksum */
-+ compat_skb_ip_header(newSkb)->check =
-+ ip_fast_csum(compat_skb_network_header(newSkb),
-+ compat_skb_ip_header(newSkb)->ihl);
-+
-+ /* Fix up TCP hdr */
-+ compat_skb_tcp_header(newSkb)->seq = htonl(seqNo);
-+ /* Clear FIN/PSH if not last packet */
-+ if (bytesLeft > 0) {
-+ compat_skb_tcp_header(newSkb)->fin = 0;
-+ compat_skb_tcp_header(newSkb)->psh = 0;
-+ }
-+ /* Recompute partial TCP checksum */
-+ compat_skb_tcp_header(newSkb)->check =
-+ ~csum_tcpudp_magic(compat_skb_ip_header(newSkb)->saddr,
-+ compat_skb_ip_header(newSkb)->daddr,
-+ payloadSize+tcpHdrLen, IPPROTO_TCP, 0);
-+
-+ /* Offset of field */
-+ newSkb->csum = offsetof(struct tcphdr, check);
-+
-+ /* Join packet to the list of segments */
-+ *next = newSkb;
-+ next = &newSkb->next;
-+
-+ /* Bump up our counters */
-+ ipID++;
-+ seqNo += payloadSize;
-+
-+ }
-+ return segs;
-+}
-+#else
-+#define VNetBridgeIsGSO(skb) (0)
-+#define VNetBridgeGSOSegment(skb) ERR_PTR(-ENOSYS)
-+#endif
-+
-+
-+/*
-+ *----------------------------------------------------------------------
-+ *
-+ * VNetBridgeSendLargePacket --
-+ *
-+ * Split and send a large TCP/IPv4 sk_buff into multiple sk_buffs which
-+ * fits on wire. Called from VNetBridgeReceiveFromDev(), which is a
-+ * protocol handler called from the bottom half, so steady as she
-+ * goes...
-+ *
-+ * skb passed in is deallocated by function.
-+ *
-+ * Results:
-+ * None.
-+ *
-+ * Side effects:
-+ * The incoming packet is split into multiple packets and sent to the
-+ * vnet.
-+ *
-+ *----------------------------------------------------------------------
-+ */
-+
-+void
-+VNetBridgeSendLargePacket(struct sk_buff *skb, // IN: packet to split
-+ VNetBridge *bridge) // IN: bridge
-+{
-+ struct sk_buff *segs;
-+
-+ segs = VNetBridgeGSOSegment(skb);
-+ dev_kfree_skb(skb);
-+ if (IS_ERR(segs)) {
-+ LOG(1, (KERN_DEBUG "bridge-%s: cannot segment packet: error %ld\n",
-+ bridge->name, PTR_ERR(segs)));
-+ return;
-+ }
-+
-+ while (segs) {
-+ struct sk_buff *newSkb;
-+
-+ newSkb = segs;
-+ segs = newSkb->next;
-+ newSkb->next = NULL;
-+ /* Send it along */
-+ skb = newSkb;
-+ VNetSend(&bridge->port.jack, newSkb);
-+ }
-+}
-+
-+
-+/*
-+ *----------------------------------------------------------------------
-+ *
-+ * VNetBridgeReceiveFromDev --
-+ *
-+ * Receive a packet from a bridged peer device
-+ *
-+ * This is called from the bottom half. Must be careful.
-+ *
-+ * Results:
-+ * errno.
-+ *
-+ * Side effects:
-+ * A packet may be sent to the vnet.
-+ *
-+ *----------------------------------------------------------------------
-+ */
-+
-+#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 14) && \
-+ !defined(VMW_TL10S64_WORKAROUND)
-+int
-+VNetBridgeReceiveFromDev(struct sk_buff *skb, // IN: packet to receive
-+ struct net_device *dev, // IN: unused
-+ struct packet_type *pt) // IN: pt (pointer to bridge)
-+#else
-+int
-+VNetBridgeReceiveFromDev(struct sk_buff *skb, // IN: packet to receive
-+ struct net_device *dev, // IN: unused
-+ struct packet_type *pt, // IN: pt (pointer to bridge)
-+ struct net_device *real_dev) // IN: real device, unused
-+#endif
-+{
-+ VNetBridge *bridge = list_entry(pt, VNetBridge, pt);
-+ int i;
-+ unsigned long flags;
-+
-+ if (bridge->dev == NULL) {
-+ LOG(3, (KERN_DEBUG "bridge-%s: received %d closed\n",
-+ bridge->name, (int) skb->len));
-+ dev_kfree_skb(skb);
-+ return -EIO; // value is ignored anyway
-+ }
-+
-+ /*
-+ * Check is this is a packet that we sent up to the host, and if
-+ * so then don't bother to receive the packet.
-+ */
-+
-+ spin_lock_irqsave(&bridge->historyLock, flags);
-+ for (i = 0; i < VNET_BRIDGE_HISTORY; i++) {
-+ struct sk_buff *s = bridge->history[i];
-+ if (s != NULL &&
-+ (s == skb || SKB_IS_CLONE_OF(skb, s))) {
-+ bridge->history[i] = NULL;
-+ spin_unlock_irqrestore(&bridge->historyLock, flags);
-+ dev_kfree_skb(s);
-+ LOG(3, (KERN_DEBUG "bridge-%s: receive %d self %d\n",
-+ bridge->name, (int) skb->len, i));
-+ dev_kfree_skb(skb);
-+ return 0;
-+ }
-+ }
-+ spin_unlock_irqrestore(&bridge->historyLock, flags);
-+
-+# if LOGLEVEL >= 4
-+ {
-+ struct timeval now;
-+ do_gettimeofday(&now);
-+ LOG(3, (KERN_DEBUG "bridge-%s: time %d\n",
-+ bridge->name,
-+ (int)((now.tv_sec * 1000000 + now.tv_usec)
-+ - (vnetTime.tv_sec * 1000000 + vnetTime.tv_usec))));
-+ }
-+# endif
-+
-+ if (bridge->smac) {
-+ if (VNetCallSMACFunc(bridge->smac, &skb, compat_skb_mac_header(skb),
-+ SMAC_CheckPacketFromHost) !=
-+ PacketStatusForwardPacket) {
-+ LOG(4, (KERN_NOTICE "bridge-%s: packet dropped .\n",
-+ bridge->name));
-+ return 0;
-+ }
-+ }
-+
-+#ifdef KERNEL_2_3_15
-+ skb = skb_share_check(skb, GFP_ATOMIC);
-+ if (!skb) {
-+ return 0;
-+ }
-+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 4, 4)
-+ /*
-+ * Unbelievable... Caller sets h.raw = nh.raw before invoking us...
-+ */
-+ VNetBridgeComputeHeaderPos(skb);
-+#endif
-+#endif
-+
-+ skb_push(skb, skb->data - compat_skb_mac_header(skb));
-+ LOG(3, (KERN_DEBUG "bridge-%s: receive %d\n",
-+ bridge->name, (int) skb->len));
-+
-+ /*
-+ * If this is a large packet, chop chop chop (if supported)...
-+ */
-+ if (VNetBridgeIsGSO(skb)) {
-+ VNetBridgeSendLargePacket(skb, bridge);
-+ } else {
-+ VNetSend(&bridge->port.jack, skb);
-+ }
-+
-+ return 0;
-+}
-+
-+
-+/*
-+ *----------------------------------------------------------------------
-+ *
-+ * VNetBridgeProcRead --
-+ *
-+ * Callback for read operation on this bridge entry in vnets proc fs.
-+ *
-+ * Results:
-+ * Length of read operation.
-+ *
-+ * Side effects:
-+ * None.
-+ *
-+ *----------------------------------------------------------------------
-+ */
-+
-+int
-+VNetBridgeProcRead(char *page, // IN/OUT: buffer to write into
-+ char **start, // OUT: 0 if file < 4k, else offset into page
-+ off_t off, // IN: (unused) offset of read into the file
-+ int count, // IN: (unused) maximum number of bytes to read
-+ int *eof, // OUT: TRUE if there is nothing more to read
-+ void *data) // IN: client data - pointer to bridge
-+{
-+ VNetBridge *bridge = (VNetBridge*)data;
-+ int len = 0;
-+
-+ if (!bridge) {
-+ return len;
-+ }
-+
-+ len += VNetPrintPort(&bridge->port, page+len);
-+
-+ len += sprintf(page+len, "dev %s ", bridge->name);
-+
-+ len += sprintf(page+len, "\n");
-+
-+ *start = 0;
-+ *eof = 1;
-+ return len;
-+}
diff -Nur old/vmware-any-any-update117d/vmnet-only/vmnetInt.h new/vmware-any-any-update117d/vmnet-only/vmnetInt.h
--- old/vmware-any-any-update117d/vmnet-only/vmnetInt.h 2008-08-30 15:50:06.800648000 +0000
+++ new/vmware-any-any-update117d/vmnet-only/vmnetInt.h 2008-08-30 15:59:47.768956250 +0000
PF_NETLINK, _pri, &vmnet_proto)
#elif defined(VMW_HAVE_SK_ALLOC_WITH_PROTO)
extern struct proto vmnet_proto;
-diff -Nur old/vmware-any-any-update117d/vmnet-only/vmnetInt.h~ new/vmware-any-any-update117d/vmnet-only/vmnetInt.h~
---- old/vmware-any-any-update117d/vmnet-only/vmnetInt.h~ 1970-01-01 00:00:00.000000000 +0000
-+++ new/vmware-any-any-update117d/vmnet-only/vmnetInt.h~ 2008-08-30 15:49:59.016161500 +0000
-@@ -0,0 +1,157 @@
-+/* **********************************************************
-+ * Copyright 1998 VMware, Inc. All rights reserved. -- VMware Confidential
-+ * **********************************************************/
-+
-+#ifndef __VMNETINT_H__
-+#define __VMNETINT_H__
-+
-+
-+#define INCLUDE_ALLOW_MODULE
-+#include "includeCheck.h"
-+#include "driver-config.h"
-+
-+
-+/*
-+ * Hide all kernel compatibility stuff in those macros
-+ */
-+
-+/* All kernels above 2.6.23 have net namespaces. */
-+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 24) && !defined(VMW_NETDEV_HAS_NET)
-+# define VMW_NETDEV_HAS_NET
-+#endif
-+
-+/* All kernels above 2.6.23 have skb argument in nf_hookfn. */
-+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 24) && !defined(VMW_NFHOOK_USES_SKB)
-+# define VMW_NFHOOK_USES_SKB
-+#endif
-+
-+
-+#ifdef KERNEL_2_4_0
-+# define compat_fop_set_owner(_pFop) do { \
-+ (_pFop)->owner = THIS_MODULE; \
-+} while (0)
-+# define compat_mod_inc_refcount
-+# define compat_mod_dec_refcount
-+#else
-+# define compat_fop_set_owner(_pFop)
-+# define compat_mod_inc_refcount do { \
-+ MOD_INC_USE_COUNT; \
-+} while (0)
-+# define compat_mod_dec_refcount do { \
-+ MOD_DEC_USE_COUNT; \
-+} while (0)
-+#endif
-+
-+
-+#ifdef skb_shinfo
-+# define SKB_IS_CLONE_OF(clone, skb) ( \
-+ skb_shinfo(clone) == skb_shinfo(skb) \
-+ )
-+#else
-+# define SKB_IS_CLONE_OF(clone, skb) ( \
-+ skb_datarefp(clone) == skb_datarefp(skb) \
-+ )
-+#endif
-+#define DEV_QUEUE_XMIT(skb, dev, pri) ( \
-+ (skb)->dev = (dev), \
-+ (skb)->priority = (pri), \
-+ compat_skb_reset_mac_header(skb), \
-+ compat_skb_set_network_header(skb, sizeof (struct ethhdr)), \
-+ dev_queue_xmit(skb) \
-+ )
-+#ifdef KERNEL_2_3_15
-+# define dev_lock_list() read_lock(&dev_base_lock)
-+# define dev_unlock_list() read_unlock(&dev_base_lock)
-+# ifdef VMW_NETDEV_HAS_NET
-+# define DEV_GET(x) __dev_get_by_name(dev_net((x)->internalDev), (x)->name)
-+# else
-+# define DEV_GET(x) __dev_get_by_name((x)->name)
-+# endif
-+#else
-+# define DEV_GET(x) dev_get((x)->name)
-+#endif
-+
-+
-+/*
-+ * Various fields (including 'dead') of struct sock are replaced with the
-+ * 'flags' bitfield in 2.5.65, with sock_valbool_flag() to set flag's
-+ * value. Since 2.5.71 there is sock_set_flag() to set bit to 1, and
-+ * since 2.6.25-rc1 sock_valbool_flag() is gone.
-+ */
-+#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 5, 65)
-+# define SET_SK_DEAD(_sk) (_sk)->dead = 1
-+#elif LINUX_VERSION_CODE < KERNEL_VERSION(2, 5, 71)
-+# define SET_SK_DEAD(_sk) sock_valbool_flag(_sk, SOCK_DEAD, 1)
-+#else
-+# define SET_SK_DEAD(_sk) sock_set_flag(_sk, SOCK_DEAD)
-+#endif
-+
-+
-+#ifdef VMW_NETDEV_HAS_NET
-+extern struct proto vmnet_proto;
-+# define compat_sk_alloc(_bri, _pri) sk_alloc(dev_net((_bri)->internalDev), \
-+ PF_NETLINK, _pri, &vmnet_proto)
-+#elif defined(VMW_HAVE_SK_ALLOC_WITH_PROTO)
-+extern struct proto vmnet_proto;
-+# define compat_sk_alloc(_bri, _pri) sk_alloc(PF_NETLINK, _pri, &vmnet_proto, 1)
-+#elif defined(KERNEL_2_5_5)
-+# define compat_sk_alloc(_bri, _pri) sk_alloc(PF_NETLINK, _pri, 1, NULL)
-+#else
-+# define compat_sk_alloc(_bri, _pri) sk_alloc(0, _pri, 1)
-+#endif
-+
-+
-+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0)
-+# define fileTraversalLock(lock) spin_lock(lock)
-+# define fileTraversalUnLock(lock) spin_unlock(lock)
-+#elif LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0)
-+# define fileTraversalLock(lock) read_lock(lock)
-+# define fileTraversalUnLock(lock) read_unlock(lock)
-+#else //2.2 kernels
-+# define fileTraversalLock(lock) lock_kernel()
-+# define fileTraversalUnLock(lock) unlock_kernel()
-+#endif
-+
-+
-+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0)
-+# define taskLock(lock) task_lock(lock)
-+# define taskUnLock(lock) task_unlock(lock)
-+#else //2.2 kernels
-+# define taskLock(lock) lock_kernel()
-+# define taskUnLock(lock) unlock_kernel()
-+#endif
-+
-+
-+/*
-+ * Use CHECKSUM_HW for old kernels, if they have CHECKSUM_HW. Use CHECKSUM_PARTIAL for
-+ * new ones even if CHECKSUM_HW is defined. We do not do decision based on kernel version
-+ * only as CHECKSUM_PARTIAL was in mm tree for some time already, and we do not test
-+ * for CHECKSUM_PARTIAL existence as it may get converted to enum in future.
-+ */
-+#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 19) && defined(CHECKSUM_HW)
-+# define VM_CHECKSUM_PARTIAL CHECKSUM_HW
-+#else
-+# define VM_CHECKSUM_PARTIAL CHECKSUM_PARTIAL
-+#endif
-+
-+
-+/*
-+ * The "owner" field in nf_hook_ops got added in 2.5.69
-+ */
-+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 5, 69)
-+# define compat_nf_hook_owner .owner = THIS_MODULE,
-+#else
-+# define compat_nf_hook_owner
-+#endif
-+
-+
-+#ifdef NF_IP_LOCAL_IN
-+#define VMW_NF_INET_LOCAL_IN NF_IP_LOCAL_IN
-+#define VMW_NF_INET_POST_ROUTING NF_IP_POST_ROUTING
-+#else
-+#define VMW_NF_INET_LOCAL_IN NF_INET_LOCAL_IN
-+#define VMW_NF_INET_POST_ROUTING NF_INET_POST_ROUTING
-+#endif
-+
-+
-+#endif /* __VMNETINT_H__ */