f86f2dc613a22ee06add9b878197922466df641bvboxsync/* $Id$ */
f86f2dc613a22ee06add9b878197922466df641bvboxsync/** @file
f86f2dc613a22ee06add9b878197922466df641bvboxsync * VBoxNetAdp - Virtual Network Adapter Driver (Host), Common Code.
f86f2dc613a22ee06add9b878197922466df641bvboxsync */
f86f2dc613a22ee06add9b878197922466df641bvboxsync
f86f2dc613a22ee06add9b878197922466df641bvboxsync/*
c0b6af690ad705bddfa87c643b89770a7a0aaf5avboxsync * Copyright (C) 2008-2014 Oracle Corporation
f86f2dc613a22ee06add9b878197922466df641bvboxsync *
f86f2dc613a22ee06add9b878197922466df641bvboxsync * This file is part of VirtualBox Open Source Edition (OSE), as
f86f2dc613a22ee06add9b878197922466df641bvboxsync * available from http://www.virtualbox.org. This file is free software;
f86f2dc613a22ee06add9b878197922466df641bvboxsync * you can redistribute it and/or modify it under the terms of the GNU
f86f2dc613a22ee06add9b878197922466df641bvboxsync * General Public License (GPL) as published by the Free Software
f86f2dc613a22ee06add9b878197922466df641bvboxsync * Foundation, in version 2 as it comes in the "COPYING" file of the
f86f2dc613a22ee06add9b878197922466df641bvboxsync * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
f86f2dc613a22ee06add9b878197922466df641bvboxsync * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
f86f2dc613a22ee06add9b878197922466df641bvboxsync */
f86f2dc613a22ee06add9b878197922466df641bvboxsync
2a047f0d7ee5964456dbc4dec9925031482588abvboxsync/** @page pg_netadp VBoxNetAdp - Network Adapter
2a047f0d7ee5964456dbc4dec9925031482588abvboxsync *
2a047f0d7ee5964456dbc4dec9925031482588abvboxsync * This is a kernel module that creates a virtual interface that can be attached
2a047f0d7ee5964456dbc4dec9925031482588abvboxsync * to an internal network.
2a047f0d7ee5964456dbc4dec9925031482588abvboxsync *
2a047f0d7ee5964456dbc4dec9925031482588abvboxsync * In the big picture we're one of the three trunk interface on the internal
2a047f0d7ee5964456dbc4dec9925031482588abvboxsync * network, the one named "TAP Interface": @image html Networking_Overview.gif
2a047f0d7ee5964456dbc4dec9925031482588abvboxsync *
2a047f0d7ee5964456dbc4dec9925031482588abvboxsync */
2a047f0d7ee5964456dbc4dec9925031482588abvboxsync
40c9dcdf4b9d1c60dc67fa671b7a689b3c0f84d4vboxsync/*******************************************************************************
40c9dcdf4b9d1c60dc67fa671b7a689b3c0f84d4vboxsync* Header Files *
40c9dcdf4b9d1c60dc67fa671b7a689b3c0f84d4vboxsync*******************************************************************************/
2a047f0d7ee5964456dbc4dec9925031482588abvboxsync#define LOG_GROUP LOG_GROUP_NET_ADP_DRV
f86f2dc613a22ee06add9b878197922466df641bvboxsync#include "VBoxNetAdpInternal.h"
f86f2dc613a22ee06add9b878197922466df641bvboxsync
f86f2dc613a22ee06add9b878197922466df641bvboxsync#include <VBox/log.h>
f86f2dc613a22ee06add9b878197922466df641bvboxsync#include <VBox/err.h>
f86f2dc613a22ee06add9b878197922466df641bvboxsync#include <iprt/string.h>
6a008ce8150c1391d9e0dda0cdf9485b3c806034vboxsync
6a008ce8150c1391d9e0dda0cdf9485b3c806034vboxsync#ifdef VBOXANETADP_DO_NOT_USE_NETFLT
d61e6f5b11d9031623420bd7ed3013477d8f402dvboxsync#error "this code is broken"
6a008ce8150c1391d9e0dda0cdf9485b3c806034vboxsync
6a008ce8150c1391d9e0dda0cdf9485b3c806034vboxsync#include <VBox/sup.h>
6a008ce8150c1391d9e0dda0cdf9485b3c806034vboxsync#include <iprt/assert.h>
f86f2dc613a22ee06add9b878197922466df641bvboxsync#include <iprt/spinlock.h>
f86f2dc613a22ee06add9b878197922466df641bvboxsync#include <iprt/uuid.h>
ccc948c886b751603889a67909fbd4a5fcaeac85vboxsync#include <VBox/version.h>
f86f2dc613a22ee06add9b878197922466df641bvboxsync
ad27e1d5e48ca41245120c331cc88b50464813cevboxsync/** r=bird: why is this here in the agnostic code? */
ccc948c886b751603889a67909fbd4a5fcaeac85vboxsync#ifdef RT_OS_DARWIN
2a047f0d7ee5964456dbc4dec9925031482588abvboxsync# include <net/ethernet.h>
2a047f0d7ee5964456dbc4dec9925031482588abvboxsync# include <net/if_ether.h>
2a047f0d7ee5964456dbc4dec9925031482588abvboxsync# include <net/if_types.h>
2a047f0d7ee5964456dbc4dec9925031482588abvboxsync# include <sys/socket.h>
2a047f0d7ee5964456dbc4dec9925031482588abvboxsync# include <net/if.h>
2a047f0d7ee5964456dbc4dec9925031482588abvboxsync# include <net/if_dl.h>
2a047f0d7ee5964456dbc4dec9925031482588abvboxsync# include <sys/errno.h>
2a047f0d7ee5964456dbc4dec9925031482588abvboxsync# include <sys/param.h>
97dc19418e21b4b87280756668cf171a4332e498vboxsync#endif
f86f2dc613a22ee06add9b878197922466df641bvboxsync
40c9dcdf4b9d1c60dc67fa671b7a689b3c0f84d4vboxsync
f86f2dc613a22ee06add9b878197922466df641bvboxsync/*******************************************************************************
f86f2dc613a22ee06add9b878197922466df641bvboxsync* Defined Constants And Macros *
f86f2dc613a22ee06add9b878197922466df641bvboxsync*******************************************************************************/
f86f2dc613a22ee06add9b878197922466df641bvboxsync#define IFPORT_2_VBOXNETADP(pIfPort) \
f86f2dc613a22ee06add9b878197922466df641bvboxsync ( (PVBOXNETADP)((uint8_t *)pIfPort - RT_OFFSETOF(VBOXNETADP, MyPort)) )
f86f2dc613a22ee06add9b878197922466df641bvboxsync
f86f2dc613a22ee06add9b878197922466df641bvboxsync
2a047f0d7ee5964456dbc4dec9925031482588abvboxsyncAssertCompileMemberSize(VBOXNETADP, enmState, sizeof(uint32_t));
8300beb17e7c288655895d07bfdc58a01f618218vboxsync
8300beb17e7c288655895d07bfdc58a01f618218vboxsync/**
8300beb17e7c288655895d07bfdc58a01f618218vboxsync * Gets the enmState member atomically.
8300beb17e7c288655895d07bfdc58a01f618218vboxsync *
8300beb17e7c288655895d07bfdc58a01f618218vboxsync * Used for all reads.
8300beb17e7c288655895d07bfdc58a01f618218vboxsync *
8300beb17e7c288655895d07bfdc58a01f618218vboxsync * @returns The enmState value.
8300beb17e7c288655895d07bfdc58a01f618218vboxsync * @param pThis The instance.
8300beb17e7c288655895d07bfdc58a01f618218vboxsync */
8300beb17e7c288655895d07bfdc58a01f618218vboxsyncDECLINLINE(VBOXNETADPSTATE) vboxNetAdpGetState(PVBOXNETADP pThis)
8300beb17e7c288655895d07bfdc58a01f618218vboxsync{
8300beb17e7c288655895d07bfdc58a01f618218vboxsync return (VBOXNETADPSTATE)ASMAtomicUoReadU32((uint32_t volatile *)&pThis->enmState);
8300beb17e7c288655895d07bfdc58a01f618218vboxsync}
8300beb17e7c288655895d07bfdc58a01f618218vboxsync
8300beb17e7c288655895d07bfdc58a01f618218vboxsync
f86f2dc613a22ee06add9b878197922466df641bvboxsync/**
f86f2dc613a22ee06add9b878197922466df641bvboxsync * Sets the enmState member atomically.
f86f2dc613a22ee06add9b878197922466df641bvboxsync *
f86f2dc613a22ee06add9b878197922466df641bvboxsync * Used for all updates.
f86f2dc613a22ee06add9b878197922466df641bvboxsync *
f86f2dc613a22ee06add9b878197922466df641bvboxsync * @param pThis The instance.
f86f2dc613a22ee06add9b878197922466df641bvboxsync * @param enmNewState The new value.
f86f2dc613a22ee06add9b878197922466df641bvboxsync */
f86f2dc613a22ee06add9b878197922466df641bvboxsyncDECLINLINE(void) vboxNetAdpSetState(PVBOXNETADP pThis, VBOXNETADPSTATE enmNewState)
f86f2dc613a22ee06add9b878197922466df641bvboxsync{
8300beb17e7c288655895d07bfdc58a01f618218vboxsync Log(("vboxNetAdpSetState: pThis=%p, state change: %d -> %d.\n", pThis, vboxNetAdpGetState(pThis), enmNewState));
f86f2dc613a22ee06add9b878197922466df641bvboxsync ASMAtomicWriteU32((uint32_t volatile *)&pThis->enmState, enmNewState);
f86f2dc613a22ee06add9b878197922466df641bvboxsync}
f86f2dc613a22ee06add9b878197922466df641bvboxsync
2a047f0d7ee5964456dbc4dec9925031482588abvboxsync
f86f2dc613a22ee06add9b878197922466df641bvboxsync/**
ccc948c886b751603889a67909fbd4a5fcaeac85vboxsync * Sets the enmState member atomically after first acquiring the spinlock.
f86f2dc613a22ee06add9b878197922466df641bvboxsync *
8300beb17e7c288655895d07bfdc58a01f618218vboxsync * Used for all updates.
f86f2dc613a22ee06add9b878197922466df641bvboxsync *
f86f2dc613a22ee06add9b878197922466df641bvboxsync * @param pThis The instance.
8300beb17e7c288655895d07bfdc58a01f618218vboxsync * @param enmNewState The new value.
f86f2dc613a22ee06add9b878197922466df641bvboxsync */
8300beb17e7c288655895d07bfdc58a01f618218vboxsyncDECLINLINE(void) vboxNetAdpSetStateWithLock(PVBOXNETADP pThis, VBOXNETADPSTATE enmNewState)
f86f2dc613a22ee06add9b878197922466df641bvboxsync{
ccc948c886b751603889a67909fbd4a5fcaeac85vboxsync Log(("vboxNetAdpSetStateWithLock: pThis=%p, state=%d.\n", pThis, enmNewState));
f0ed7ab5e7f8d2f73b5aa08e46eb3a04cbb31cb2vboxsync RTSpinlockAcquire(pThis->hSpinlock);
8300beb17e7c288655895d07bfdc58a01f618218vboxsync vboxNetAdpSetState(pThis, enmNewState);
c0b6af690ad705bddfa87c643b89770a7a0aaf5avboxsync RTSpinlockRelease(pThis->hSpinlock);
f86f2dc613a22ee06add9b878197922466df641bvboxsync}
f86f2dc613a22ee06add9b878197922466df641bvboxsync
f86f2dc613a22ee06add9b878197922466df641bvboxsync
8300beb17e7c288655895d07bfdc58a01f618218vboxsync/**
8300beb17e7c288655895d07bfdc58a01f618218vboxsync * Gets the enmState member with locking.
8300beb17e7c288655895d07bfdc58a01f618218vboxsync *
8300beb17e7c288655895d07bfdc58a01f618218vboxsync * Used for all reads.
8300beb17e7c288655895d07bfdc58a01f618218vboxsync *
8300beb17e7c288655895d07bfdc58a01f618218vboxsync * @returns The enmState value.
8300beb17e7c288655895d07bfdc58a01f618218vboxsync * @param pThis The instance.
8300beb17e7c288655895d07bfdc58a01f618218vboxsync */
8300beb17e7c288655895d07bfdc58a01f618218vboxsyncDECLINLINE(VBOXNETADPSTATE) vboxNetAdpGetStateWithLock(PVBOXNETADP pThis)
f86f2dc613a22ee06add9b878197922466df641bvboxsync{
8300beb17e7c288655895d07bfdc58a01f618218vboxsync VBOXNETADPSTATE enmState;
f0ed7ab5e7f8d2f73b5aa08e46eb3a04cbb31cb2vboxsync RTSpinlockAcquire(pThis->hSpinlock);
8300beb17e7c288655895d07bfdc58a01f618218vboxsync enmState = vboxNetAdpGetState(pThis);
c0b6af690ad705bddfa87c643b89770a7a0aaf5avboxsync RTSpinlockRelease(pThis->hSpinlock);
8300beb17e7c288655895d07bfdc58a01f618218vboxsync Log(("vboxNetAdpGetStateWithLock: pThis=%p, state=%d.\n", pThis, enmState));
8300beb17e7c288655895d07bfdc58a01f618218vboxsync return enmState;
f86f2dc613a22ee06add9b878197922466df641bvboxsync}
f86f2dc613a22ee06add9b878197922466df641bvboxsync
2a047f0d7ee5964456dbc4dec9925031482588abvboxsync
8300beb17e7c288655895d07bfdc58a01f618218vboxsync/**
8300beb17e7c288655895d07bfdc58a01f618218vboxsync * Checks and sets the enmState member atomically.
8300beb17e7c288655895d07bfdc58a01f618218vboxsync *
8300beb17e7c288655895d07bfdc58a01f618218vboxsync * Used for all updates.
8300beb17e7c288655895d07bfdc58a01f618218vboxsync *
8300beb17e7c288655895d07bfdc58a01f618218vboxsync * @returns true if the state has been changed.
8300beb17e7c288655895d07bfdc58a01f618218vboxsync * @param pThis The instance.
8300beb17e7c288655895d07bfdc58a01f618218vboxsync * @param enmNewState The new value.
8300beb17e7c288655895d07bfdc58a01f618218vboxsync */
8300beb17e7c288655895d07bfdc58a01f618218vboxsyncDECLINLINE(bool) vboxNetAdpCheckAndSetState(PVBOXNETADP pThis, VBOXNETADPSTATE enmOldState, VBOXNETADPSTATE enmNewState)
f86f2dc613a22ee06add9b878197922466df641bvboxsync{
8300beb17e7c288655895d07bfdc58a01f618218vboxsync VBOXNETADPSTATE enmActualState;
8300beb17e7c288655895d07bfdc58a01f618218vboxsync bool fRc = true; /* be optimistic */
2a047f0d7ee5964456dbc4dec9925031482588abvboxsync
f0ed7ab5e7f8d2f73b5aa08e46eb3a04cbb31cb2vboxsync RTSpinlockAcquire(pThis->hSpinlock);
2a047f0d7ee5964456dbc4dec9925031482588abvboxsync enmActualState = vboxNetAdpGetState(pThis); /** @todo r=bird: ASMAtomicCmpXchgU32()*/
8300beb17e7c288655895d07bfdc58a01f618218vboxsync if (enmActualState == enmOldState)
8300beb17e7c288655895d07bfdc58a01f618218vboxsync vboxNetAdpSetState(pThis, enmNewState);
8300beb17e7c288655895d07bfdc58a01f618218vboxsync else
8300beb17e7c288655895d07bfdc58a01f618218vboxsync fRc = false;
c0b6af690ad705bddfa87c643b89770a7a0aaf5avboxsync RTSpinlockRelease(pThis->hSpinlock);
2a047f0d7ee5964456dbc4dec9925031482588abvboxsync
8300beb17e7c288655895d07bfdc58a01f618218vboxsync if (fRc)
8300beb17e7c288655895d07bfdc58a01f618218vboxsync Log(("vboxNetAdpCheckAndSetState: pThis=%p, state changed: %d -> %d.\n", pThis, enmOldState, enmNewState));
8300beb17e7c288655895d07bfdc58a01f618218vboxsync else
8300beb17e7c288655895d07bfdc58a01f618218vboxsync Log(("vboxNetAdpCheckAndSetState: pThis=%p, no state change: %d != %d (expected).\n", pThis, enmActualState, enmOldState));
8300beb17e7c288655895d07bfdc58a01f618218vboxsync return fRc;
f86f2dc613a22ee06add9b878197922466df641bvboxsync}
f86f2dc613a22ee06add9b878197922466df641bvboxsync
f86f2dc613a22ee06add9b878197922466df641bvboxsync
2a047f0d7ee5964456dbc4dec9925031482588abvboxsync/**
2a047f0d7ee5964456dbc4dec9925031482588abvboxsync * Finds a instance by its name, the caller does the locking.
2a047f0d7ee5964456dbc4dec9925031482588abvboxsync *
2a047f0d7ee5964456dbc4dec9925031482588abvboxsync * @returns Pointer to the instance by the given name. NULL if not found.
2a047f0d7ee5964456dbc4dec9925031482588abvboxsync * @param pGlobals The globals.
2a047f0d7ee5964456dbc4dec9925031482588abvboxsync * @param pszName The name of the instance.
2a047f0d7ee5964456dbc4dec9925031482588abvboxsync */
f86f2dc613a22ee06add9b878197922466df641bvboxsyncstatic PVBOXNETADP vboxNetAdpFind(PVBOXNETADPGLOBALS pGlobals, const char *pszName)
f86f2dc613a22ee06add9b878197922466df641bvboxsync{
f86f2dc613a22ee06add9b878197922466df641bvboxsync unsigned i;
f86f2dc613a22ee06add9b878197922466df641bvboxsync
f86f2dc613a22ee06add9b878197922466df641bvboxsync for (i = 0; i < RT_ELEMENTS(pGlobals->aAdapters); i++)
f86f2dc613a22ee06add9b878197922466df641bvboxsync {
f86f2dc613a22ee06add9b878197922466df641bvboxsync PVBOXNETADP pThis = &pGlobals->aAdapters[i];
f0ed7ab5e7f8d2f73b5aa08e46eb3a04cbb31cb2vboxsync RTSpinlockAcquire(pThis->hSpinlock);
2a047f0d7ee5964456dbc4dec9925031482588abvboxsync if ( vboxNetAdpGetState(pThis)
2a047f0d7ee5964456dbc4dec9925031482588abvboxsync && !strcmp(pThis->szName, pszName))
f86f2dc613a22ee06add9b878197922466df641bvboxsync {
c0b6af690ad705bddfa87c643b89770a7a0aaf5avboxsync RTSpinlockRelease(pThis->hSpinlock);
f86f2dc613a22ee06add9b878197922466df641bvboxsync return pThis;
f86f2dc613a22ee06add9b878197922466df641bvboxsync }
c0b6af690ad705bddfa87c643b89770a7a0aaf5avboxsync RTSpinlockRelease(pThis->hSpinlock);
f86f2dc613a22ee06add9b878197922466df641bvboxsync }
f86f2dc613a22ee06add9b878197922466df641bvboxsync return NULL;
f86f2dc613a22ee06add9b878197922466df641bvboxsync}
f86f2dc613a22ee06add9b878197922466df641bvboxsync
2a047f0d7ee5964456dbc4dec9925031482588abvboxsync
f86f2dc613a22ee06add9b878197922466df641bvboxsync/**
f86f2dc613a22ee06add9b878197922466df641bvboxsync * Releases a reference to the specified instance.
f86f2dc613a22ee06add9b878197922466df641bvboxsync *
f86f2dc613a22ee06add9b878197922466df641bvboxsync * @param pThis The instance.
f86f2dc613a22ee06add9b878197922466df641bvboxsync * @param fBusy Whether the busy counter should be decremented too.
f86f2dc613a22ee06add9b878197922466df641bvboxsync */
f86f2dc613a22ee06add9b878197922466df641bvboxsyncDECLHIDDEN(void) vboxNetAdpRelease(PVBOXNETADP pThis)
f86f2dc613a22ee06add9b878197922466df641bvboxsync{
f86f2dc613a22ee06add9b878197922466df641bvboxsync uint32_t cRefs;
f86f2dc613a22ee06add9b878197922466df641bvboxsync
f86f2dc613a22ee06add9b878197922466df641bvboxsync /*
f86f2dc613a22ee06add9b878197922466df641bvboxsync * Paranoid Android.
f86f2dc613a22ee06add9b878197922466df641bvboxsync */
f86f2dc613a22ee06add9b878197922466df641bvboxsync AssertPtr(pThis);
f86f2dc613a22ee06add9b878197922466df641bvboxsync Assert(pThis->MyPort.u32Version == INTNETTRUNKIFPORT_VERSION);
f86f2dc613a22ee06add9b878197922466df641bvboxsync Assert(pThis->MyPort.u32VersionEnd == INTNETTRUNKIFPORT_VERSION);
f86f2dc613a22ee06add9b878197922466df641bvboxsync Assert(vboxNetAdpGetState(pThis) > kVBoxNetAdpState_Invalid);
f86f2dc613a22ee06add9b878197922466df641bvboxsync AssertPtr(pThis->pGlobals);
f86f2dc613a22ee06add9b878197922466df641bvboxsync Assert(pThis->hEventIdle != NIL_RTSEMEVENT);
f86f2dc613a22ee06add9b878197922466df641bvboxsync Assert(pThis->hSpinlock != NIL_RTSPINLOCK);
f86f2dc613a22ee06add9b878197922466df641bvboxsync Assert(pThis->szName[0]);
f86f2dc613a22ee06add9b878197922466df641bvboxsync
f86f2dc613a22ee06add9b878197922466df641bvboxsync /*
f86f2dc613a22ee06add9b878197922466df641bvboxsync * The object reference counting.
f86f2dc613a22ee06add9b878197922466df641bvboxsync */
f86f2dc613a22ee06add9b878197922466df641bvboxsync cRefs = ASMAtomicDecU32(&pThis->cRefs);
8300beb17e7c288655895d07bfdc58a01f618218vboxsync Assert(cRefs < UINT32_MAX / 2);
f86f2dc613a22ee06add9b878197922466df641bvboxsync}
f86f2dc613a22ee06add9b878197922466df641bvboxsync
2a047f0d7ee5964456dbc4dec9925031482588abvboxsync
f86f2dc613a22ee06add9b878197922466df641bvboxsync/**
f86f2dc613a22ee06add9b878197922466df641bvboxsync * Decrements the busy counter and does idle wakeup.
f86f2dc613a22ee06add9b878197922466df641bvboxsync *
f86f2dc613a22ee06add9b878197922466df641bvboxsync * @param pThis The instance.
f86f2dc613a22ee06add9b878197922466df641bvboxsync */
f86f2dc613a22ee06add9b878197922466df641bvboxsyncDECLHIDDEN(void) vboxNetAdpIdle(PVBOXNETADP pThis)
f86f2dc613a22ee06add9b878197922466df641bvboxsync{
f86f2dc613a22ee06add9b878197922466df641bvboxsync uint32_t cBusy;
f86f2dc613a22ee06add9b878197922466df641bvboxsync
f86f2dc613a22ee06add9b878197922466df641bvboxsync /*
f86f2dc613a22ee06add9b878197922466df641bvboxsync * Paranoid Android.
f86f2dc613a22ee06add9b878197922466df641bvboxsync */
f86f2dc613a22ee06add9b878197922466df641bvboxsync AssertPtr(pThis);
f86f2dc613a22ee06add9b878197922466df641bvboxsync Assert(pThis->MyPort.u32Version == INTNETTRUNKIFPORT_VERSION);
f86f2dc613a22ee06add9b878197922466df641bvboxsync Assert(pThis->MyPort.u32VersionEnd == INTNETTRUNKIFPORT_VERSION);
8300beb17e7c288655895d07bfdc58a01f618218vboxsync Assert(vboxNetAdpGetState(pThis) >= kVBoxNetAdpState_Connected);
f86f2dc613a22ee06add9b878197922466df641bvboxsync AssertPtr(pThis->pGlobals);
f86f2dc613a22ee06add9b878197922466df641bvboxsync Assert(pThis->hEventIdle != NIL_RTSEMEVENT);
f86f2dc613a22ee06add9b878197922466df641bvboxsync
f86f2dc613a22ee06add9b878197922466df641bvboxsync cBusy = ASMAtomicDecU32(&pThis->cBusy);
f86f2dc613a22ee06add9b878197922466df641bvboxsync if (!cBusy)
f86f2dc613a22ee06add9b878197922466df641bvboxsync {
f86f2dc613a22ee06add9b878197922466df641bvboxsync int rc = RTSemEventSignal(pThis->hEventIdle);
f86f2dc613a22ee06add9b878197922466df641bvboxsync AssertRC(rc);
f86f2dc613a22ee06add9b878197922466df641bvboxsync }
f86f2dc613a22ee06add9b878197922466df641bvboxsync else
f86f2dc613a22ee06add9b878197922466df641bvboxsync Assert(cBusy < UINT32_MAX / 2);
f86f2dc613a22ee06add9b878197922466df641bvboxsync}
f86f2dc613a22ee06add9b878197922466df641bvboxsync
2a047f0d7ee5964456dbc4dec9925031482588abvboxsync
f86f2dc613a22ee06add9b878197922466df641bvboxsync/**
f86f2dc613a22ee06add9b878197922466df641bvboxsync * Retains a reference to the specified instance.
f86f2dc613a22ee06add9b878197922466df641bvboxsync *
f86f2dc613a22ee06add9b878197922466df641bvboxsync * @param pThis The instance.
f86f2dc613a22ee06add9b878197922466df641bvboxsync */
f86f2dc613a22ee06add9b878197922466df641bvboxsyncDECLHIDDEN(void) vboxNetAdpRetain(PVBOXNETADP pThis)
f86f2dc613a22ee06add9b878197922466df641bvboxsync{
f86f2dc613a22ee06add9b878197922466df641bvboxsync uint32_t cRefs;
f86f2dc613a22ee06add9b878197922466df641bvboxsync
f86f2dc613a22ee06add9b878197922466df641bvboxsync /*
f86f2dc613a22ee06add9b878197922466df641bvboxsync * Paranoid Android.
f86f2dc613a22ee06add9b878197922466df641bvboxsync */
f86f2dc613a22ee06add9b878197922466df641bvboxsync AssertPtr(pThis);
f86f2dc613a22ee06add9b878197922466df641bvboxsync Assert(pThis->MyPort.u32Version == INTNETTRUNKIFPORT_VERSION);
f86f2dc613a22ee06add9b878197922466df641bvboxsync Assert(pThis->MyPort.u32VersionEnd == INTNETTRUNKIFPORT_VERSION);
f86f2dc613a22ee06add9b878197922466df641bvboxsync Assert(vboxNetAdpGetState(pThis) > kVBoxNetAdpState_Invalid);
f86f2dc613a22ee06add9b878197922466df641bvboxsync AssertPtr(pThis->pGlobals);
f86f2dc613a22ee06add9b878197922466df641bvboxsync Assert(pThis->hEventIdle != NIL_RTSEMEVENT);
f86f2dc613a22ee06add9b878197922466df641bvboxsync Assert(pThis->hSpinlock != NIL_RTSPINLOCK);
f86f2dc613a22ee06add9b878197922466df641bvboxsync Assert(pThis->szName[0]);
f86f2dc613a22ee06add9b878197922466df641bvboxsync
f86f2dc613a22ee06add9b878197922466df641bvboxsync /*
f86f2dc613a22ee06add9b878197922466df641bvboxsync * Retain the object.
f86f2dc613a22ee06add9b878197922466df641bvboxsync */
f86f2dc613a22ee06add9b878197922466df641bvboxsync cRefs = ASMAtomicIncU32(&pThis->cRefs);
f86f2dc613a22ee06add9b878197922466df641bvboxsync Assert(cRefs > 1 && cRefs < UINT32_MAX / 2);
f86f2dc613a22ee06add9b878197922466df641bvboxsync
f86f2dc613a22ee06add9b878197922466df641bvboxsync NOREF(cRefs);
f86f2dc613a22ee06add9b878197922466df641bvboxsync}
f86f2dc613a22ee06add9b878197922466df641bvboxsync
2a047f0d7ee5964456dbc4dec9925031482588abvboxsync
f86f2dc613a22ee06add9b878197922466df641bvboxsync/**
f86f2dc613a22ee06add9b878197922466df641bvboxsync * Increments busy counter.
f86f2dc613a22ee06add9b878197922466df641bvboxsync *
f86f2dc613a22ee06add9b878197922466df641bvboxsync * @param pThis The instance.
f86f2dc613a22ee06add9b878197922466df641bvboxsync */
f86f2dc613a22ee06add9b878197922466df641bvboxsyncDECLHIDDEN(void) vboxNetAdpBusy(PVBOXNETADP pThis)
f86f2dc613a22ee06add9b878197922466df641bvboxsync{
f86f2dc613a22ee06add9b878197922466df641bvboxsync uint32_t cBusy;
f86f2dc613a22ee06add9b878197922466df641bvboxsync
f86f2dc613a22ee06add9b878197922466df641bvboxsync /*
f86f2dc613a22ee06add9b878197922466df641bvboxsync * Are we vigilant enough?
f86f2dc613a22ee06add9b878197922466df641bvboxsync */
f86f2dc613a22ee06add9b878197922466df641bvboxsync AssertPtr(pThis);
f86f2dc613a22ee06add9b878197922466df641bvboxsync Assert(pThis->MyPort.u32Version == INTNETTRUNKIFPORT_VERSION);
f86f2dc613a22ee06add9b878197922466df641bvboxsync Assert(pThis->MyPort.u32VersionEnd == INTNETTRUNKIFPORT_VERSION);
8300beb17e7c288655895d07bfdc58a01f618218vboxsync Assert(vboxNetAdpGetState(pThis) >= kVBoxNetAdpState_Connected);
f86f2dc613a22ee06add9b878197922466df641bvboxsync AssertPtr(pThis->pGlobals);
f86f2dc613a22ee06add9b878197922466df641bvboxsync Assert(pThis->hEventIdle != NIL_RTSEMEVENT);
f86f2dc613a22ee06add9b878197922466df641bvboxsync cBusy = ASMAtomicIncU32(&pThis->cBusy);
f86f2dc613a22ee06add9b878197922466df641bvboxsync Assert(cBusy > 0 && cBusy < UINT32_MAX / 2);
f86f2dc613a22ee06add9b878197922466df641bvboxsync
f86f2dc613a22ee06add9b878197922466df641bvboxsync NOREF(cBusy);
f86f2dc613a22ee06add9b878197922466df641bvboxsync}
f86f2dc613a22ee06add9b878197922466df641bvboxsync
2a047f0d7ee5964456dbc4dec9925031482588abvboxsync
ccc948c886b751603889a67909fbd4a5fcaeac85vboxsync/**
ccc948c886b751603889a67909fbd4a5fcaeac85vboxsync * Generate a suitable MAC address.
ccc948c886b751603889a67909fbd4a5fcaeac85vboxsync *
ccc948c886b751603889a67909fbd4a5fcaeac85vboxsync * @param pThis The instance.
ccc948c886b751603889a67909fbd4a5fcaeac85vboxsync * @param pMac Where to return the MAC address.
ccc948c886b751603889a67909fbd4a5fcaeac85vboxsync */
ccc948c886b751603889a67909fbd4a5fcaeac85vboxsyncDECLHIDDEN(void) vboxNetAdpComposeMACAddress(PVBOXNETADP pThis, PRTMAC pMac)
ccc948c886b751603889a67909fbd4a5fcaeac85vboxsync{
ccc948c886b751603889a67909fbd4a5fcaeac85vboxsync#if 0 /* Use a locally administered version of the OUI we use for the guest NICs. */
ccc948c886b751603889a67909fbd4a5fcaeac85vboxsync pMac->au8[0] = 0x08 | 2;
ccc948c886b751603889a67909fbd4a5fcaeac85vboxsync pMac->au8[1] = 0x00;
ccc948c886b751603889a67909fbd4a5fcaeac85vboxsync pMac->au8[2] = 0x27;
ccc948c886b751603889a67909fbd4a5fcaeac85vboxsync#else /* this is what \0vb comes down to. It seems to be unassigned atm. */
ccc948c886b751603889a67909fbd4a5fcaeac85vboxsync pMac->au8[0] = 0;
ccc948c886b751603889a67909fbd4a5fcaeac85vboxsync pMac->au8[1] = 0x76;
ccc948c886b751603889a67909fbd4a5fcaeac85vboxsync pMac->au8[2] = 0x62;
ccc948c886b751603889a67909fbd4a5fcaeac85vboxsync#endif
ccc948c886b751603889a67909fbd4a5fcaeac85vboxsync
ccc948c886b751603889a67909fbd4a5fcaeac85vboxsync pMac->au8[3] = 0; /* pThis->uUnit >> 16; */
ccc948c886b751603889a67909fbd4a5fcaeac85vboxsync pMac->au8[4] = 0; /* pThis->uUnit >> 8; */
ccc948c886b751603889a67909fbd4a5fcaeac85vboxsync pMac->au8[5] = pThis->uUnit;
ccc948c886b751603889a67909fbd4a5fcaeac85vboxsync}
ccc948c886b751603889a67909fbd4a5fcaeac85vboxsync
ccc948c886b751603889a67909fbd4a5fcaeac85vboxsync
f86f2dc613a22ee06add9b878197922466df641bvboxsync/**
f86f2dc613a22ee06add9b878197922466df641bvboxsync * Checks if receive is possible and increases busy and ref counters if so.
f86f2dc613a22ee06add9b878197922466df641bvboxsync *
f86f2dc613a22ee06add9b878197922466df641bvboxsync * @param pThis The instance.
f86f2dc613a22ee06add9b878197922466df641bvboxsync */
f86f2dc613a22ee06add9b878197922466df641bvboxsyncDECLHIDDEN(bool) vboxNetAdpPrepareToReceive(PVBOXNETADP pThis)
f86f2dc613a22ee06add9b878197922466df641bvboxsync{
f86f2dc613a22ee06add9b878197922466df641bvboxsync bool fCanReceive = false;
f86f2dc613a22ee06add9b878197922466df641bvboxsync /*
f86f2dc613a22ee06add9b878197922466df641bvboxsync * Input validation.
f86f2dc613a22ee06add9b878197922466df641bvboxsync */
f86f2dc613a22ee06add9b878197922466df641bvboxsync AssertPtr(pThis);
f86f2dc613a22ee06add9b878197922466df641bvboxsync Assert(pThis->MyPort.u32Version == INTNETTRUNKIFPORT_VERSION);
f0ed7ab5e7f8d2f73b5aa08e46eb3a04cbb31cb2vboxsync RTSpinlockAcquire(pThis->hSpinlock);
8300beb17e7c288655895d07bfdc58a01f618218vboxsync if (vboxNetAdpGetState(pThis) == kVBoxNetAdpState_Active)
f86f2dc613a22ee06add9b878197922466df641bvboxsync {
f86f2dc613a22ee06add9b878197922466df641bvboxsync fCanReceive = true;
f86f2dc613a22ee06add9b878197922466df641bvboxsync vboxNetAdpRetain(pThis);
f86f2dc613a22ee06add9b878197922466df641bvboxsync vboxNetAdpBusy(pThis);
f86f2dc613a22ee06add9b878197922466df641bvboxsync }
c0b6af690ad705bddfa87c643b89770a7a0aaf5avboxsync RTSpinlockRelease(pThis->hSpinlock);
6af5a377dcdc4437fa51e183a5a8dad78abf2ec0vboxsync Log(("vboxNetAdpPrepareToReceive: fCanReceive=%d.\n", fCanReceive));
f86f2dc613a22ee06add9b878197922466df641bvboxsync
f86f2dc613a22ee06add9b878197922466df641bvboxsync return fCanReceive;
f86f2dc613a22ee06add9b878197922466df641bvboxsync}
f86f2dc613a22ee06add9b878197922466df641bvboxsync
2a047f0d7ee5964456dbc4dec9925031482588abvboxsync
f86f2dc613a22ee06add9b878197922466df641bvboxsync/**
f86f2dc613a22ee06add9b878197922466df641bvboxsync * Forwards scatter/gather list to internal network and decreases busy and ref counters.
f86f2dc613a22ee06add9b878197922466df641bvboxsync *
f86f2dc613a22ee06add9b878197922466df641bvboxsync * @param pThis The instance.
f86f2dc613a22ee06add9b878197922466df641bvboxsync */
f86f2dc613a22ee06add9b878197922466df641bvboxsyncDECLHIDDEN(void) vboxNetAdpReceive(PVBOXNETADP pThis, PINTNETSG pSG)
f86f2dc613a22ee06add9b878197922466df641bvboxsync{
f86f2dc613a22ee06add9b878197922466df641bvboxsync /*
f86f2dc613a22ee06add9b878197922466df641bvboxsync * Input validation.
f86f2dc613a22ee06add9b878197922466df641bvboxsync */
f86f2dc613a22ee06add9b878197922466df641bvboxsync AssertPtr(pThis);
f86f2dc613a22ee06add9b878197922466df641bvboxsync AssertPtr(pSG);
8300beb17e7c288655895d07bfdc58a01f618218vboxsync AssertPtr(pThis->pSwitchPort);
f86f2dc613a22ee06add9b878197922466df641bvboxsync Assert(pThis->MyPort.u32Version == INTNETTRUNKIFPORT_VERSION);
6af5a377dcdc4437fa51e183a5a8dad78abf2ec0vboxsync Log(("vboxNetAdpReceive: forwarding packet to internal net...\n"));
f86f2dc613a22ee06add9b878197922466df641bvboxsync pThis->pSwitchPort->pfnRecv(pThis->pSwitchPort, pSG, INTNETTRUNKDIR_HOST);
f86f2dc613a22ee06add9b878197922466df641bvboxsync vboxNetAdpIdle(pThis);
f86f2dc613a22ee06add9b878197922466df641bvboxsync vboxNetAdpRelease(pThis);
f86f2dc613a22ee06add9b878197922466df641bvboxsync}
f86f2dc613a22ee06add9b878197922466df641bvboxsync
2a047f0d7ee5964456dbc4dec9925031482588abvboxsync
f86f2dc613a22ee06add9b878197922466df641bvboxsync/**
f86f2dc613a22ee06add9b878197922466df641bvboxsync * Decreases busy and ref counters.
f86f2dc613a22ee06add9b878197922466df641bvboxsync *
f86f2dc613a22ee06add9b878197922466df641bvboxsync * @param pThis The instance.
f86f2dc613a22ee06add9b878197922466df641bvboxsync */
f86f2dc613a22ee06add9b878197922466df641bvboxsyncDECLHIDDEN(void) vboxNetAdpCancelReceive(PVBOXNETADP pThis)
f86f2dc613a22ee06add9b878197922466df641bvboxsync{
6af5a377dcdc4437fa51e183a5a8dad78abf2ec0vboxsync Log(("vboxNetAdpCancelReceive: cancelled.\n"));
f86f2dc613a22ee06add9b878197922466df641bvboxsync vboxNetAdpIdle(pThis);
f86f2dc613a22ee06add9b878197922466df641bvboxsync vboxNetAdpRelease(pThis);
f86f2dc613a22ee06add9b878197922466df641bvboxsync}
f86f2dc613a22ee06add9b878197922466df641bvboxsync
f86f2dc613a22ee06add9b878197922466df641bvboxsync
f86f2dc613a22ee06add9b878197922466df641bvboxsync/**
f86f2dc613a22ee06add9b878197922466df641bvboxsync * @copydoc INTNETTRUNKIFPORT::pfnXmit
f86f2dc613a22ee06add9b878197922466df641bvboxsync */
5a9f1d57ea268b1d88ff2492d9d59a696b1c693evboxsyncstatic DECLCALLBACK(int) vboxNetAdpPortXmit(PINTNETTRUNKIFPORT pIfPort, PINTNETSG pSG, uint32_t fDst)
f86f2dc613a22ee06add9b878197922466df641bvboxsync{
f86f2dc613a22ee06add9b878197922466df641bvboxsync PVBOXNETADP pThis = IFPORT_2_VBOXNETADP(pIfPort);
f86f2dc613a22ee06add9b878197922466df641bvboxsync int rc = VINF_SUCCESS;
f86f2dc613a22ee06add9b878197922466df641bvboxsync
f86f2dc613a22ee06add9b878197922466df641bvboxsync /*
f86f2dc613a22ee06add9b878197922466df641bvboxsync * Input validation.
f86f2dc613a22ee06add9b878197922466df641bvboxsync */
f86f2dc613a22ee06add9b878197922466df641bvboxsync AssertPtr(pThis);
f86f2dc613a22ee06add9b878197922466df641bvboxsync AssertPtr(pSG);
f86f2dc613a22ee06add9b878197922466df641bvboxsync Assert(pThis->MyPort.u32Version == INTNETTRUNKIFPORT_VERSION);
f86f2dc613a22ee06add9b878197922466df641bvboxsync
6af5a377dcdc4437fa51e183a5a8dad78abf2ec0vboxsync Log(("vboxNetAdpPortXmit: outgoing packet (len=%d)\n", pSG->cbTotal));
6af5a377dcdc4437fa51e183a5a8dad78abf2ec0vboxsync
f86f2dc613a22ee06add9b878197922466df641bvboxsync /*
f86f2dc613a22ee06add9b878197922466df641bvboxsync * Do a retain/busy, invoke the OS specific code.
f86f2dc613a22ee06add9b878197922466df641bvboxsync */
f0ed7ab5e7f8d2f73b5aa08e46eb3a04cbb31cb2vboxsync RTSpinlockAcquire(pThis->hSpinlock);
8300beb17e7c288655895d07bfdc58a01f618218vboxsync if (vboxNetAdpGetState(pThis) != kVBoxNetAdpState_Active)
f86f2dc613a22ee06add9b878197922466df641bvboxsync {
c0b6af690ad705bddfa87c643b89770a7a0aaf5avboxsync RTSpinlockRelease(pThis->hSpinlock);
f86f2dc613a22ee06add9b878197922466df641bvboxsync Log(("vboxNetAdpReceive: Dropping incoming packet for inactive interface %s.\n",
f86f2dc613a22ee06add9b878197922466df641bvboxsync pThis->szName));
f86f2dc613a22ee06add9b878197922466df641bvboxsync return VERR_INVALID_STATE;
f86f2dc613a22ee06add9b878197922466df641bvboxsync }
f86f2dc613a22ee06add9b878197922466df641bvboxsync vboxNetAdpRetain(pThis);
f86f2dc613a22ee06add9b878197922466df641bvboxsync vboxNetAdpBusy(pThis);
c0b6af690ad705bddfa87c643b89770a7a0aaf5avboxsync RTSpinlockRelease(pThis->hSpinlock);
2a047f0d7ee5964456dbc4dec9925031482588abvboxsync
f86f2dc613a22ee06add9b878197922466df641bvboxsync rc = vboxNetAdpPortOsXmit(pThis, pSG, fDst);
f86f2dc613a22ee06add9b878197922466df641bvboxsync vboxNetAdpIdle(pThis);
f86f2dc613a22ee06add9b878197922466df641bvboxsync vboxNetAdpRelease(pThis);
f86f2dc613a22ee06add9b878197922466df641bvboxsync
f86f2dc613a22ee06add9b878197922466df641bvboxsync return rc;
f86f2dc613a22ee06add9b878197922466df641bvboxsync}
f86f2dc613a22ee06add9b878197922466df641bvboxsync
f86f2dc613a22ee06add9b878197922466df641bvboxsync
f86f2dc613a22ee06add9b878197922466df641bvboxsync/**
f86f2dc613a22ee06add9b878197922466df641bvboxsync * @copydoc INTNETTRUNKIFPORT::pfnGetMacAddress
f86f2dc613a22ee06add9b878197922466df641bvboxsync */
5a9f1d57ea268b1d88ff2492d9d59a696b1c693evboxsyncstatic DECLCALLBACK(void) vboxNetAdpPortGetMacAddress(PINTNETTRUNKIFPORT pIfPort, PRTMAC pMac)
f86f2dc613a22ee06add9b878197922466df641bvboxsync{
f86f2dc613a22ee06add9b878197922466df641bvboxsync PVBOXNETADP pThis = IFPORT_2_VBOXNETADP(pIfPort);
f86f2dc613a22ee06add9b878197922466df641bvboxsync
f86f2dc613a22ee06add9b878197922466df641bvboxsync /*
f86f2dc613a22ee06add9b878197922466df641bvboxsync * Input validation.
f86f2dc613a22ee06add9b878197922466df641bvboxsync */
f86f2dc613a22ee06add9b878197922466df641bvboxsync AssertPtr(pThis);
f86f2dc613a22ee06add9b878197922466df641bvboxsync Assert(pThis->MyPort.u32Version == INTNETTRUNKIFPORT_VERSION);
6af5a377dcdc4437fa51e183a5a8dad78abf2ec0vboxsync Assert(vboxNetAdpGetStateWithLock(pThis) == kVBoxNetAdpState_Active);
f86f2dc613a22ee06add9b878197922466df641bvboxsync
f86f2dc613a22ee06add9b878197922466df641bvboxsync /*
f86f2dc613a22ee06add9b878197922466df641bvboxsync * Forward the question to the OS specific code.
f86f2dc613a22ee06add9b878197922466df641bvboxsync */
f86f2dc613a22ee06add9b878197922466df641bvboxsync vboxNetAdpPortOsGetMacAddress(pThis, pMac);
f86f2dc613a22ee06add9b878197922466df641bvboxsync}
f86f2dc613a22ee06add9b878197922466df641bvboxsync
f86f2dc613a22ee06add9b878197922466df641bvboxsync
f86f2dc613a22ee06add9b878197922466df641bvboxsync/**
f86f2dc613a22ee06add9b878197922466df641bvboxsync * @copydoc INTNETTRUNKIFPORT::pfnWaitForIdle
f86f2dc613a22ee06add9b878197922466df641bvboxsync */
5a9f1d57ea268b1d88ff2492d9d59a696b1c693evboxsyncstatic DECLCALLBACK(int) vboxNetAdpPortWaitForIdle(PINTNETTRUNKIFPORT pIfPort, uint32_t cMillies)
f86f2dc613a22ee06add9b878197922466df641bvboxsync{
f86f2dc613a22ee06add9b878197922466df641bvboxsync int rc;
8300beb17e7c288655895d07bfdc58a01f618218vboxsync PVBOXNETADP pThis = IFPORT_2_VBOXNETADP(pIfPort);
f86f2dc613a22ee06add9b878197922466df641bvboxsync
f86f2dc613a22ee06add9b878197922466df641bvboxsync /*
f86f2dc613a22ee06add9b878197922466df641bvboxsync * Input validation.
f86f2dc613a22ee06add9b878197922466df641bvboxsync */
f86f2dc613a22ee06add9b878197922466df641bvboxsync AssertPtr(pThis);
f86f2dc613a22ee06add9b878197922466df641bvboxsync Assert(pThis->MyPort.u32Version == INTNETTRUNKIFPORT_VERSION);
8300beb17e7c288655895d07bfdc58a01f618218vboxsync AssertReturn(vboxNetAdpGetStateWithLock(pThis) >= kVBoxNetAdpState_Connected, VERR_INVALID_STATE);
f86f2dc613a22ee06add9b878197922466df641bvboxsync
f86f2dc613a22ee06add9b878197922466df641bvboxsync /*
f86f2dc613a22ee06add9b878197922466df641bvboxsync * Go to sleep on the semaphore after checking the busy count.
f86f2dc613a22ee06add9b878197922466df641bvboxsync */
f86f2dc613a22ee06add9b878197922466df641bvboxsync vboxNetAdpRetain(pThis);
f86f2dc613a22ee06add9b878197922466df641bvboxsync
f86f2dc613a22ee06add9b878197922466df641bvboxsync rc = VINF_SUCCESS;
f86f2dc613a22ee06add9b878197922466df641bvboxsync while (pThis->cBusy && RT_SUCCESS(rc))
f86f2dc613a22ee06add9b878197922466df641bvboxsync rc = RTSemEventWait(pThis->hEventIdle, cMillies); /** @todo make interruptible? */
f86f2dc613a22ee06add9b878197922466df641bvboxsync
f86f2dc613a22ee06add9b878197922466df641bvboxsync vboxNetAdpRelease(pThis);
f86f2dc613a22ee06add9b878197922466df641bvboxsync
f86f2dc613a22ee06add9b878197922466df641bvboxsync return rc;
f86f2dc613a22ee06add9b878197922466df641bvboxsync}
f86f2dc613a22ee06add9b878197922466df641bvboxsync
f86f2dc613a22ee06add9b878197922466df641bvboxsync
f86f2dc613a22ee06add9b878197922466df641bvboxsync/**
f86f2dc613a22ee06add9b878197922466df641bvboxsync * @copydoc INTNETTRUNKIFPORT::pfnSetActive
f86f2dc613a22ee06add9b878197922466df641bvboxsync */
5a9f1d57ea268b1d88ff2492d9d59a696b1c693evboxsyncstatic DECLCALLBACK(bool) vboxNetAdpPortSetActive(PINTNETTRUNKIFPORT pIfPort, bool fActive)
f86f2dc613a22ee06add9b878197922466df641bvboxsync{
f86f2dc613a22ee06add9b878197922466df641bvboxsync bool fPreviouslyActive;
f86f2dc613a22ee06add9b878197922466df641bvboxsync PVBOXNETADP pThis = IFPORT_2_VBOXNETADP(pIfPort);
f86f2dc613a22ee06add9b878197922466df641bvboxsync
f86f2dc613a22ee06add9b878197922466df641bvboxsync /*
f86f2dc613a22ee06add9b878197922466df641bvboxsync * Input validation.
f86f2dc613a22ee06add9b878197922466df641bvboxsync */
f86f2dc613a22ee06add9b878197922466df641bvboxsync AssertPtr(pThis);
f86f2dc613a22ee06add9b878197922466df641bvboxsync AssertPtr(pThis->pGlobals);
f86f2dc613a22ee06add9b878197922466df641bvboxsync Assert(pThis->MyPort.u32Version == INTNETTRUNKIFPORT_VERSION);
f86f2dc613a22ee06add9b878197922466df641bvboxsync
8300beb17e7c288655895d07bfdc58a01f618218vboxsync Log(("vboxNetAdpPortSetActive: pThis=%p, fActive=%d, state before: %d.\n", pThis, fActive, vboxNetAdpGetState(pThis)));
f0ed7ab5e7f8d2f73b5aa08e46eb3a04cbb31cb2vboxsync RTSpinlockAcquire(pThis->hSpinlock);
2a047f0d7ee5964456dbc4dec9925031482588abvboxsync
8300beb17e7c288655895d07bfdc58a01f618218vboxsync fPreviouslyActive = vboxNetAdpGetState(pThis) == kVBoxNetAdpState_Active;
8300beb17e7c288655895d07bfdc58a01f618218vboxsync if (fPreviouslyActive != fActive)
f86f2dc613a22ee06add9b878197922466df641bvboxsync {
8300beb17e7c288655895d07bfdc58a01f618218vboxsync switch (vboxNetAdpGetState(pThis))
8300beb17e7c288655895d07bfdc58a01f618218vboxsync {
8300beb17e7c288655895d07bfdc58a01f618218vboxsync case kVBoxNetAdpState_Connected:
8300beb17e7c288655895d07bfdc58a01f618218vboxsync vboxNetAdpSetState(pThis, kVBoxNetAdpState_Active);
8300beb17e7c288655895d07bfdc58a01f618218vboxsync break;
8300beb17e7c288655895d07bfdc58a01f618218vboxsync case kVBoxNetAdpState_Active:
8300beb17e7c288655895d07bfdc58a01f618218vboxsync vboxNetAdpSetState(pThis, kVBoxNetAdpState_Connected);
8300beb17e7c288655895d07bfdc58a01f618218vboxsync break;
6af5a377dcdc4437fa51e183a5a8dad78abf2ec0vboxsync default:
6af5a377dcdc4437fa51e183a5a8dad78abf2ec0vboxsync break;
8300beb17e7c288655895d07bfdc58a01f618218vboxsync }
f86f2dc613a22ee06add9b878197922466df641bvboxsync }
2a047f0d7ee5964456dbc4dec9925031482588abvboxsync
c0b6af690ad705bddfa87c643b89770a7a0aaf5avboxsync RTSpinlockRelease(pThis->hSpinlock);
2a047f0d7ee5964456dbc4dec9925031482588abvboxsync Log(("vboxNetAdpPortSetActive: state after: %RTbool.\n", vboxNetAdpGetState(pThis)));
f86f2dc613a22ee06add9b878197922466df641bvboxsync return fPreviouslyActive;
f86f2dc613a22ee06add9b878197922466df641bvboxsync}
f86f2dc613a22ee06add9b878197922466df641bvboxsync
f86f2dc613a22ee06add9b878197922466df641bvboxsync
f86f2dc613a22ee06add9b878197922466df641bvboxsync/**
f86f2dc613a22ee06add9b878197922466df641bvboxsync * @copydoc INTNETTRUNKIFPORT::pfnDisconnectAndRelease
f86f2dc613a22ee06add9b878197922466df641bvboxsync */
5a9f1d57ea268b1d88ff2492d9d59a696b1c693evboxsyncstatic DECLCALLBACK(void) vboxNetAdpPortDisconnectAndRelease(PINTNETTRUNKIFPORT pIfPort)
f86f2dc613a22ee06add9b878197922466df641bvboxsync{
f86f2dc613a22ee06add9b878197922466df641bvboxsync PVBOXNETADP pThis = IFPORT_2_VBOXNETADP(pIfPort);
f86f2dc613a22ee06add9b878197922466df641bvboxsync
f86f2dc613a22ee06add9b878197922466df641bvboxsync /*
f86f2dc613a22ee06add9b878197922466df641bvboxsync * Serious paranoia.
f86f2dc613a22ee06add9b878197922466df641bvboxsync */
f86f2dc613a22ee06add9b878197922466df641bvboxsync AssertPtr(pThis);
f86f2dc613a22ee06add9b878197922466df641bvboxsync Assert(pThis->MyPort.u32Version == INTNETTRUNKIFPORT_VERSION);
f86f2dc613a22ee06add9b878197922466df641bvboxsync Assert(pThis->MyPort.u32VersionEnd == INTNETTRUNKIFPORT_VERSION);
f86f2dc613a22ee06add9b878197922466df641bvboxsync AssertPtr(pThis->pGlobals);
f86f2dc613a22ee06add9b878197922466df641bvboxsync Assert(pThis->hEventIdle != NIL_RTSEMEVENT);
f86f2dc613a22ee06add9b878197922466df641bvboxsync Assert(pThis->hSpinlock != NIL_RTSPINLOCK);
f86f2dc613a22ee06add9b878197922466df641bvboxsync
f86f2dc613a22ee06add9b878197922466df641bvboxsync
f86f2dc613a22ee06add9b878197922466df641bvboxsync /*
f86f2dc613a22ee06add9b878197922466df641bvboxsync * Disconnect and release it.
f86f2dc613a22ee06add9b878197922466df641bvboxsync */
f0ed7ab5e7f8d2f73b5aa08e46eb3a04cbb31cb2vboxsync RTSpinlockAcquire(pThis->hSpinlock);
8300beb17e7c288655895d07bfdc58a01f618218vboxsync //Assert(vboxNetAdpGetState(pThis) == kVBoxNetAdpState_Connected);
8300beb17e7c288655895d07bfdc58a01f618218vboxsync Assert(!pThis->cBusy);
f86f2dc613a22ee06add9b878197922466df641bvboxsync vboxNetAdpSetState(pThis, kVBoxNetAdpState_Transitional);
c0b6af690ad705bddfa87c643b89770a7a0aaf5avboxsync RTSpinlockRelease(pThis->hSpinlock);
f86f2dc613a22ee06add9b878197922466df641bvboxsync
f86f2dc613a22ee06add9b878197922466df641bvboxsync vboxNetAdpOsDisconnectIt(pThis);
f86f2dc613a22ee06add9b878197922466df641bvboxsync pThis->pSwitchPort = NULL;
f86f2dc613a22ee06add9b878197922466df641bvboxsync
f0ed7ab5e7f8d2f73b5aa08e46eb3a04cbb31cb2vboxsync RTSpinlockAcquire(pThis->hSpinlock);
f86f2dc613a22ee06add9b878197922466df641bvboxsync vboxNetAdpSetState(pThis, kVBoxNetAdpState_Available);
c0b6af690ad705bddfa87c643b89770a7a0aaf5avboxsync RTSpinlockRelease(pThis->hSpinlock);
f86f2dc613a22ee06add9b878197922466df641bvboxsync
f86f2dc613a22ee06add9b878197922466df641bvboxsync vboxNetAdpRelease(pThis);
f86f2dc613a22ee06add9b878197922466df641bvboxsync}
f86f2dc613a22ee06add9b878197922466df641bvboxsync
f86f2dc613a22ee06add9b878197922466df641bvboxsync
f86f2dc613a22ee06add9b878197922466df641bvboxsync/**
f86f2dc613a22ee06add9b878197922466df641bvboxsync * @copydoc INTNETTRUNKIFPORT::pfnRelease
f86f2dc613a22ee06add9b878197922466df641bvboxsync */
5a9f1d57ea268b1d88ff2492d9d59a696b1c693evboxsyncstatic DECLCALLBACK(void) vboxNetAdpPortRelease(PINTNETTRUNKIFPORT pIfPort)
f86f2dc613a22ee06add9b878197922466df641bvboxsync{
f86f2dc613a22ee06add9b878197922466df641bvboxsync PVBOXNETADP pThis = IFPORT_2_VBOXNETADP(pIfPort);
f86f2dc613a22ee06add9b878197922466df641bvboxsync vboxNetAdpRelease(pThis);
f86f2dc613a22ee06add9b878197922466df641bvboxsync}
f86f2dc613a22ee06add9b878197922466df641bvboxsync
f86f2dc613a22ee06add9b878197922466df641bvboxsync
f86f2dc613a22ee06add9b878197922466df641bvboxsync/**
f86f2dc613a22ee06add9b878197922466df641bvboxsync * @copydoc INTNETTRUNKIFPORT::pfnRetain
f86f2dc613a22ee06add9b878197922466df641bvboxsync */
5a9f1d57ea268b1d88ff2492d9d59a696b1c693evboxsyncstatic DECLCALLBACK(void) vboxNetAdpPortRetain(PINTNETTRUNKIFPORT pIfPort)
f86f2dc613a22ee06add9b878197922466df641bvboxsync{
f86f2dc613a22ee06add9b878197922466df641bvboxsync PVBOXNETADP pThis = IFPORT_2_VBOXNETADP(pIfPort);
f86f2dc613a22ee06add9b878197922466df641bvboxsync vboxNetAdpRetain(pThis);
f86f2dc613a22ee06add9b878197922466df641bvboxsync}
f86f2dc613a22ee06add9b878197922466df641bvboxsync
f86f2dc613a22ee06add9b878197922466df641bvboxsync
72d7681289c829fb514dcc953c9b07ec4d20a28bvboxsyncint vboxNetAdpCreate(PINTNETTRUNKFACTORY pIfFactory, PVBOXNETADP *ppNew)
8300beb17e7c288655895d07bfdc58a01f618218vboxsync{
8300beb17e7c288655895d07bfdc58a01f618218vboxsync PVBOXNETADPGLOBALS pGlobals = (PVBOXNETADPGLOBALS)((uint8_t *)pIfFactory - RT_OFFSETOF(VBOXNETADPGLOBALS, TrunkFactory));
f0ed7ab5e7f8d2f73b5aa08e46eb3a04cbb31cb2vboxsync unsigned i;
f0ed7ab5e7f8d2f73b5aa08e46eb3a04cbb31cb2vboxsync int rc;
8300beb17e7c288655895d07bfdc58a01f618218vboxsync
8300beb17e7c288655895d07bfdc58a01f618218vboxsync for (i = 0; i < RT_ELEMENTS(pGlobals->aAdapters); i++)
8300beb17e7c288655895d07bfdc58a01f618218vboxsync {
8300beb17e7c288655895d07bfdc58a01f618218vboxsync PVBOXNETADP pThis = &pGlobals->aAdapters[i];
2a047f0d7ee5964456dbc4dec9925031482588abvboxsync
8300beb17e7c288655895d07bfdc58a01f618218vboxsync if (vboxNetAdpCheckAndSetState(pThis, kVBoxNetAdpState_Invalid, kVBoxNetAdpState_Transitional))
8300beb17e7c288655895d07bfdc58a01f618218vboxsync {
8300beb17e7c288655895d07bfdc58a01f618218vboxsync /* Found an empty slot -- use it. */
3e003a17e052e1696a96d3e344280851e9a340cavboxsync uint32_t cRefs = ASMAtomicIncU32(&pThis->cRefs);
3e003a17e052e1696a96d3e344280851e9a340cavboxsync Assert(cRefs == 1);
8300beb17e7c288655895d07bfdc58a01f618218vboxsync RTMAC Mac;
8300beb17e7c288655895d07bfdc58a01f618218vboxsync vboxNetAdpComposeMACAddress(pThis, &Mac);
8300beb17e7c288655895d07bfdc58a01f618218vboxsync rc = vboxNetAdpOsCreate(pThis, &Mac);
8300beb17e7c288655895d07bfdc58a01f618218vboxsync *ppNew = pThis;
f0ed7ab5e7f8d2f73b5aa08e46eb3a04cbb31cb2vboxsync
f0ed7ab5e7f8d2f73b5aa08e46eb3a04cbb31cb2vboxsync RTSpinlockAcquire(pThis->hSpinlock);
8300beb17e7c288655895d07bfdc58a01f618218vboxsync vboxNetAdpSetState(pThis, kVBoxNetAdpState_Available);
c0b6af690ad705bddfa87c643b89770a7a0aaf5avboxsync RTSpinlockRelease(pThis->hSpinlock);
8300beb17e7c288655895d07bfdc58a01f618218vboxsync return rc;
8300beb17e7c288655895d07bfdc58a01f618218vboxsync }
8300beb17e7c288655895d07bfdc58a01f618218vboxsync }
8300beb17e7c288655895d07bfdc58a01f618218vboxsync
8300beb17e7c288655895d07bfdc58a01f618218vboxsync /* All slots in adapter array are busy. */
8300beb17e7c288655895d07bfdc58a01f618218vboxsync return VERR_OUT_OF_RESOURCES;
8300beb17e7c288655895d07bfdc58a01f618218vboxsync}
8300beb17e7c288655895d07bfdc58a01f618218vboxsync
72d7681289c829fb514dcc953c9b07ec4d20a28bvboxsyncint vboxNetAdpDestroy(PVBOXNETADP pThis)
8300beb17e7c288655895d07bfdc58a01f618218vboxsync{
8300beb17e7c288655895d07bfdc58a01f618218vboxsync int rc = VINF_SUCCESS;
2a047f0d7ee5964456dbc4dec9925031482588abvboxsync
f0ed7ab5e7f8d2f73b5aa08e46eb3a04cbb31cb2vboxsync RTSpinlockAcquire(pThis->hSpinlock);
8300beb17e7c288655895d07bfdc58a01f618218vboxsync if (vboxNetAdpGetState(pThis) != kVBoxNetAdpState_Available || pThis->cBusy)
8300beb17e7c288655895d07bfdc58a01f618218vboxsync {
c0b6af690ad705bddfa87c643b89770a7a0aaf5avboxsync RTSpinlockRelease(pThis->hSpinlock);
8300beb17e7c288655895d07bfdc58a01f618218vboxsync return VERR_INTNET_FLT_IF_BUSY;
8300beb17e7c288655895d07bfdc58a01f618218vboxsync }
8300beb17e7c288655895d07bfdc58a01f618218vboxsync vboxNetAdpSetState(pThis, kVBoxNetAdpState_Transitional);
c0b6af690ad705bddfa87c643b89770a7a0aaf5avboxsync RTSpinlockRelease(pThis->hSpinlock);
8300beb17e7c288655895d07bfdc58a01f618218vboxsync vboxNetAdpRelease(pThis);
8300beb17e7c288655895d07bfdc58a01f618218vboxsync
8300beb17e7c288655895d07bfdc58a01f618218vboxsync vboxNetAdpOsDestroy(pThis);
8300beb17e7c288655895d07bfdc58a01f618218vboxsync
f0ed7ab5e7f8d2f73b5aa08e46eb3a04cbb31cb2vboxsync RTSpinlockAcquire(pThis->hSpinlock);
8300beb17e7c288655895d07bfdc58a01f618218vboxsync vboxNetAdpSetState(pThis, kVBoxNetAdpState_Invalid);
c0b6af690ad705bddfa87c643b89770a7a0aaf5avboxsync RTSpinlockRelease(pThis->hSpinlock);
8300beb17e7c288655895d07bfdc58a01f618218vboxsync
8300beb17e7c288655895d07bfdc58a01f618218vboxsync return rc;
8300beb17e7c288655895d07bfdc58a01f618218vboxsync}
8300beb17e7c288655895d07bfdc58a01f618218vboxsync
f86f2dc613a22ee06add9b878197922466df641bvboxsync/**
f86f2dc613a22ee06add9b878197922466df641bvboxsync * Connects the instance to the specified switch port.
f86f2dc613a22ee06add9b878197922466df641bvboxsync *
f86f2dc613a22ee06add9b878197922466df641bvboxsync * Called while owning the lock. We're ASSUMING that the internal
f86f2dc613a22ee06add9b878197922466df641bvboxsync * networking code is already owning an recursive mutex, so, there
f86f2dc613a22ee06add9b878197922466df641bvboxsync * will be no deadlocks when vboxNetAdpOsConnectIt calls back into
f86f2dc613a22ee06add9b878197922466df641bvboxsync * it for setting preferences.
f86f2dc613a22ee06add9b878197922466df641bvboxsync *
f86f2dc613a22ee06add9b878197922466df641bvboxsync * @returns VBox status code.
f86f2dc613a22ee06add9b878197922466df641bvboxsync * @param pThis The instance.
f86f2dc613a22ee06add9b878197922466df641bvboxsync * @param pSwitchPort The port on the internal network 'switch'.
f86f2dc613a22ee06add9b878197922466df641bvboxsync * @param ppIfPort Where to return our port interface.
f86f2dc613a22ee06add9b878197922466df641bvboxsync */
f86f2dc613a22ee06add9b878197922466df641bvboxsyncstatic int vboxNetAdpConnectIt(PVBOXNETADP pThis, PINTNETTRUNKSWPORT pSwitchPort, PINTNETTRUNKIFPORT *ppIfPort)
f86f2dc613a22ee06add9b878197922466df641bvboxsync{
f86f2dc613a22ee06add9b878197922466df641bvboxsync int rc;
f86f2dc613a22ee06add9b878197922466df641bvboxsync
f86f2dc613a22ee06add9b878197922466df641bvboxsync /*
f86f2dc613a22ee06add9b878197922466df641bvboxsync * Validate state.
f86f2dc613a22ee06add9b878197922466df641bvboxsync */
f86f2dc613a22ee06add9b878197922466df641bvboxsync Assert(!pThis->cBusy);
8300beb17e7c288655895d07bfdc58a01f618218vboxsync Assert(vboxNetAdpGetStateWithLock(pThis) == kVBoxNetAdpState_Transitional);
f86f2dc613a22ee06add9b878197922466df641bvboxsync
f86f2dc613a22ee06add9b878197922466df641bvboxsync /*
f86f2dc613a22ee06add9b878197922466df641bvboxsync * Do the job.
f86f2dc613a22ee06add9b878197922466df641bvboxsync * Note that we're calling the os stuff while owning the semaphore here.
f86f2dc613a22ee06add9b878197922466df641bvboxsync */
f86f2dc613a22ee06add9b878197922466df641bvboxsync pThis->pSwitchPort = pSwitchPort;
f86f2dc613a22ee06add9b878197922466df641bvboxsync rc = vboxNetAdpOsConnectIt(pThis);
f86f2dc613a22ee06add9b878197922466df641bvboxsync if (RT_SUCCESS(rc))
f86f2dc613a22ee06add9b878197922466df641bvboxsync {
f86f2dc613a22ee06add9b878197922466df641bvboxsync *ppIfPort = &pThis->MyPort;
f86f2dc613a22ee06add9b878197922466df641bvboxsync }
f86f2dc613a22ee06add9b878197922466df641bvboxsync else
f86f2dc613a22ee06add9b878197922466df641bvboxsync pThis->pSwitchPort = NULL;
f86f2dc613a22ee06add9b878197922466df641bvboxsync
f86f2dc613a22ee06add9b878197922466df641bvboxsync return rc;
f86f2dc613a22ee06add9b878197922466df641bvboxsync}
f86f2dc613a22ee06add9b878197922466df641bvboxsync
2a047f0d7ee5964456dbc4dec9925031482588abvboxsync
f86f2dc613a22ee06add9b878197922466df641bvboxsync/**
f86f2dc613a22ee06add9b878197922466df641bvboxsync * @copydoc INTNETTRUNKFACTORY::pfnCreateAndConnect
f86f2dc613a22ee06add9b878197922466df641bvboxsync */
f86f2dc613a22ee06add9b878197922466df641bvboxsyncstatic DECLCALLBACK(int) vboxNetAdpFactoryCreateAndConnect(PINTNETTRUNKFACTORY pIfFactory, const char *pszName,
2a047f0d7ee5964456dbc4dec9925031482588abvboxsync PINTNETTRUNKSWPORT pSwitchPort, uint32_t fFlags,
2a047f0d7ee5964456dbc4dec9925031482588abvboxsync PINTNETTRUNKIFPORT *ppIfPort)
f86f2dc613a22ee06add9b878197922466df641bvboxsync{
2a047f0d7ee5964456dbc4dec9925031482588abvboxsync PVBOXNETADPGLOBALS pGlobals = (PVBOXNETADPGLOBALS)((uint8_t *)pIfFactory - RT_OFFSETOF(VBOXNETADPGLOBALS, TrunkFactory));
f86f2dc613a22ee06add9b878197922466df641bvboxsync PVBOXNETADP pThis;
f86f2dc613a22ee06add9b878197922466df641bvboxsync int rc;
f86f2dc613a22ee06add9b878197922466df641bvboxsync
2a047f0d7ee5964456dbc4dec9925031482588abvboxsync LogFlow(("vboxNetAdpFactoryCreateAndConnect: pszName=%p:{%s} fFlags=%#x\n", pszName, pszName, fFlags));
f86f2dc613a22ee06add9b878197922466df641bvboxsync Assert(pGlobals->cFactoryRefs > 0);
d2cf175ed00723f7896557c3be24932730ef3539vboxsync AssertMsgReturn(!fFlags,
2a047f0d7ee5964456dbc4dec9925031482588abvboxsync ("%#x\n", fFlags), VERR_INVALID_PARAMETER);
f86f2dc613a22ee06add9b878197922466df641bvboxsync
f86f2dc613a22ee06add9b878197922466df641bvboxsync /*
f86f2dc613a22ee06add9b878197922466df641bvboxsync * Find instance, check if busy, connect if not.
f86f2dc613a22ee06add9b878197922466df641bvboxsync */
f86f2dc613a22ee06add9b878197922466df641bvboxsync pThis = vboxNetAdpFind(pGlobals, pszName);
f86f2dc613a22ee06add9b878197922466df641bvboxsync if (pThis)
f86f2dc613a22ee06add9b878197922466df641bvboxsync {
8300beb17e7c288655895d07bfdc58a01f618218vboxsync if (vboxNetAdpCheckAndSetState(pThis, kVBoxNetAdpState_Available, kVBoxNetAdpState_Transitional))
f86f2dc613a22ee06add9b878197922466df641bvboxsync {
8300beb17e7c288655895d07bfdc58a01f618218vboxsync vboxNetAdpRetain(pThis);
f86f2dc613a22ee06add9b878197922466df641bvboxsync rc = vboxNetAdpConnectIt(pThis, pSwitchPort, ppIfPort);
8300beb17e7c288655895d07bfdc58a01f618218vboxsync vboxNetAdpSetStateWithLock(pThis, RT_SUCCESS(rc) ? kVBoxNetAdpState_Connected : kVBoxNetAdpState_Available);
f86f2dc613a22ee06add9b878197922466df641bvboxsync }
f86f2dc613a22ee06add9b878197922466df641bvboxsync else
f86f2dc613a22ee06add9b878197922466df641bvboxsync rc = VERR_INTNET_FLT_IF_BUSY;
f86f2dc613a22ee06add9b878197922466df641bvboxsync }
f86f2dc613a22ee06add9b878197922466df641bvboxsync else
f86f2dc613a22ee06add9b878197922466df641bvboxsync rc = VERR_INTNET_FLT_IF_NOT_FOUND;
f86f2dc613a22ee06add9b878197922466df641bvboxsync
f86f2dc613a22ee06add9b878197922466df641bvboxsync return rc;
f86f2dc613a22ee06add9b878197922466df641bvboxsync}
f86f2dc613a22ee06add9b878197922466df641bvboxsync
2a047f0d7ee5964456dbc4dec9925031482588abvboxsync
f86f2dc613a22ee06add9b878197922466df641bvboxsync/**
f86f2dc613a22ee06add9b878197922466df641bvboxsync * @copydoc INTNETTRUNKFACTORY::pfnRelease
f86f2dc613a22ee06add9b878197922466df641bvboxsync */
f86f2dc613a22ee06add9b878197922466df641bvboxsyncstatic DECLCALLBACK(void) vboxNetAdpFactoryRelease(PINTNETTRUNKFACTORY pIfFactory)
f86f2dc613a22ee06add9b878197922466df641bvboxsync{
f86f2dc613a22ee06add9b878197922466df641bvboxsync PVBOXNETADPGLOBALS pGlobals = (PVBOXNETADPGLOBALS)((uint8_t *)pIfFactory - RT_OFFSETOF(VBOXNETADPGLOBALS, TrunkFactory));
f86f2dc613a22ee06add9b878197922466df641bvboxsync
f86f2dc613a22ee06add9b878197922466df641bvboxsync int32_t cRefs = ASMAtomicDecS32(&pGlobals->cFactoryRefs);
f86f2dc613a22ee06add9b878197922466df641bvboxsync Assert(cRefs >= 0); NOREF(cRefs);
f86f2dc613a22ee06add9b878197922466df641bvboxsync LogFlow(("vboxNetAdpFactoryRelease: cRefs=%d (new)\n", cRefs));
f86f2dc613a22ee06add9b878197922466df641bvboxsync}
f86f2dc613a22ee06add9b878197922466df641bvboxsync
f86f2dc613a22ee06add9b878197922466df641bvboxsync
f86f2dc613a22ee06add9b878197922466df641bvboxsync/**
f86f2dc613a22ee06add9b878197922466df641bvboxsync * Implements the SUPDRV component factor interface query method.
f86f2dc613a22ee06add9b878197922466df641bvboxsync *
f86f2dc613a22ee06add9b878197922466df641bvboxsync * @returns Pointer to an interface. NULL if not supported.
f86f2dc613a22ee06add9b878197922466df641bvboxsync *
f86f2dc613a22ee06add9b878197922466df641bvboxsync * @param pSupDrvFactory Pointer to the component factory registration structure.
f86f2dc613a22ee06add9b878197922466df641bvboxsync * @param pSession The session - unused.
f86f2dc613a22ee06add9b878197922466df641bvboxsync * @param pszInterfaceUuid The factory interface id.
f86f2dc613a22ee06add9b878197922466df641bvboxsync */
f86f2dc613a22ee06add9b878197922466df641bvboxsyncstatic DECLCALLBACK(void *) vboxNetAdpQueryFactoryInterface(PCSUPDRVFACTORY pSupDrvFactory, PSUPDRVSESSION pSession, const char *pszInterfaceUuid)
f86f2dc613a22ee06add9b878197922466df641bvboxsync{
f86f2dc613a22ee06add9b878197922466df641bvboxsync PVBOXNETADPGLOBALS pGlobals = (PVBOXNETADPGLOBALS)((uint8_t *)pSupDrvFactory - RT_OFFSETOF(VBOXNETADPGLOBALS, SupDrvFactory));
f86f2dc613a22ee06add9b878197922466df641bvboxsync
f86f2dc613a22ee06add9b878197922466df641bvboxsync /*
f86f2dc613a22ee06add9b878197922466df641bvboxsync * Convert the UUID strings and compare them.
f86f2dc613a22ee06add9b878197922466df641bvboxsync */
f86f2dc613a22ee06add9b878197922466df641bvboxsync RTUUID UuidReq;
f86f2dc613a22ee06add9b878197922466df641bvboxsync int rc = RTUuidFromStr(&UuidReq, pszInterfaceUuid);
f86f2dc613a22ee06add9b878197922466df641bvboxsync if (RT_SUCCESS(rc))
f86f2dc613a22ee06add9b878197922466df641bvboxsync {
f86f2dc613a22ee06add9b878197922466df641bvboxsync if (!RTUuidCompareStr(&UuidReq, INTNETTRUNKFACTORY_UUID_STR))
f86f2dc613a22ee06add9b878197922466df641bvboxsync {
f86f2dc613a22ee06add9b878197922466df641bvboxsync ASMAtomicIncS32(&pGlobals->cFactoryRefs);
f86f2dc613a22ee06add9b878197922466df641bvboxsync return &pGlobals->TrunkFactory;
f86f2dc613a22ee06add9b878197922466df641bvboxsync }
f86f2dc613a22ee06add9b878197922466df641bvboxsync#ifdef LOG_ENABLED
f86f2dc613a22ee06add9b878197922466df641bvboxsync else
f86f2dc613a22ee06add9b878197922466df641bvboxsync Log(("VBoxNetAdp: unknown factory interface query (%s)\n", pszInterfaceUuid));
f86f2dc613a22ee06add9b878197922466df641bvboxsync#endif
f86f2dc613a22ee06add9b878197922466df641bvboxsync }
f86f2dc613a22ee06add9b878197922466df641bvboxsync else
f86f2dc613a22ee06add9b878197922466df641bvboxsync Log(("VBoxNetAdp: rc=%Rrc, uuid=%s\n", rc, pszInterfaceUuid));
f86f2dc613a22ee06add9b878197922466df641bvboxsync
f86f2dc613a22ee06add9b878197922466df641bvboxsync return NULL;
f86f2dc613a22ee06add9b878197922466df641bvboxsync}
f86f2dc613a22ee06add9b878197922466df641bvboxsync
f86f2dc613a22ee06add9b878197922466df641bvboxsync
f86f2dc613a22ee06add9b878197922466df641bvboxsync/**
f86f2dc613a22ee06add9b878197922466df641bvboxsync * Checks whether the VBoxNetAdp wossname can be unloaded.
f86f2dc613a22ee06add9b878197922466df641bvboxsync *
f86f2dc613a22ee06add9b878197922466df641bvboxsync * This will return false if someone is currently using the module.
f86f2dc613a22ee06add9b878197922466df641bvboxsync *
f86f2dc613a22ee06add9b878197922466df641bvboxsync * @returns true if it's relatively safe to unload it, otherwise false.
f86f2dc613a22ee06add9b878197922466df641bvboxsync * @param pGlobals Pointer to the globals.
f86f2dc613a22ee06add9b878197922466df641bvboxsync */
f86f2dc613a22ee06add9b878197922466df641bvboxsyncDECLHIDDEN(bool) vboxNetAdpCanUnload(PVBOXNETADPGLOBALS pGlobals)
f86f2dc613a22ee06add9b878197922466df641bvboxsync{
f86f2dc613a22ee06add9b878197922466df641bvboxsync bool fRc = true; /* Assume it can be unloaded. */
ccc948c886b751603889a67909fbd4a5fcaeac85vboxsync unsigned i;
f86f2dc613a22ee06add9b878197922466df641bvboxsync
f86f2dc613a22ee06add9b878197922466df641bvboxsync for (i = 0; i < RT_ELEMENTS(pGlobals->aAdapters); i++)
f86f2dc613a22ee06add9b878197922466df641bvboxsync {
f86f2dc613a22ee06add9b878197922466df641bvboxsync PVBOXNETADP pThis = &pGlobals->aAdapters[i];
8300beb17e7c288655895d07bfdc58a01f618218vboxsync if (vboxNetAdpGetStateWithLock(&pGlobals->aAdapters[i]) >= kVBoxNetAdpState_Connected)
f86f2dc613a22ee06add9b878197922466df641bvboxsync {
f86f2dc613a22ee06add9b878197922466df641bvboxsync fRc = false;
f86f2dc613a22ee06add9b878197922466df641bvboxsync break; /* We already know the answer. */
f86f2dc613a22ee06add9b878197922466df641bvboxsync }
f86f2dc613a22ee06add9b878197922466df641bvboxsync }
f86f2dc613a22ee06add9b878197922466df641bvboxsync return fRc && ASMAtomicUoReadS32((int32_t volatile *)&pGlobals->cFactoryRefs) <= 0;
f86f2dc613a22ee06add9b878197922466df641bvboxsync}
f86f2dc613a22ee06add9b878197922466df641bvboxsync
f86f2dc613a22ee06add9b878197922466df641bvboxsync/**
f86f2dc613a22ee06add9b878197922466df641bvboxsync * tries to deinitialize Idc
f86f2dc613a22ee06add9b878197922466df641bvboxsync * we separate the globals settings "base" which is actually
f86f2dc613a22ee06add9b878197922466df641bvboxsync * "general" globals settings except for Idc, and idc.
f86f2dc613a22ee06add9b878197922466df641bvboxsync * This is needed for windows filter driver, which gets loaded prior to VBoxDrv,
f86f2dc613a22ee06add9b878197922466df641bvboxsync * thus it's not possible to make idc initialization from the driver startup routine for it,
f86f2dc613a22ee06add9b878197922466df641bvboxsync * though the "base is still needed for the driver to functions".
f86f2dc613a22ee06add9b878197922466df641bvboxsync * @param pGlobals
ad27e1d5e48ca41245120c331cc88b50464813cevboxsync * @return VINF_SUCCESS on success, VERR_WRONG_ORDER if we're busy.
f86f2dc613a22ee06add9b878197922466df641bvboxsync */
f86f2dc613a22ee06add9b878197922466df641bvboxsyncDECLHIDDEN(int) vboxNetAdpTryDeleteIdc(PVBOXNETADPGLOBALS pGlobals)
f86f2dc613a22ee06add9b878197922466df641bvboxsync{
f86f2dc613a22ee06add9b878197922466df641bvboxsync int rc;
f86f2dc613a22ee06add9b878197922466df641bvboxsync
f86f2dc613a22ee06add9b878197922466df641bvboxsync Assert(pGlobals->hFastMtx != NIL_RTSEMFASTMUTEX);
f86f2dc613a22ee06add9b878197922466df641bvboxsync
f86f2dc613a22ee06add9b878197922466df641bvboxsync /*
f86f2dc613a22ee06add9b878197922466df641bvboxsync * Check before trying to deregister the factory.
f86f2dc613a22ee06add9b878197922466df641bvboxsync */
f86f2dc613a22ee06add9b878197922466df641bvboxsync if (!vboxNetAdpCanUnload(pGlobals))
f86f2dc613a22ee06add9b878197922466df641bvboxsync return VERR_WRONG_ORDER;
f86f2dc613a22ee06add9b878197922466df641bvboxsync
f86f2dc613a22ee06add9b878197922466df641bvboxsync /*
f86f2dc613a22ee06add9b878197922466df641bvboxsync * Disconnect from SUPDRV and check that nobody raced us,
f86f2dc613a22ee06add9b878197922466df641bvboxsync * reconnect if that should happen.
f86f2dc613a22ee06add9b878197922466df641bvboxsync */
f86f2dc613a22ee06add9b878197922466df641bvboxsync rc = SUPR0IdcComponentDeregisterFactory(&pGlobals->SupDrvIDC, &pGlobals->SupDrvFactory);
f86f2dc613a22ee06add9b878197922466df641bvboxsync AssertRC(rc);
f86f2dc613a22ee06add9b878197922466df641bvboxsync if (!vboxNetAdpCanUnload(pGlobals))
f86f2dc613a22ee06add9b878197922466df641bvboxsync {
f86f2dc613a22ee06add9b878197922466df641bvboxsync rc = SUPR0IdcComponentRegisterFactory(&pGlobals->SupDrvIDC, &pGlobals->SupDrvFactory);
f86f2dc613a22ee06add9b878197922466df641bvboxsync AssertRC(rc);
f86f2dc613a22ee06add9b878197922466df641bvboxsync return VERR_WRONG_ORDER;
f86f2dc613a22ee06add9b878197922466df641bvboxsync }
f86f2dc613a22ee06add9b878197922466df641bvboxsync
f86f2dc613a22ee06add9b878197922466df641bvboxsync SUPR0IdcClose(&pGlobals->SupDrvIDC);
f86f2dc613a22ee06add9b878197922466df641bvboxsync
f86f2dc613a22ee06add9b878197922466df641bvboxsync return rc;
f86f2dc613a22ee06add9b878197922466df641bvboxsync}
f86f2dc613a22ee06add9b878197922466df641bvboxsync
8300beb17e7c288655895d07bfdc58a01f618218vboxsyncstatic int vboxNetAdpSlotCreate(PVBOXNETADPGLOBALS pGlobals, unsigned uUnit, PVBOXNETADP pNew)
8300beb17e7c288655895d07bfdc58a01f618218vboxsync{
8300beb17e7c288655895d07bfdc58a01f618218vboxsync int rc;
8300beb17e7c288655895d07bfdc58a01f618218vboxsync
8300beb17e7c288655895d07bfdc58a01f618218vboxsync pNew->MyPort.u32Version = INTNETTRUNKIFPORT_VERSION;
5a9f1d57ea268b1d88ff2492d9d59a696b1c693evboxsync pNew->MyPort.pfnRetain = vboxNetAdpPortRetain;
5a9f1d57ea268b1d88ff2492d9d59a696b1c693evboxsync pNew->MyPort.pfnRelease = vboxNetAdpPortRelease;
5a9f1d57ea268b1d88ff2492d9d59a696b1c693evboxsync pNew->MyPort.pfnDisconnectAndRelease= vboxNetAdpPortDisconnectAndRelease;
d61e6f5b11d9031623420bd7ed3013477d8f402dvboxsync pNew->MyPort.pfnSetState = vboxNetAdpPortSetState;
5a9f1d57ea268b1d88ff2492d9d59a696b1c693evboxsync pNew->MyPort.pfnWaitForIdle = vboxNetAdpPortWaitForIdle;
5a9f1d57ea268b1d88ff2492d9d59a696b1c693evboxsync pNew->MyPort.pfnXmit = vboxNetAdpPortXmit;
8300beb17e7c288655895d07bfdc58a01f618218vboxsync pNew->MyPort.u32VersionEnd = INTNETTRUNKIFPORT_VERSION;
8300beb17e7c288655895d07bfdc58a01f618218vboxsync pNew->pSwitchPort = NULL;
8300beb17e7c288655895d07bfdc58a01f618218vboxsync pNew->pGlobals = pGlobals;
8300beb17e7c288655895d07bfdc58a01f618218vboxsync pNew->hSpinlock = NIL_RTSPINLOCK;
8300beb17e7c288655895d07bfdc58a01f618218vboxsync pNew->enmState = kVBoxNetAdpState_Invalid;
8300beb17e7c288655895d07bfdc58a01f618218vboxsync pNew->cRefs = 0;
8300beb17e7c288655895d07bfdc58a01f618218vboxsync pNew->cBusy = 0;
8300beb17e7c288655895d07bfdc58a01f618218vboxsync pNew->hEventIdle = NIL_RTSEMEVENT;
8300beb17e7c288655895d07bfdc58a01f618218vboxsync
f0ed7ab5e7f8d2f73b5aa08e46eb3a04cbb31cb2vboxsync rc = RTSpinlockCreate(&pNew->hSpinlock, RTSPINLOCK_FLAGS_INTERRUPT_SAFE, "VBoxNetAdptSlotCreate");
8300beb17e7c288655895d07bfdc58a01f618218vboxsync if (RT_SUCCESS(rc))
8300beb17e7c288655895d07bfdc58a01f618218vboxsync {
8300beb17e7c288655895d07bfdc58a01f618218vboxsync rc = RTSemEventCreate(&pNew->hEventIdle);
8300beb17e7c288655895d07bfdc58a01f618218vboxsync if (RT_SUCCESS(rc))
8300beb17e7c288655895d07bfdc58a01f618218vboxsync {
8300beb17e7c288655895d07bfdc58a01f618218vboxsync rc = vboxNetAdpOsInit(pNew);
8300beb17e7c288655895d07bfdc58a01f618218vboxsync if (RT_SUCCESS(rc))
8300beb17e7c288655895d07bfdc58a01f618218vboxsync {
8300beb17e7c288655895d07bfdc58a01f618218vboxsync return rc;
8300beb17e7c288655895d07bfdc58a01f618218vboxsync }
8300beb17e7c288655895d07bfdc58a01f618218vboxsync RTSemEventDestroy(pNew->hEventIdle);
8300beb17e7c288655895d07bfdc58a01f618218vboxsync pNew->hEventIdle = NIL_RTSEMEVENT;
8300beb17e7c288655895d07bfdc58a01f618218vboxsync }
8300beb17e7c288655895d07bfdc58a01f618218vboxsync RTSpinlockDestroy(pNew->hSpinlock);
8300beb17e7c288655895d07bfdc58a01f618218vboxsync pNew->hSpinlock = NIL_RTSPINLOCK;
8300beb17e7c288655895d07bfdc58a01f618218vboxsync }
8300beb17e7c288655895d07bfdc58a01f618218vboxsync return rc;
8300beb17e7c288655895d07bfdc58a01f618218vboxsync}
8300beb17e7c288655895d07bfdc58a01f618218vboxsync
8300beb17e7c288655895d07bfdc58a01f618218vboxsyncstatic void vboxNetAdpSlotDestroy(PVBOXNETADP pThis)
8300beb17e7c288655895d07bfdc58a01f618218vboxsync{
8300beb17e7c288655895d07bfdc58a01f618218vboxsync Assert(pThis->cRefs == 0);
8300beb17e7c288655895d07bfdc58a01f618218vboxsync Assert(pThis->cBusy == 0);
8300beb17e7c288655895d07bfdc58a01f618218vboxsync Assert(vboxNetAdpGetState(pThis) == kVBoxNetAdpState_Invalid);
8300beb17e7c288655895d07bfdc58a01f618218vboxsync if (pThis->hEventIdle != NIL_RTSEMEVENT)
8300beb17e7c288655895d07bfdc58a01f618218vboxsync {
8300beb17e7c288655895d07bfdc58a01f618218vboxsync RTSemEventDestroy(pThis->hEventIdle);
8300beb17e7c288655895d07bfdc58a01f618218vboxsync pThis->hEventIdle = NIL_RTSEMEVENT;
8300beb17e7c288655895d07bfdc58a01f618218vboxsync }
8300beb17e7c288655895d07bfdc58a01f618218vboxsync if (pThis->hSpinlock != NIL_RTSPINLOCK)
8300beb17e7c288655895d07bfdc58a01f618218vboxsync {
8300beb17e7c288655895d07bfdc58a01f618218vboxsync RTSpinlockDestroy(pThis->hSpinlock);
8300beb17e7c288655895d07bfdc58a01f618218vboxsync pThis->hSpinlock = NIL_RTSPINLOCK;
8300beb17e7c288655895d07bfdc58a01f618218vboxsync }
8300beb17e7c288655895d07bfdc58a01f618218vboxsync}
8300beb17e7c288655895d07bfdc58a01f618218vboxsync
f86f2dc613a22ee06add9b878197922466df641bvboxsync/**
f86f2dc613a22ee06add9b878197922466df641bvboxsync * performs "base" globals deinitialization
f86f2dc613a22ee06add9b878197922466df641bvboxsync * we separate the globals settings "base" which is actually
f86f2dc613a22ee06add9b878197922466df641bvboxsync * "general" globals settings except for Idc, and idc.
f86f2dc613a22ee06add9b878197922466df641bvboxsync * This is needed for windows filter driver, which gets loaded prior to VBoxDrv,
f86f2dc613a22ee06add9b878197922466df641bvboxsync * thus it's not possible to make idc initialization from the driver startup routine for it,
f86f2dc613a22ee06add9b878197922466df641bvboxsync * though the "base is still needed for the driver to functions".
f86f2dc613a22ee06add9b878197922466df641bvboxsync * @param pGlobals
f86f2dc613a22ee06add9b878197922466df641bvboxsync * @return none
f86f2dc613a22ee06add9b878197922466df641bvboxsync */
f86f2dc613a22ee06add9b878197922466df641bvboxsyncDECLHIDDEN(void) vboxNetAdpDeleteGlobalsBase(PVBOXNETADPGLOBALS pGlobals)
f86f2dc613a22ee06add9b878197922466df641bvboxsync{
8300beb17e7c288655895d07bfdc58a01f618218vboxsync int i;
f86f2dc613a22ee06add9b878197922466df641bvboxsync /*
f86f2dc613a22ee06add9b878197922466df641bvboxsync * Release resources.
f86f2dc613a22ee06add9b878197922466df641bvboxsync */
8300beb17e7c288655895d07bfdc58a01f618218vboxsync for (i = 0; i < (int)RT_ELEMENTS(pGlobals->aAdapters); i++)
8300beb17e7c288655895d07bfdc58a01f618218vboxsync if (RT_SUCCESS(vboxNetAdpDestroy(&pGlobals->aAdapters[i])))
8300beb17e7c288655895d07bfdc58a01f618218vboxsync vboxNetAdpSlotDestroy(&pGlobals->aAdapters[i]);
8300beb17e7c288655895d07bfdc58a01f618218vboxsync
f86f2dc613a22ee06add9b878197922466df641bvboxsync RTSemFastMutexDestroy(pGlobals->hFastMtx);
f86f2dc613a22ee06add9b878197922466df641bvboxsync pGlobals->hFastMtx = NIL_RTSEMFASTMUTEX;
f86f2dc613a22ee06add9b878197922466df641bvboxsync
f86f2dc613a22ee06add9b878197922466df641bvboxsync#ifdef VBOXNETADP_STATIC_CONFIG
f86f2dc613a22ee06add9b878197922466df641bvboxsync RTSemEventDestroy(pGlobals->hTimerEvent);
f86f2dc613a22ee06add9b878197922466df641bvboxsync pGlobals->hTimerEvent = NIL_RTSEMEVENT;
f86f2dc613a22ee06add9b878197922466df641bvboxsync#endif
f86f2dc613a22ee06add9b878197922466df641bvboxsync
f86f2dc613a22ee06add9b878197922466df641bvboxsync}
f86f2dc613a22ee06add9b878197922466df641bvboxsync
2a047f0d7ee5964456dbc4dec9925031482588abvboxsync
f86f2dc613a22ee06add9b878197922466df641bvboxsync/**
f86f2dc613a22ee06add9b878197922466df641bvboxsync * Called by the native part when the OS wants the driver to unload.
f86f2dc613a22ee06add9b878197922466df641bvboxsync *
ad27e1d5e48ca41245120c331cc88b50464813cevboxsync * @returns VINF_SUCCESS on success, VERR_WRONG_ORDER if we're busy.
f86f2dc613a22ee06add9b878197922466df641bvboxsync *
f86f2dc613a22ee06add9b878197922466df641bvboxsync * @param pGlobals Pointer to the globals.
f86f2dc613a22ee06add9b878197922466df641bvboxsync */
f86f2dc613a22ee06add9b878197922466df641bvboxsyncDECLHIDDEN(int) vboxNetAdpTryDeleteGlobals(PVBOXNETADPGLOBALS pGlobals)
f86f2dc613a22ee06add9b878197922466df641bvboxsync{
f86f2dc613a22ee06add9b878197922466df641bvboxsync int rc = vboxNetAdpTryDeleteIdc(pGlobals);
2a047f0d7ee5964456dbc4dec9925031482588abvboxsync if (RT_SUCCESS(rc))
f86f2dc613a22ee06add9b878197922466df641bvboxsync {
f86f2dc613a22ee06add9b878197922466df641bvboxsync vboxNetAdpDeleteGlobalsBase(pGlobals);
f86f2dc613a22ee06add9b878197922466df641bvboxsync }
f86f2dc613a22ee06add9b878197922466df641bvboxsync return rc;
f86f2dc613a22ee06add9b878197922466df641bvboxsync}
f86f2dc613a22ee06add9b878197922466df641bvboxsync
8300beb17e7c288655895d07bfdc58a01f618218vboxsync
f86f2dc613a22ee06add9b878197922466df641bvboxsync/**
f86f2dc613a22ee06add9b878197922466df641bvboxsync * performs the "base" globals initialization
f86f2dc613a22ee06add9b878197922466df641bvboxsync * we separate the globals initialization to globals "base" initialization which is actually
f86f2dc613a22ee06add9b878197922466df641bvboxsync * "general" globals initialization except for Idc not being initialized, and idc initialization.
f86f2dc613a22ee06add9b878197922466df641bvboxsync * This is needed for windows filter driver, which gets loaded prior to VBoxDrv,
f86f2dc613a22ee06add9b878197922466df641bvboxsync * thus it's not possible to make idc initialization from the driver startup routine for it.
f86f2dc613a22ee06add9b878197922466df641bvboxsync *
f86f2dc613a22ee06add9b878197922466df641bvboxsync * @returns VBox status code.
f86f2dc613a22ee06add9b878197922466df641bvboxsync * @param pGlobals Pointer to the globals. */
f86f2dc613a22ee06add9b878197922466df641bvboxsyncDECLHIDDEN(int) vboxNetAdpInitGlobalsBase(PVBOXNETADPGLOBALS pGlobals)
f86f2dc613a22ee06add9b878197922466df641bvboxsync{
f86f2dc613a22ee06add9b878197922466df641bvboxsync /*
f86f2dc613a22ee06add9b878197922466df641bvboxsync * Initialize the common portions of the structure.
f86f2dc613a22ee06add9b878197922466df641bvboxsync */
f86f2dc613a22ee06add9b878197922466df641bvboxsync int i;
f86f2dc613a22ee06add9b878197922466df641bvboxsync int rc = RTSemFastMutexCreate(&pGlobals->hFastMtx);
f86f2dc613a22ee06add9b878197922466df641bvboxsync if (RT_SUCCESS(rc))
f86f2dc613a22ee06add9b878197922466df641bvboxsync {
f86f2dc613a22ee06add9b878197922466df641bvboxsync memset(pGlobals->aAdapters, 0, sizeof(pGlobals->aAdapters));
f86f2dc613a22ee06add9b878197922466df641bvboxsync for (i = 0; i < (int)RT_ELEMENTS(pGlobals->aAdapters); i++)
f86f2dc613a22ee06add9b878197922466df641bvboxsync {
8300beb17e7c288655895d07bfdc58a01f618218vboxsync rc = vboxNetAdpSlotCreate(pGlobals, i, &pGlobals->aAdapters[i]);
f86f2dc613a22ee06add9b878197922466df641bvboxsync if (RT_FAILURE(rc))
f86f2dc613a22ee06add9b878197922466df641bvboxsync {
f86f2dc613a22ee06add9b878197922466df641bvboxsync /* Clean up. */
f86f2dc613a22ee06add9b878197922466df641bvboxsync while (--i >= 0)
8300beb17e7c288655895d07bfdc58a01f618218vboxsync vboxNetAdpSlotDestroy(&pGlobals->aAdapters[i]);
f86f2dc613a22ee06add9b878197922466df641bvboxsync Log(("vboxNetAdpInitGlobalsBase: Failed to create fast mutex (rc=%Rrc).\n", rc));
f86f2dc613a22ee06add9b878197922466df641bvboxsync RTSemFastMutexDestroy(pGlobals->hFastMtx);
f86f2dc613a22ee06add9b878197922466df641bvboxsync return rc;
f86f2dc613a22ee06add9b878197922466df641bvboxsync }
f86f2dc613a22ee06add9b878197922466df641bvboxsync }
f86f2dc613a22ee06add9b878197922466df641bvboxsync pGlobals->TrunkFactory.pfnRelease = vboxNetAdpFactoryRelease;
f86f2dc613a22ee06add9b878197922466df641bvboxsync pGlobals->TrunkFactory.pfnCreateAndConnect = vboxNetAdpFactoryCreateAndConnect;
f86f2dc613a22ee06add9b878197922466df641bvboxsync
8300beb17e7c288655895d07bfdc58a01f618218vboxsync strcpy(pGlobals->SupDrvFactory.szName, "VBoxNetAdp");
f86f2dc613a22ee06add9b878197922466df641bvboxsync pGlobals->SupDrvFactory.pfnQueryFactoryInterface = vboxNetAdpQueryFactoryInterface;
f86f2dc613a22ee06add9b878197922466df641bvboxsync }
f86f2dc613a22ee06add9b878197922466df641bvboxsync
f86f2dc613a22ee06add9b878197922466df641bvboxsync return rc;
f86f2dc613a22ee06add9b878197922466df641bvboxsync}
f86f2dc613a22ee06add9b878197922466df641bvboxsync
f86f2dc613a22ee06add9b878197922466df641bvboxsync/**
f86f2dc613a22ee06add9b878197922466df641bvboxsync * performs the Idc initialization
f86f2dc613a22ee06add9b878197922466df641bvboxsync * we separate the globals initialization to globals "base" initialization which is actually
f86f2dc613a22ee06add9b878197922466df641bvboxsync * "general" globals initialization except for Idc not being initialized, and idc initialization.
f86f2dc613a22ee06add9b878197922466df641bvboxsync * This is needed for windows filter driver, which gets loaded prior to VBoxDrv,
f86f2dc613a22ee06add9b878197922466df641bvboxsync * thus it's not possible to make idc initialization from the driver startup routine for it.
f86f2dc613a22ee06add9b878197922466df641bvboxsync *
f86f2dc613a22ee06add9b878197922466df641bvboxsync * @returns VBox status code.
f86f2dc613a22ee06add9b878197922466df641bvboxsync * @param pGlobals Pointer to the globals. */
f86f2dc613a22ee06add9b878197922466df641bvboxsyncDECLHIDDEN(int) vboxNetAdpInitIdc(PVBOXNETADPGLOBALS pGlobals)
f86f2dc613a22ee06add9b878197922466df641bvboxsync{
f86f2dc613a22ee06add9b878197922466df641bvboxsync int rc;
f86f2dc613a22ee06add9b878197922466df641bvboxsync /*
f86f2dc613a22ee06add9b878197922466df641bvboxsync * Establish a connection to SUPDRV and register our component factory.
f86f2dc613a22ee06add9b878197922466df641bvboxsync */
f86f2dc613a22ee06add9b878197922466df641bvboxsync rc = SUPR0IdcOpen(&pGlobals->SupDrvIDC, 0 /* iReqVersion = default */, 0 /* iMinVersion = default */, NULL, NULL, NULL);
f86f2dc613a22ee06add9b878197922466df641bvboxsync if (RT_SUCCESS(rc))
f86f2dc613a22ee06add9b878197922466df641bvboxsync {
f86f2dc613a22ee06add9b878197922466df641bvboxsync rc = SUPR0IdcComponentRegisterFactory(&pGlobals->SupDrvIDC, &pGlobals->SupDrvFactory);
f86f2dc613a22ee06add9b878197922466df641bvboxsync if (RT_SUCCESS(rc))
f86f2dc613a22ee06add9b878197922466df641bvboxsync {
2a047f0d7ee5964456dbc4dec9925031482588abvboxsync#if 1 /** @todo REMOVE ME! */
8300beb17e7c288655895d07bfdc58a01f618218vboxsync PVBOXNETADP pTmp;
8300beb17e7c288655895d07bfdc58a01f618218vboxsync rc = vboxNetAdpCreate(&pGlobals->TrunkFactory, &pTmp);
8300beb17e7c288655895d07bfdc58a01f618218vboxsync if (RT_FAILURE(rc))
8300beb17e7c288655895d07bfdc58a01f618218vboxsync Log(("Failed to create vboxnet0, rc=%Rrc.\n", rc));
2a047f0d7ee5964456dbc4dec9925031482588abvboxsync#endif
f86f2dc613a22ee06add9b878197922466df641bvboxsync Log(("VBoxNetAdp: pSession=%p\n", SUPR0IdcGetSession(&pGlobals->SupDrvIDC)));
f86f2dc613a22ee06add9b878197922466df641bvboxsync return rc;
f86f2dc613a22ee06add9b878197922466df641bvboxsync }
f86f2dc613a22ee06add9b878197922466df641bvboxsync
f86f2dc613a22ee06add9b878197922466df641bvboxsync /* bail out. */
f86f2dc613a22ee06add9b878197922466df641bvboxsync LogRel(("VBoxNetAdp: Failed to register component factory, rc=%Rrc\n", rc));
f86f2dc613a22ee06add9b878197922466df641bvboxsync SUPR0IdcClose(&pGlobals->SupDrvIDC);
f86f2dc613a22ee06add9b878197922466df641bvboxsync }
f86f2dc613a22ee06add9b878197922466df641bvboxsync
f86f2dc613a22ee06add9b878197922466df641bvboxsync return rc;
f86f2dc613a22ee06add9b878197922466df641bvboxsync}
f86f2dc613a22ee06add9b878197922466df641bvboxsync
f86f2dc613a22ee06add9b878197922466df641bvboxsync/**
f86f2dc613a22ee06add9b878197922466df641bvboxsync * Called by the native driver/kext module initialization routine.
f86f2dc613a22ee06add9b878197922466df641bvboxsync *
f86f2dc613a22ee06add9b878197922466df641bvboxsync * It will initialize the common parts of the globals, assuming the caller
f86f2dc613a22ee06add9b878197922466df641bvboxsync * has already taken care of the OS specific bits.
f86f2dc613a22ee06add9b878197922466df641bvboxsync *
f86f2dc613a22ee06add9b878197922466df641bvboxsync * @returns VBox status code.
f86f2dc613a22ee06add9b878197922466df641bvboxsync * @param pGlobals Pointer to the globals.
f86f2dc613a22ee06add9b878197922466df641bvboxsync */
f86f2dc613a22ee06add9b878197922466df641bvboxsyncDECLHIDDEN(int) vboxNetAdpInitGlobals(PVBOXNETADPGLOBALS pGlobals)
f86f2dc613a22ee06add9b878197922466df641bvboxsync{
f86f2dc613a22ee06add9b878197922466df641bvboxsync /*
f86f2dc613a22ee06add9b878197922466df641bvboxsync * Initialize the common portions of the structure.
f86f2dc613a22ee06add9b878197922466df641bvboxsync */
f86f2dc613a22ee06add9b878197922466df641bvboxsync int rc = vboxNetAdpInitGlobalsBase(pGlobals);
f86f2dc613a22ee06add9b878197922466df641bvboxsync if (RT_SUCCESS(rc))
f86f2dc613a22ee06add9b878197922466df641bvboxsync {
f86f2dc613a22ee06add9b878197922466df641bvboxsync rc = vboxNetAdpInitIdc(pGlobals);
f86f2dc613a22ee06add9b878197922466df641bvboxsync if (RT_SUCCESS(rc))
f86f2dc613a22ee06add9b878197922466df641bvboxsync {
f86f2dc613a22ee06add9b878197922466df641bvboxsync return rc;
f86f2dc613a22ee06add9b878197922466df641bvboxsync }
f86f2dc613a22ee06add9b878197922466df641bvboxsync
f86f2dc613a22ee06add9b878197922466df641bvboxsync /* bail out. */
f86f2dc613a22ee06add9b878197922466df641bvboxsync vboxNetAdpDeleteGlobalsBase(pGlobals);
f86f2dc613a22ee06add9b878197922466df641bvboxsync }
f86f2dc613a22ee06add9b878197922466df641bvboxsync
f86f2dc613a22ee06add9b878197922466df641bvboxsync return rc;
f86f2dc613a22ee06add9b878197922466df641bvboxsync}
2a047f0d7ee5964456dbc4dec9925031482588abvboxsync
6a008ce8150c1391d9e0dda0cdf9485b3c806034vboxsync#else /* !VBOXANETADP_DO_NOT_USE_NETFLT */
6a008ce8150c1391d9e0dda0cdf9485b3c806034vboxsync
6a008ce8150c1391d9e0dda0cdf9485b3c806034vboxsync
6a008ce8150c1391d9e0dda0cdf9485b3c806034vboxsyncVBOXNETADP g_aAdapters[VBOXNETADP_MAX_INSTANCES];
83365ff77c1571f994b3a15bfbdee077d2ea8a07vboxsyncstatic uint8_t g_aUnits[VBOXNETADP_MAX_UNITS/8];
6a008ce8150c1391d9e0dda0cdf9485b3c806034vboxsync
6a008ce8150c1391d9e0dda0cdf9485b3c806034vboxsync
83365ff77c1571f994b3a15bfbdee077d2ea8a07vboxsyncDECLINLINE(int) vboxNetAdpGetUnitByName(const char *pcszName)
83365ff77c1571f994b3a15bfbdee077d2ea8a07vboxsync{
72d7681289c829fb514dcc953c9b07ec4d20a28bvboxsync uint32_t iUnit = RTStrToUInt32(pcszName + sizeof(VBOXNETADP_NAME) - 1);
ca0f503cc033462eb7285e271a06a6e7b8d9e92evboxsync bool fOld;
83365ff77c1571f994b3a15bfbdee077d2ea8a07vboxsync
72d7681289c829fb514dcc953c9b07ec4d20a28bvboxsync if (iUnit >= VBOXNETADP_MAX_UNITS)
83365ff77c1571f994b3a15bfbdee077d2ea8a07vboxsync return -1;
83365ff77c1571f994b3a15bfbdee077d2ea8a07vboxsync
72d7681289c829fb514dcc953c9b07ec4d20a28bvboxsync fOld = ASMAtomicBitTestAndSet(g_aUnits, iUnit);
72d7681289c829fb514dcc953c9b07ec4d20a28bvboxsync return fOld ? -1 : (int)iUnit;
83365ff77c1571f994b3a15bfbdee077d2ea8a07vboxsync}
83365ff77c1571f994b3a15bfbdee077d2ea8a07vboxsync
83365ff77c1571f994b3a15bfbdee077d2ea8a07vboxsyncDECLINLINE(int) vboxNetAdpGetNextAvailableUnit(void)
83365ff77c1571f994b3a15bfbdee077d2ea8a07vboxsync{
ca0f503cc033462eb7285e271a06a6e7b8d9e92evboxsync bool fOld;
72d7681289c829fb514dcc953c9b07ec4d20a28bvboxsync int iUnit;
83365ff77c1571f994b3a15bfbdee077d2ea8a07vboxsync /* There is absolutely no chance that all units are taken */
83365ff77c1571f994b3a15bfbdee077d2ea8a07vboxsync do {
72d7681289c829fb514dcc953c9b07ec4d20a28bvboxsync iUnit = ASMBitFirstClear(g_aUnits, VBOXNETADP_MAX_UNITS);
72d7681289c829fb514dcc953c9b07ec4d20a28bvboxsync if (iUnit < 0)
83365ff77c1571f994b3a15bfbdee077d2ea8a07vboxsync break;
72d7681289c829fb514dcc953c9b07ec4d20a28bvboxsync fOld = ASMAtomicBitTestAndSet(g_aUnits, iUnit);
ca0f503cc033462eb7285e271a06a6e7b8d9e92evboxsync } while (fOld);
83365ff77c1571f994b3a15bfbdee077d2ea8a07vboxsync
72d7681289c829fb514dcc953c9b07ec4d20a28bvboxsync return iUnit;
83365ff77c1571f994b3a15bfbdee077d2ea8a07vboxsync}
83365ff77c1571f994b3a15bfbdee077d2ea8a07vboxsync
72d7681289c829fb514dcc953c9b07ec4d20a28bvboxsyncDECLINLINE(void) vboxNetAdpReleaseUnit(int iUnit)
83365ff77c1571f994b3a15bfbdee077d2ea8a07vboxsync{
279dec545609849069f5f55d9cf74a88d21735eavboxsync bool fSet = ASMAtomicBitTestAndClear(g_aUnits, iUnit);
57a2e9fd8744c4af7450639313f3216787e07ff5vboxsync NOREF(fSet);
279dec545609849069f5f55d9cf74a88d21735eavboxsync Assert(fSet);
83365ff77c1571f994b3a15bfbdee077d2ea8a07vboxsync}
6a008ce8150c1391d9e0dda0cdf9485b3c806034vboxsync
6a008ce8150c1391d9e0dda0cdf9485b3c806034vboxsync/**
6a008ce8150c1391d9e0dda0cdf9485b3c806034vboxsync * Generate a suitable MAC address.
6a008ce8150c1391d9e0dda0cdf9485b3c806034vboxsync *
6a008ce8150c1391d9e0dda0cdf9485b3c806034vboxsync * @param pThis The instance.
6a008ce8150c1391d9e0dda0cdf9485b3c806034vboxsync * @param pMac Where to return the MAC address.
6a008ce8150c1391d9e0dda0cdf9485b3c806034vboxsync */
6a008ce8150c1391d9e0dda0cdf9485b3c806034vboxsyncDECLHIDDEN(void) vboxNetAdpComposeMACAddress(PVBOXNETADP pThis, PRTMAC pMac)
6a008ce8150c1391d9e0dda0cdf9485b3c806034vboxsync{
6a008ce8150c1391d9e0dda0cdf9485b3c806034vboxsync /* Use a locally administered version of the OUI we use for the guest NICs. */
6a008ce8150c1391d9e0dda0cdf9485b3c806034vboxsync pMac->au8[0] = 0x08 | 2;
6a008ce8150c1391d9e0dda0cdf9485b3c806034vboxsync pMac->au8[1] = 0x00;
6a008ce8150c1391d9e0dda0cdf9485b3c806034vboxsync pMac->au8[2] = 0x27;
6a008ce8150c1391d9e0dda0cdf9485b3c806034vboxsync
72d7681289c829fb514dcc953c9b07ec4d20a28bvboxsync pMac->au8[3] = 0; /* pThis->iUnit >> 16; */
72d7681289c829fb514dcc953c9b07ec4d20a28bvboxsync pMac->au8[4] = 0; /* pThis->iUnit >> 8; */
72d7681289c829fb514dcc953c9b07ec4d20a28bvboxsync pMac->au8[5] = pThis->iUnit;
6a008ce8150c1391d9e0dda0cdf9485b3c806034vboxsync}
6a008ce8150c1391d9e0dda0cdf9485b3c806034vboxsync
72d7681289c829fb514dcc953c9b07ec4d20a28bvboxsyncint vboxNetAdpCreate(PVBOXNETADP *ppNew, const char *pcszName)
6a008ce8150c1391d9e0dda0cdf9485b3c806034vboxsync{
6a008ce8150c1391d9e0dda0cdf9485b3c806034vboxsync int rc;
6a008ce8150c1391d9e0dda0cdf9485b3c806034vboxsync unsigned i;
6a008ce8150c1391d9e0dda0cdf9485b3c806034vboxsync for (i = 0; i < RT_ELEMENTS(g_aAdapters); i++)
6a008ce8150c1391d9e0dda0cdf9485b3c806034vboxsync {
6a008ce8150c1391d9e0dda0cdf9485b3c806034vboxsync PVBOXNETADP pThis = &g_aAdapters[i];
6a008ce8150c1391d9e0dda0cdf9485b3c806034vboxsync
6a008ce8150c1391d9e0dda0cdf9485b3c806034vboxsync if (ASMAtomicCmpXchgU32((uint32_t volatile *)&pThis->enmState, kVBoxNetAdpState_Transitional, kVBoxNetAdpState_Invalid))
6a008ce8150c1391d9e0dda0cdf9485b3c806034vboxsync {
6a008ce8150c1391d9e0dda0cdf9485b3c806034vboxsync RTMAC Mac;
6a008ce8150c1391d9e0dda0cdf9485b3c806034vboxsync /* Found an empty slot -- use it. */
6a008ce8150c1391d9e0dda0cdf9485b3c806034vboxsync Log(("vboxNetAdpCreate: found empty slot: %d\n", i));
83365ff77c1571f994b3a15bfbdee077d2ea8a07vboxsync if (pcszName)
83365ff77c1571f994b3a15bfbdee077d2ea8a07vboxsync {
83365ff77c1571f994b3a15bfbdee077d2ea8a07vboxsync Log(("vboxNetAdpCreate: using name: %s\n", pcszName));
72d7681289c829fb514dcc953c9b07ec4d20a28bvboxsync pThis->iUnit = vboxNetAdpGetUnitByName(pcszName);
83365ff77c1571f994b3a15bfbdee077d2ea8a07vboxsync strncpy(pThis->szName, pcszName, sizeof(pThis->szName));
83365ff77c1571f994b3a15bfbdee077d2ea8a07vboxsync pThis->szName[sizeof(pThis->szName) - 1] = '\0';
83365ff77c1571f994b3a15bfbdee077d2ea8a07vboxsync }
83365ff77c1571f994b3a15bfbdee077d2ea8a07vboxsync else
83365ff77c1571f994b3a15bfbdee077d2ea8a07vboxsync {
72d7681289c829fb514dcc953c9b07ec4d20a28bvboxsync pThis->iUnit = vboxNetAdpGetNextAvailableUnit();
83365ff77c1571f994b3a15bfbdee077d2ea8a07vboxsync pThis->szName[0] = '\0';
83365ff77c1571f994b3a15bfbdee077d2ea8a07vboxsync }
72d7681289c829fb514dcc953c9b07ec4d20a28bvboxsync if (pThis->iUnit < 0)
83365ff77c1571f994b3a15bfbdee077d2ea8a07vboxsync rc = VERR_INVALID_PARAMETER;
83365ff77c1571f994b3a15bfbdee077d2ea8a07vboxsync else
83365ff77c1571f994b3a15bfbdee077d2ea8a07vboxsync {
83365ff77c1571f994b3a15bfbdee077d2ea8a07vboxsync vboxNetAdpComposeMACAddress(pThis, &Mac);
83365ff77c1571f994b3a15bfbdee077d2ea8a07vboxsync rc = vboxNetAdpOsCreate(pThis, &Mac);
72d7681289c829fb514dcc953c9b07ec4d20a28bvboxsync Log(("vboxNetAdpCreate: pThis=%p pThis->iUnit=%d, pThis->szName=%s\n",
72d7681289c829fb514dcc953c9b07ec4d20a28bvboxsync pThis, pThis->iUnit, pThis->szName));
83365ff77c1571f994b3a15bfbdee077d2ea8a07vboxsync }
6a008ce8150c1391d9e0dda0cdf9485b3c806034vboxsync if (RT_SUCCESS(rc))
6a008ce8150c1391d9e0dda0cdf9485b3c806034vboxsync {
6a008ce8150c1391d9e0dda0cdf9485b3c806034vboxsync *ppNew = pThis;
6a008ce8150c1391d9e0dda0cdf9485b3c806034vboxsync ASMAtomicWriteU32((uint32_t volatile *)&pThis->enmState, kVBoxNetAdpState_Active);
83365ff77c1571f994b3a15bfbdee077d2ea8a07vboxsync Log2(("VBoxNetAdpCreate: Created %s\n", g_aAdapters[i].szName));
6a008ce8150c1391d9e0dda0cdf9485b3c806034vboxsync }
6a008ce8150c1391d9e0dda0cdf9485b3c806034vboxsync else
6a008ce8150c1391d9e0dda0cdf9485b3c806034vboxsync {
6a008ce8150c1391d9e0dda0cdf9485b3c806034vboxsync ASMAtomicWriteU32((uint32_t volatile *)&pThis->enmState, kVBoxNetAdpState_Invalid);
6a008ce8150c1391d9e0dda0cdf9485b3c806034vboxsync Log(("vboxNetAdpCreate: vboxNetAdpOsCreate failed with '%Rrc'.\n", rc));
6a008ce8150c1391d9e0dda0cdf9485b3c806034vboxsync }
6a008ce8150c1391d9e0dda0cdf9485b3c806034vboxsync for (i = 0; i < RT_ELEMENTS(g_aAdapters); i++)
83365ff77c1571f994b3a15bfbdee077d2ea8a07vboxsync Log2(("VBoxNetAdpCreate: Scanning entry: state=%d unit=%d name=%s\n",
72d7681289c829fb514dcc953c9b07ec4d20a28bvboxsync g_aAdapters[i].enmState, g_aAdapters[i].iUnit, g_aAdapters[i].szName));
6a008ce8150c1391d9e0dda0cdf9485b3c806034vboxsync return rc;
6a008ce8150c1391d9e0dda0cdf9485b3c806034vboxsync }
6a008ce8150c1391d9e0dda0cdf9485b3c806034vboxsync }
6a008ce8150c1391d9e0dda0cdf9485b3c806034vboxsync Log(("vboxNetAdpCreate: no empty slots!\n"));
6a008ce8150c1391d9e0dda0cdf9485b3c806034vboxsync
6a008ce8150c1391d9e0dda0cdf9485b3c806034vboxsync /* All slots in adapter array are busy. */
6a008ce8150c1391d9e0dda0cdf9485b3c806034vboxsync return VERR_OUT_OF_RESOURCES;
6a008ce8150c1391d9e0dda0cdf9485b3c806034vboxsync}
6a008ce8150c1391d9e0dda0cdf9485b3c806034vboxsync
72d7681289c829fb514dcc953c9b07ec4d20a28bvboxsyncint vboxNetAdpDestroy(PVBOXNETADP pThis)
6a008ce8150c1391d9e0dda0cdf9485b3c806034vboxsync{
6a008ce8150c1391d9e0dda0cdf9485b3c806034vboxsync int rc = VINF_SUCCESS;
6a008ce8150c1391d9e0dda0cdf9485b3c806034vboxsync
6a008ce8150c1391d9e0dda0cdf9485b3c806034vboxsync if (!ASMAtomicCmpXchgU32((uint32_t volatile *)&pThis->enmState, kVBoxNetAdpState_Transitional, kVBoxNetAdpState_Active))
6a008ce8150c1391d9e0dda0cdf9485b3c806034vboxsync return VERR_INTNET_FLT_IF_BUSY;
6a008ce8150c1391d9e0dda0cdf9485b3c806034vboxsync
72d7681289c829fb514dcc953c9b07ec4d20a28bvboxsync Assert(pThis->iUnit >= 0 && pThis->iUnit < VBOXNETADP_MAX_UNITS);
6a008ce8150c1391d9e0dda0cdf9485b3c806034vboxsync vboxNetAdpOsDestroy(pThis);
72d7681289c829fb514dcc953c9b07ec4d20a28bvboxsync vboxNetAdpReleaseUnit(pThis->iUnit);
72d7681289c829fb514dcc953c9b07ec4d20a28bvboxsync pThis->iUnit = -1;
83365ff77c1571f994b3a15bfbdee077d2ea8a07vboxsync pThis->szName[0] = '\0';
6a008ce8150c1391d9e0dda0cdf9485b3c806034vboxsync
6a008ce8150c1391d9e0dda0cdf9485b3c806034vboxsync ASMAtomicWriteU32((uint32_t volatile *)&pThis->enmState, kVBoxNetAdpState_Invalid);
6a008ce8150c1391d9e0dda0cdf9485b3c806034vboxsync
6a008ce8150c1391d9e0dda0cdf9485b3c806034vboxsync return rc;
6a008ce8150c1391d9e0dda0cdf9485b3c806034vboxsync}
6a008ce8150c1391d9e0dda0cdf9485b3c806034vboxsync
6a008ce8150c1391d9e0dda0cdf9485b3c806034vboxsyncint vboxNetAdpInit(void)
6a008ce8150c1391d9e0dda0cdf9485b3c806034vboxsync{
6a008ce8150c1391d9e0dda0cdf9485b3c806034vboxsync unsigned i;
6a008ce8150c1391d9e0dda0cdf9485b3c806034vboxsync /*
6a008ce8150c1391d9e0dda0cdf9485b3c806034vboxsync * Init common members and call OS-specific init.
6a008ce8150c1391d9e0dda0cdf9485b3c806034vboxsync */
83365ff77c1571f994b3a15bfbdee077d2ea8a07vboxsync memset(g_aUnits, 0, sizeof(g_aUnits));
83365ff77c1571f994b3a15bfbdee077d2ea8a07vboxsync memset(g_aAdapters, 0, sizeof(g_aAdapters));
599595881adeaefb423b996cf29e21e5831c26d7vboxsync LogFlow(("vboxnetadp: max host-only interfaces supported: %d (%d bytes)\n",
599595881adeaefb423b996cf29e21e5831c26d7vboxsync VBOXNETADP_MAX_INSTANCES, sizeof(g_aAdapters)));
6a008ce8150c1391d9e0dda0cdf9485b3c806034vboxsync for (i = 0; i < RT_ELEMENTS(g_aAdapters); i++)
6a008ce8150c1391d9e0dda0cdf9485b3c806034vboxsync {
6a008ce8150c1391d9e0dda0cdf9485b3c806034vboxsync g_aAdapters[i].enmState = kVBoxNetAdpState_Invalid;
72d7681289c829fb514dcc953c9b07ec4d20a28bvboxsync g_aAdapters[i].iUnit = -1;
6a008ce8150c1391d9e0dda0cdf9485b3c806034vboxsync vboxNetAdpOsInit(&g_aAdapters[i]);
6a008ce8150c1391d9e0dda0cdf9485b3c806034vboxsync }
6a008ce8150c1391d9e0dda0cdf9485b3c806034vboxsync
1c19381e9455f78f30a14a20d19f1dab7da19334vboxsync return VINF_SUCCESS;
6a008ce8150c1391d9e0dda0cdf9485b3c806034vboxsync}
6a008ce8150c1391d9e0dda0cdf9485b3c806034vboxsync
6a008ce8150c1391d9e0dda0cdf9485b3c806034vboxsync/**
6a008ce8150c1391d9e0dda0cdf9485b3c806034vboxsync * Finds an adapter by its name.
6a008ce8150c1391d9e0dda0cdf9485b3c806034vboxsync *
6a008ce8150c1391d9e0dda0cdf9485b3c806034vboxsync * @returns Pointer to the instance by the given name. NULL if not found.
6a008ce8150c1391d9e0dda0cdf9485b3c806034vboxsync * @param pGlobals The globals.
6a008ce8150c1391d9e0dda0cdf9485b3c806034vboxsync * @param pszName The name of the instance.
6a008ce8150c1391d9e0dda0cdf9485b3c806034vboxsync */
6a008ce8150c1391d9e0dda0cdf9485b3c806034vboxsyncPVBOXNETADP vboxNetAdpFindByName(const char *pszName)
6a008ce8150c1391d9e0dda0cdf9485b3c806034vboxsync{
6a008ce8150c1391d9e0dda0cdf9485b3c806034vboxsync unsigned i;
6a008ce8150c1391d9e0dda0cdf9485b3c806034vboxsync
6a008ce8150c1391d9e0dda0cdf9485b3c806034vboxsync for (i = 0; i < RT_ELEMENTS(g_aAdapters); i++)
6a008ce8150c1391d9e0dda0cdf9485b3c806034vboxsync {
6a008ce8150c1391d9e0dda0cdf9485b3c806034vboxsync PVBOXNETADP pThis = &g_aAdapters[i];
6a008ce8150c1391d9e0dda0cdf9485b3c806034vboxsync Log2(("VBoxNetAdp: Scanning entry: state=%d name=%s\n", pThis->enmState, pThis->szName));
62bce8f445bcb26dca9a6967cd22a1ba12af3e4cvboxsync if ( strcmp(pThis->szName, pszName) == 0
62bce8f445bcb26dca9a6967cd22a1ba12af3e4cvboxsync && ASMAtomicReadU32((uint32_t volatile *)&pThis->enmState) == kVBoxNetAdpState_Active)
62bce8f445bcb26dca9a6967cd22a1ba12af3e4cvboxsync return pThis;
6a008ce8150c1391d9e0dda0cdf9485b3c806034vboxsync }
6a008ce8150c1391d9e0dda0cdf9485b3c806034vboxsync return NULL;
6a008ce8150c1391d9e0dda0cdf9485b3c806034vboxsync}
6a008ce8150c1391d9e0dda0cdf9485b3c806034vboxsync
6a008ce8150c1391d9e0dda0cdf9485b3c806034vboxsyncvoid vboxNetAdpShutdown(void)
6a008ce8150c1391d9e0dda0cdf9485b3c806034vboxsync{
6a008ce8150c1391d9e0dda0cdf9485b3c806034vboxsync unsigned i;
6a008ce8150c1391d9e0dda0cdf9485b3c806034vboxsync
6a008ce8150c1391d9e0dda0cdf9485b3c806034vboxsync /* Remove virtual adapters */
6a008ce8150c1391d9e0dda0cdf9485b3c806034vboxsync for (i = 0; i < RT_ELEMENTS(g_aAdapters); i++)
6a008ce8150c1391d9e0dda0cdf9485b3c806034vboxsync vboxNetAdpDestroy(&g_aAdapters[i]);
6a008ce8150c1391d9e0dda0cdf9485b3c806034vboxsync}
6a008ce8150c1391d9e0dda0cdf9485b3c806034vboxsync#endif /* !VBOXANETADP_DO_NOT_USE_NETFLT */