Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- root@a1-MS-7885:~/vmware-patch-temp# patch -p1 < vmware-patch.diff
- patching file vmmon-only/include/pgtbl.h
- Hunk #1 FAILED at 58.
- Hunk #2 FAILED at 68.
- Hunk #3 FAILED at 77.
- Hunk #4 FAILED at 86.
- 4 out of 4 hunks FAILED -- saving rejects to file vmmon-only/include/pgtbl.h.rej
- patching file vmnet-only/bridge.c
- Hunk #1 FAILED at 581.
- Hunk #2 FAILED at 894.
- Hunk #3 FAILED at 1410.
- 3 out of 3 hunks FAILED -- saving rejects to file vmnet-only/bridge.c.rej
- root@a1-MS-7885:~/vmware-patch-temp# cat root@a1-MS-7885:~/vmware-patch-temp# ll
- total 2372
- drwxr-xr-x 4 root root 4096 ноя 4 02:57 ./
- drwx------ 9 root root 4096 ноя 4 02:56 ../
- drwxr-xr-x 7 root root 4096 ноя 16 2022 vmmon-only/
- -rw-r--r-- 1 root root 1628160 ноя 4 02:54 vmmon.tar
- drwxr-xr-x 2 root root 4096 ноя 16 2022 vmnet-only/
- -rw-r--r-- 1 root root 778240 ноя 4 02:54 vmnet.tar
- -rw-r--r-- 1 root root 1844 ноя 4 02:55 vmware-patch.diff
- root@a1-MS-7885:~/vmware-patch-temp# pwd
- /root/vmware-patch-temp
- root@a1-MS-7885:~/vmware-patch-temp# patch -p0 < vmware-patch.diff
- can't find file to patch at input line 3
- Perhaps you used the wrong -p or --strip option?
- The text leading up to this was:
- --------------------------
- |--- a/vmmon-only/include/pgtbl.h
- |+++ b/vmmon-only/include/pgtbl.h
- ---------------------^C
- root@a1-MS-7885:~/vmware-patch-temp# cat vmmon-only/include/pgtbl.h.rej
- --- vmmon-only/include/pgtbl.h
- +++ vmmon-only/include/pgtbl.h
- @@ -58,7 +58,7 @@
- if (!pgd_present(*pgd)) {
- return INVALID_MPN;
- }
- - if (pgd_large(*pgd)) {
- + if (pgd_page(*pgd) && pgd_large(*pgd)) {
- return (pgd_pfn(*pgd) << PAGE_SHIFT) + (va & I915_GTT_PAGE_MASK);
- }
- @@ -68,7 +68,7 @@
- if (!compat_p4d_present(*p4d)) {
- return INVALID_MPN;
- }
- - if (compat_p4d_large(*p4d)) {
- + if (p4d_page(*p4d) && compat_p4d_large(*p4d)) {
- return (compat_p4d_pfn(*p4d) << PAGE_SHIFT) + (va & I915_GTT_PAGE_MASK);
- }
- @@ -77,7 +77,7 @@
- if (!pud_present(*pud)) {
- return INVALID_MPN;
- }
- - if (pud_large(*pud)) {
- + if (pud_page(*pud) && pud_large(*pud)) {
- return (pud_pfn(*pud) << PAGE_SHIFT) + (va & I915_GTT_PAGE_MASK);
- }
- @@ -86,7 +86,7 @@
- if (!pmd_present(*pmd)) {
- return INVALID_MPN;
- }
- - if (pmd_large(*pmd)) {
- + if (pmd_page(*pmd) && pmd_large(*pmd)) {
- return (pmd_pfn(*pmd) << PAGE_SHIFT) + (va & I915_GTT_PAGE_MASK);
- }
- root@a1-MS-7885:~/vmware-patch-temp# cat vmmon-only/include/pgtbl.h
- /*********************************************************
- * Copyright (C) 2002,2014-2017 VMware, Inc. All rights reserved.
- *
- * 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 version 2 and no later version.
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
- * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
- * for more details.
- *
- * You should have received a copy of the GNU General Public License along
- * with this program; if not, write to the Free Software Foundation, Inc.,
- * 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
- *
- *********************************************************/
- #ifndef __PGTBL_H__
- # define __PGTBL_H__
- #include <linux/highmem.h>
- #include "compat_pgtable.h"
- #include "compat_spinlock.h"
- #include "compat_page.h"
- /*
- *-----------------------------------------------------------------------------
- *
- * PgtblVa2MPNLocked --
- *
- * Walks through the hardware page tables to try to find the pte
- * associated to a virtual address. Then maps PTE to MPN.
- *
- * Results:
- * INVALID_MPN on failure
- * mpn on success
- *
- * Side effects:
- * None
- *
- *-----------------------------------------------------------------------------
- */
- static INLINE MPN
- PgtblVa2MPNLocked(struct mm_struct *mm, // IN: Mm structure of a process
- VA addr) // IN: Address in the virtual address
- // space of that process
- {
- pgd_t *pgd;
- compat_p4d_t *p4d;
- MPN mpn;
- pgd = pgd_offset(mm, addr);
- if (pgd_present(*pgd) == 0) {
- return INVALID_MPN;
- }
- if (pgd_large(*pgd)) {
- /* Linux kernel does not support PGD huge pages. */
- /* return pgd_pfn(*pgd) + ((addr & PGD_MASK) >> PAGE_SHIFT); */
- return INVALID_MPN;
- }
- p4d = compat_p4d_offset(pgd, addr);
- if (compat_p4d_present(*p4d) == 0) {
- return INVALID_MPN;
- }
- if (compat_p4d_large(*p4d)) {
- mpn = compat_p4d_pfn(*p4d) + ((addr & ~COMPAT_P4D_MASK) >> PAGE_SHIFT);
- } else {
- pud_t *pud;
- pud = pud_offset(p4d, addr);
- if (pud_present(*pud) == 0) {
- return INVALID_MPN;
- }
- if (pud_large(*pud)) {
- mpn = pud_pfn(*pud) + ((addr & ~PUD_MASK) >> PAGE_SHIFT);
- } else {
- pmd_t *pmd;
- pmd = pmd_offset(pud, addr);
- if (pmd_present(*pmd) == 0) {
- return INVALID_MPN;
- }
- if (pmd_large(*pmd)) {
- mpn = pmd_pfn(*pmd) + ((addr & ~PMD_MASK) >> PAGE_SHIFT);
- } else {
- pte_t *pte;
- pte = pte_offset_map(pmd, addr);
- if (pte_present(*pte) == 0) {
- pte_unmap(pte);
- return INVALID_MPN;
- }
- mpn = pte_pfn(*pte);
- pte_unmap(pte);
- }
- }
- }
- if (mpn >= INVALID_MPN) {
- mpn = INVALID_MPN;
- }
- return mpn;
- }
- /*
- *-----------------------------------------------------------------------------
- *
- * PgtblVa2MPN --
- *
- * Walks through the hardware page tables of the current process to try to
- * find the page structure associated to a virtual address.
- *
- * Results:
- * Same as PgtblVa2MPNLocked()
- *
- * Side effects:
- * None
- *
- *-----------------------------------------------------------------------------
- */
- static INLINE MPN
- PgtblVa2MPN(VA addr) // IN
- {
- struct mm_struct *mm;
- MPN mpn;
- /* current->mm is NULL for kernel threads, so use active_mm. */
- mm = current->active_mm;
- spin_lock(&mm->page_table_lock);
- mpn = PgtblVa2MPNLocked(mm, addr);
- spin_unlock(&mm->page_table_lock);
- return mpn;
- }
- #endif /* __PGTBL_H__ */
- root@a1-MS-7885:~/vmware-patch-temp# cat vmnet-only/bridge.c
- /*********************************************************
- * Copyright (C) 1998-2013, 2017, 2022 VMware, Inc. All rights reserved.
- *
- * 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 version 2 and no later version.
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
- * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
- * for more details.
- *
- * You should have received a copy of the GNU General Public License along
- * with this program; if not, write to the Free Software Foundation, Inc.,
- * 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
- *
- *********************************************************/
- #include "driver-config.h"
- #define EXPORT_SYMTAB
- #include <linux/kernel.h>
- #include <linux/version.h>
- #include <linux/sched.h>
- #include <linux/slab.h>
- #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 <linux/spinlock.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 <linux/if_arp.h>
- #include <net/tcp.h>
- #include <net/ipv6.h>
- #ifdef CONFIG_NET_RADIO
- # include <linux/wireless.h>
- #endif
- #include "vmnetInt.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 forceSmac; // whether to use smac unconditionally
- 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
- VNetEvent_Sender *eventSender; // event sender
- };
- 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);
- static int VNetBridgeReceiveFromDev(struct sk_buff *skb,
- struct net_device *dev,
- struct packet_type *pt,
- struct net_device *real_dev);
- 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);
- static void VNetBridgeComputeHeaderPosIPv6(struct sk_buff *skb);
- static PacketStatus VNetCallSMACFunc(struct SMACState *state,
- struct sk_buff **skb, void *startOfData,
- SMACFunc func, unsigned int len);
- /*
- *----------------------------------------------------------------------
- *
- * 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;
- 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();
- }
- }
- /*
- *----------------------------------------------------------------------
- *
- * 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
- {
- if (dev_net(net) != &init_net) {
- return 0;
- }
- return strcmp(net->name, bridge->name) == 0;
- }
- /*
- *----------------------------------------------------------------------
- *
- * VNetBridge_Create --
- *
- * Creates a bridge. Allocates struct, allocates internal device,
- * initializes port/jack, and creates a proc entry. Finally, creates an
- * event sender and register itself with the kernel for device state
- * change notifications.
- *
- * At this time the bridge is not yet plugged into the hub, because this
- * will be done by the caller, i.e. the driver. But we need to know the
- * hub in order to create an event sender. This allows for enabling
- * the notification mechanism, which will instantly start firing, which in
- * turn will bring up the bridge (if present), which eventually will
- * inject bridge events. Moreover, the bridge will start injecting
- * packets, which will be dropped on the floor. All in all, this is not
- * that elegant. Alternatively, we could (i) plug into the hub inside of
- * this function, which would require adding a few parameters, (ii) split
- * the function into a create part and a registration part. Both ways are
- * not consistent with how driver.c plugs the ports into the hub.
- *
- * Results:
- * Errno. Also returns an allocated jack to connect to,
- * NULL on error.
- *
- * Side effects:
- * None.
- *
- *----------------------------------------------------------------------
- */
- int
- VNetBridge_Create(const char *devName, // IN: name of device (e.g., "eth0")
- uint32 flags, // IN: configuration flags
- VNetJack *hubJack, // IN: the future hub
- 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;
- }
- /* complain about unknown/unsupported flags */
- if (flags & ~VNET_BRFLAG_FORCE_SMAC) {
- 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);
- /*
- * 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(bridge->port.jack.name, S_IFREG, bridge,
- VNetBridgeProcRead,
- &bridge->port.jack.procEntry);
- if (retval) {
- if (retval == -ENXIO) {
- bridge->port.jack.procEntry = NULL;
- } else {
- goto out;
- }
- }
- /*
- * 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;
- /* misc. configuration */
- bridge->forceSmac = (flags & VNET_BRFLAG_FORCE_SMAC) ? TRUE : FALSE;
- /* create event sender */
- retval = VNetHub_CreateSender(hubJack, &bridge->eventSender);
- if (retval != 0) {
- goto out;
- }
- /*
- * on RHEL3 Linux 2.4.21-47 (others maybe too) the notifier does not fire
- * and bring up the bridge as expected, thus we bring it up manually
- * *before* registering the notifier (PR306435)
- */
- VNetBridgeUp(bridge, TRUE);
- /*
- * register notifier for network device state change notifications, the
- * notifier will fire right away, and the notifier handler will bring up
- * the bridge (see exception above)
- */
- bridge->notifier.notifier_call = VNetBridgeNotify;
- bridge->notifier.priority = 0;
- register_netdevice_notifier(&bridge->notifier);
- /* return bridge */
- *ret = &bridge->port;
- LOG(1, (KERN_DEBUG "bridge-%s: attached\n", bridge->name));
- return 0;
- out:
- if (bridge != NULL) {
- kfree(bridge);
- }
- return retval;
- }
- /*
- *----------------------------------------------------------------------
- *
- * VNetBridgeFree --
- *
- * Unregister from device state notifications, disable the bridge,
- * destroy sender, remove proc entry, cleanup smac, and deallocate
- * struct.
- *
- * Results:
- * None.
- *
- * Side effects:
- * None.
- *
- *----------------------------------------------------------------------
- */
- void
- VNetBridgeFree(VNetJack *this) // IN: jack to free
- {
- VNetBridge *bridge = (VNetBridge*)this->private;
- /* unregister notifier */
- if (bridge->notifier.notifier_call != NULL) {
- int err;
- err = compat_unregister_netdevice_notifier(&bridge->notifier);
- if (err != 0) {
- LOG(0, (KERN_NOTICE "Can't unregister netdevice notifier (%d)\n",
- err));
- }
- bridge->notifier.notifier_call = NULL;
- }
- /* disable bridge */
- if (bridge->dev != NULL) {
- LOG(1, (KERN_DEBUG "bridge-%s: disabling the bridge\n", bridge->name));
- VNetBridgeDown(bridge, TRUE);
- }
- /* destroy event sender */
- VNetEvent_DestroySender(bridge->eventSender);
- bridge->eventSender = NULL;
- /* remove /proc entry */
- if (this->procEntry) {
- VNetProc_RemoveEntry(this->procEntry);
- }
- if (bridge->smac){
- SMAC_CleanupState(&(bridge->smac));
- }
- /* free bridge */
- LOG(1, (KERN_DEBUG "bridge-%s: detached\n", bridge->name));
- kfree(bridge);
- }
- /*
- *----------------------------------------------------------------------
- *
- * VNetCallSMACFunc --
- *
- * Wrapper for SMAC functions. The skb must be linear.
- *
- * Results:
- * Packet Status.
- *
- * Side effects:
- * The skb buffer is freed if not successful otherwise it points to
- * the clone.
- *
- *----------------------------------------------------------------------
- */
- static 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
- unsigned int len) // IN: length including ETH header
- {
- SMACPackets packets = { {0} };
- PacketStatus status;
- SKB_LINEAR_ASSERT(*skb);
- packets.orig.skb = *skb;
- packets.orig.startOfData = startOfData;
- packets.orig.len = len;
- 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);
- #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
- /*
- * SMAC processing. SMAC interfaces that the skb is linear, so ensure that
- * this is the case prior to calling out.
- */
- if (bridge->smac) {
- if (compat_skb_is_nonlinear(skb) && compat_skb_linearize(skb)) {
- LOG(4, (KERN_NOTICE "bridge-%s: couldn't linearize, packet dropped\n",
- bridge->name));
- return;
- }
- if (VNetCallSMACFunc(bridge->smac, &skb, skb->data,
- SMAC_CheckPacketToHost, skb->len) !=
- 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 {
- skb_set_owner_w(clone, bridge->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, NULL, 0, allMultiFilter, dev->flags)) {
- clone = skb_clone(skb, GFP_ATOMIC);
- if (clone) {
- unsigned long flags;
- int i;
- clone = skb_get(clone);
- 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);
- #if LINUX_VERSION_CODE < KERNEL_VERSION(5, 18, 0)
- netif_rx_ni(clone);
- #else
- netif_rx(clone);
- #endif
- # 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_WIRELESS_EXT)
- return dev->ieee80211_ptr != NULL || dev->wireless_handlers != NULL;
- #elif LINUX_VERSION_CODE < KERNEL_VERSION(5, 19, 0) || IS_ENABLED(CONFIG_CFG80211)
- return dev->ieee80211_ptr != NULL;
- #else
- return FALSE;
- #endif
- }
- /*
- *----------------------------------------------------------------------
- *
- * VNetBridgeSendLinkStateEvent --
- *
- * Sends a link state event.
- *
- * Results:
- * Returns 0 if successful, or a negative value if an error occurs.
- *
- * Side effects:
- * None.
- *
- *----------------------------------------------------------------------
- */
- static int
- VNetBridgeSendLinkStateEvent(VNetBridge *bridge, // IN: the bridge
- uint32 adapter, // IN: the adapter
- Bool up) // IN: the link state
- {
- VNet_LinkStateEvent event;
- int res;
- event.header.size = sizeof event;
- res = VNetEvent_GetSenderId(bridge->eventSender, &event.header.senderId);
- if (res != 0) {
- LOG(1, (KERN_NOTICE "bridge-%s: can't send link state event, "
- "getSenderId failed (%d)\n", bridge->name, res));
- return res;
- }
- event.header.eventId = 0;
- event.header.classSet = VNET_EVENT_CLASS_UPLINK;
- event.header.type = VNET_EVENT_TYPE_LINK_STATE;
- event.adapter = adapter;
- event.up = up;
- res = VNetEvent_Send(bridge->eventSender, &event.header);
- if (res != 0) {
- LOG(1, (KERN_NOTICE "bridge-%s: can't send link state event, send "
- "failed (%d)\n", bridge->name, res));
- }
- return res;
- }
- /*
- *----------------------------------------------------------------------
- *
- * 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.
- *
- *----------------------------------------------------------------------
- */
- static 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_by_name(&init_net, bridge->name);
- 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;
- }
- if (bridge->dev->type != ARPHRD_ETHER) {
- LOG(1, (KERN_DEBUG "bridge-%s: can't bridge with %s (header length %d, "
- "type %d).\n", bridge->name, bridge->dev->name,
- bridge->dev->hard_header_len, bridge->dev->type));
- 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;
- }
- sock_init_data(NULL, bridge->sk);
- sock_set_flag(bridge->sk, SOCK_DEAD);
- if (VNetBridgeIsDeviceWireless(bridge->dev)) {
- LOG(1, (KERN_NOTICE "bridge-%s: device is wireless, enabling SMAC\n",
- bridge->name));
- bridge->wirelessAdapter = TRUE;
- }
- /*
- * If it is a wireless adapter initialize smac struct.
- */
- if (bridge->wirelessAdapter || bridge->forceSmac) {
- 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;
- bridge->pt.af_packet_priv = bridge->sk;
- bridge->enabledPromisc = FALSE;
- dev_add_pack(&bridge->pt);
- dev_unlock_list();
- /*
- * Put in promiscuous mode if need be.
- */
- mutex_lock(&vnetStructureMutex);
- if (VNetGetAttachedPorts(&bridge->port.jack)) {
- VNetBridgeStartPromisc(bridge, rtnlLock);
- }
- mutex_unlock(&vnetStructureMutex);
- /* send link state up event */
- retval = VNetBridgeSendLinkStateEvent(bridge, bridge->dev->ifindex, TRUE);
- if (retval != 0) {
- LOG(1, (KERN_NOTICE "bridge-%s: can't send link state event (%d)\n",
- bridge->name, retval));
- goto out;
- }
- 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.
- *
- *----------------------------------------------------------------------
- */
- static void
- VNetBridgeDown(VNetBridge *bridge, // IN: bridge
- Bool rtnlLock) // IN: acquire RTNL lock
- {
- int retval;
- if (bridge->dev == NULL) {
- LOG(0, (KERN_NOTICE "bridge-%s: already down\n", bridge->name));
- return;
- }
- /* send link state down event */
- retval = VNetBridgeSendLinkStateEvent(bridge, bridge->dev->ifindex, FALSE);
- if (retval != 0) {
- LOG(1, (KERN_NOTICE "bridge-%s: can't send link state event (%d)\n",
- bridge->name, retval));
- }
- 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));
- }
- /*
- *-----------------------------------------------------------------------------
- *
- * VNetBridgeNotifyLogBridgeUpError --
- *
- * Logs a bridge up error for the notify function following this function.
- *
- * Results:
- * None.
- *
- * Side effects:
- * None.
- *
- *-----------------------------------------------------------------------------
- */
- static void
- VNetBridgeNotifyLogBridgeUpError(int errno, // IN: the error number
- char *bridgeName, // IN: the bridge name
- char *devName) // IN: the device name
- {
- switch (errno) {
- case -ENODEV:
- LOG(0, (KERN_WARNING "bridge-%s: interface %s not found or not "
- "up\n", bridgeName, devName));
- break;
- case -EINVAL:
- LOG(0, (KERN_WARNING "bridge-%s: interface %s is not a valid "
- "Ethernet interface\n", bridgeName, devName));
- break;
- case -ENOMEM:
- LOG(0, (KERN_WARNING "bridge-%s: failed to allocate memory\n",
- bridgeName));
- break;
- default:
- /* This should never happen --hpreg */
- LOG(0, (KERN_WARNING "bridge-%s: failed to enable the bridge to "
- "interface %s (error %d)\n", bridgeName, devName,
- -errno));
- break;
- }
- }
- /*
- *-----------------------------------------------------------------------------
- *
- * 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.
- *
- *-----------------------------------------------------------------------------
- */
- static int
- VNetBridgeNotify(struct notifier_block *this, // IN: callback data (bridge)
- u_long msg, // IN: type of event
- void *data) // IN: net_device or notifier info
- {
- VNetBridge *bridge = list_entry(this, VNetBridge, notifier);
- struct net_device *dev;
- #if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 11, 0)
- dev = netdev_notifier_info_to_dev(data);
- #else
- dev = (struct net_device *)data;
- #endif
- 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 on dev down\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 on dev up\n",
- bridge->name));
- errno = VNetBridgeUp(bridge, FALSE);
- if (errno != 0) {
- VNetBridgeNotifyLogBridgeUpError(errno, bridge->name, dev->name);
- }
- }
- 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;
- }
- /*
- *----------------------------------------------------------------------
- *
- * RangeInLinearSKB --
- *
- * Checks if the given number of bytes from a given offset resides
- * within the linear part of the skb. If not then attempts to
- * linearize the skb.
- *
- * Results:
- * Returns TRUE if the range of bytes is already in the linear
- * portion or if linearize succeeded. Otherwise, returns FALSE if
- * the linearize operation fails.
- *
- * Side effects:
- * As in skb_linearize().
- *
- *----------------------------------------------------------------------
- */
- static INLINE_SINGLE_CALLER Bool
- RangeInLinearSKB(struct sk_buff *skb, // IN:
- unsigned int start, // IN: Start offset
- unsigned int length) // IN: How many bytes
- {
- if (LIKELY(!compat_skb_is_nonlinear(skb) ||
- start + length <= compat_skb_headlen(skb))) {
- /*
- * Nothing to do.
- */
- return TRUE;
- }
- return compat_skb_linearize(skb) == 0;
- }
- /*
- * Not all kernel versions have NEXTHDR_MOBILITY defined.
- */
- #ifndef NEXTHDR_MOBILITY
- # define NEXTHDR_MOBILITY 135 /* Mobility header. */
- #endif
- /*
- *----------------------------------------------------------------------
- *
- * VNetBridgeComputeHeaderPosIPv6 --
- *
- * Compute correct position of transport header in IPv6 packets.
- *
- * Results:
- * None.
- *
- * Side effects:
- * Transport header pointer updated to point to the PDU contained
- * in the packet.
- *
- *----------------------------------------------------------------------
- */
- static void
- VNetBridgeComputeHeaderPosIPv6(struct sk_buff *skb) // IN:
- {
- struct ipv6hdr *ipv6Hdr;
- unsigned int offset; /* Offset from skb->data. */
- unsigned int headerLen; /* Length of current header. */
- uint8 nextHeader;
- /*
- * Check if the start of the network header is within the linear part of
- * skb. If not, then linearize the skb.
- */
- if (UNLIKELY(compat_skb_network_header(skb) < skb->data ||
- compat_skb_network_header(skb) >= skb->data +
- compat_skb_headlen(skb))) {
- if (compat_skb_linearize(skb)) {
- return; /* Bail out. */
- }
- }
- offset = compat_skb_network_offset(skb);
- if (!RangeInLinearSKB(skb, offset, sizeof *ipv6Hdr)) {
- return; /* Bail out. */
- }
- ipv6Hdr = (struct ipv6hdr *)compat_skb_network_header(skb);
- headerLen = sizeof *ipv6Hdr;
- offset += headerLen; /* End of IPv6 header (not including extensions). */
- /*
- * All IPv6 extension headers begin with a "next header" field (one byte),
- * and most of them have a "header length" field (as the 2nd byte). In each
- * iteration, we find the length of the extension header and add it to
- * offset from the beginning of skb. And, in each iteration we update the
- * next header variable. When we return from the following for loop, offset
- * would have incremented by the length of each of the extension header,
- * and next header type will be something else than an IPv6 extension header
- * signifying that we have walked through the entire IPv6 header. We set
- * the transport header's offset to the value of this offset before exiting
- * the for loop.
- */
- nextHeader = ipv6Hdr->nexthdr;
- for (;;) {
- switch (nextHeader) {
- case NEXTHDR_HOP:
- case NEXTHDR_ROUTING:
- case NEXTHDR_AUTH:
- case NEXTHDR_DEST:
- case NEXTHDR_MOBILITY:
- /*
- * We need to check two bytes in the option header: next header and
- * header extension length.
- */
- if (!RangeInLinearSKB(skb, offset, 2)) {
- return; /* Bail out. */
- }
- headerLen = skb->data[offset + 1];
- if (nextHeader == NEXTHDR_AUTH) {
- headerLen = (headerLen + 2) << 2; /* See RFC 2402. */
- } else {
- headerLen = (headerLen + 1) << 3; /* See ipv6_optlen(). */
- }
- break;
- case NEXTHDR_FRAGMENT:
- case NEXTHDR_ESP:
- case NEXTHDR_NONE:
- /*
- * We stop walking if we find the fragment header (NEXTHDR_FRAGMENT).
- * If the payload is encrypted we may not know the start of the
- * transport header [1]. So, we just return. Same applies when
- * nothing follows this header (NEXTHDR_NONE).
- * [1]: http://www.cu.ipv6tf.org/literatura/chap8.pdf
- */
- return;
- default:
- /*
- * We have walked through all IPv6 extension headers. Let's set the
- * transport header and return.
- */
- compat_skb_set_transport_header(skb, offset);
- return;
- }
- nextHeader = skb->data[offset];
- offset += headerLen;
- }
- }
- /*
- *----------------------------------------------------------------------
- *
- * 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);
- break;
- }
- case ETH_P_IPV6:
- VNetBridgeComputeHeaderPosIPv6(skb);
- break;
- default:
- LOG(3, (KERN_DEBUG "Unknown EII protocol %04X: csum at %d\n",
- be16_to_cpu(skb->protocol), compat_skb_csum_offset(skb)));
- break;
- }
- }
- /*
- *----------------------------------------------------------------------
- *
- * 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 = skb_gso_segment(skb, 0);
- 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.
- *
- *----------------------------------------------------------------------
- */
- 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
- {
- 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
- /*
- * SMAC might linearize the skb, but linearizing a shared skb is a no-no,
- * so check for sharing before calling out to SMAC.
- */
- skb = skb_share_check(skb, GFP_ATOMIC);
- if (!skb) {
- return 0;
- }
- if (bridge->smac) {
- /*
- * Wireless driver processes the packet and processes the ethernet header
- * and the length is reduced by the amount. We need the raw ethernet
- * packet length hence add the ethernet header length for incoming
- * packets.
- *
- * Note that SMAC interfaces assume skb linearity.
- */
- if (compat_skb_is_nonlinear(skb) && compat_skb_linearize(skb)) {
- LOG(4, (KERN_NOTICE "bridge-%s: couldn't linearize, packet dropped\n",
- bridge->name));
- return 0;
- }
- if (VNetCallSMACFunc(bridge->smac, &skb, compat_skb_mac_header(skb),
- SMAC_CheckPacketFromHost, skb->len + ETH_HLEN) !=
- PacketStatusForwardPacket) {
- LOG(4, (KERN_NOTICE "bridge-%s: packet dropped\n", bridge->name));
- return 0;
- }
- }
- /*
- * Unbelievable... Caller sets h.raw = nh.raw before invoking us...
- */
- VNetBridgeComputeHeaderPos(skb);
- 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 (skb_shinfo(skb)->gso_size) {
- 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;
- }
- root@a1-MS-7885:~/vmware-patch-temp# ^C
- root@a1-MS-7885:~/vmware-patch-temp# ll
- total 2372
- drwxr-xr-x 4 root root 4096 ноя 4 02:57 ./
- drwx------ 9 root root 4096 ноя 4 02:56 ../
- drwxr-xr-x 7 root root 4096 ноя 16 2022 vmmon-only/
- -rw-r--r-- 1 root root 1628160 ноя 4 02:54 vmmon.tar
- drwxr-xr-x 2 root root 4096 ноя 4 03:00 vmnet-only/
- -rw-r--r-- 1 root root 778240 ноя 4 02:54 vmnet.tar
- -rw-r--r-- 1 root root 1844 ноя 4 02:55 vmware-patch.diff
- root@a1-MS-7885:~/vmware-patch-temp# cat vm
- vmmon-only/ vmmon.tar vmnet-only/ vmnet.tar vmware-patch.diff
- root@a1-MS-7885:~/vmware-patch-temp# cat vmware-patch.diff
- --- a/vmmon-only/include/pgtbl.h
- +++ b/vmmon-only/include/pgtbl.h
- @@ -58,7 +58,7 @@
- if (!pgd_present(*pgd)) {
- return INVALID_MPN;
- }
- - if (pgd_large(*pgd)) {
- + if (pgd_page(*pgd) && pgd_large(*pgd)) {
- return (pgd_pfn(*pgd) << PAGE_SHIFT) + (va & I915_GTT_PAGE_MASK);
- }
- @@ -68,7 +68,7 @@
- if (!compat_p4d_present(*p4d)) {
- return INVALID_MPN;
- }
- - if (compat_p4d_large(*p4d)) {
- + if (p4d_page(*p4d) && compat_p4d_large(*p4d)) {
- return (compat_p4d_pfn(*p4d) << PAGE_SHIFT) + (va & I915_GTT_PAGE_MASK);
- }
- @@ -77,7 +77,7 @@
- if (!pud_present(*pud)) {
- return INVALID_MPN;
- }
- - if (pud_large(*pud)) {
- + if (pud_page(*pud) && pud_large(*pud)) {
- return (pud_pfn(*pud) << PAGE_SHIFT) + (va & I915_GTT_PAGE_MASK);
- }
- @@ -86,7 +86,7 @@
- if (!pmd_present(*pmd)) {
- return INVALID_MPN;
- }
- - if (pmd_large(*pmd)) {
- + if (pmd_page(*pmd) && pmd_large(*pmd)) {
- return (pmd_pfn(*pmd) << PAGE_SHIFT) + (va & I915_GTT_PAGE_MASK);
- }
- --- a/vmnet-only/bridge.c
- +++ b/vmnet-only/bridge.c
- @@ -581,7 +581,7 @@
- struct net_device *dev;
- int numDevs = 0;
- - dev_lock_list();
- + rtnl_lock();
- for_each_netdev(&init_net, dev) {
- if (dev->flags & IFF_UP) {
- numDevs++;
- @@ -894,7 +894,7 @@
- struct net_device *dev;
- Bool success = TRUE;
- - dev_lock_list();
- + rtnl_lock();
- for_each_netdev(&init_net, dev) {
- if (strcmp(dev->name, bridge->devName) == 0) {
- success = VNetBridgeStartDevice(bridge, dev);
- @@ -1410,7 +1410,7 @@
- struct sk_buff *segs;
- int ret = 0;
- - segs = skb_gso_segment(skb, 0);
- + segs = skb_gso_segment(skb, dev->features & ~NETIF_F_GSO_MASK);
- if (IS_ERR(segs)) {
- ret = PTR_ERR(segs);
- } else {
- root@a1-MS-7885:~/vmware-patch-temp#
Add Comment
Please, Sign In to add comment