/** @file * INETNET - Internal Networking. (DEV,++) */ /* * Copyright (C) 2006-2007 Sun Microsystems, Inc. * * This file is part of VirtualBox Open Source Edition (OSE), as * available from http://www.virtualbox.org. This file is free software; * you can redistribute it and/or modify it under the terms of the GNU * General Public License (GPL) as published by the Free Software * Foundation, in version 2 as it comes in the "COPYING" file of the * VirtualBox OSE distribution. VirtualBox OSE is distributed in the * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind. * * The contents of this file may alternatively be used under the terms * of the Common Development and Distribution License Version 1.0 * (CDDL) only, as it comes in the "COPYING.CDDL" file of the * VirtualBox OSE distribution, in which case the provisions of the * CDDL are applicable instead of those of the GPL. * * You may elect to license modified versions of this file under the * terms and conditions of either the GPL or the CDDL or both. * * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa * Clara, CA 95054 USA or visit http://www.sun.com if you need * additional information or have any questions. */ #ifndef ___VBox_intnet_h #define ___VBox_intnet_h #include #include #include #include #include RT_C_DECLS_BEGIN /** Pointer to an internal network ring-0 instance. */ typedef struct INTNET *PINTNET; /** * Generic two-sided ring buffer. * * The deal is that there is exactly one writer and one reader. * When offRead equals offWrite the buffer is empty. In the other * extreme the writer will not use the last free byte in the buffer. */ typedef struct INTNETRINGBUF { /** The start of the buffer offset relative to the. (inclusive) */ uint32_t offStart; /** The offset to the end of the buffer. (exclusive) */ uint32_t offEnd; /** The current read offset. */ uint32_t volatile offRead; /** The current write offset. */ uint32_t volatile offWrite; } INTNETRINGBUF; /** Pointer to a ring buffer. */ typedef INTNETRINGBUF *PINTNETRINGBUF; /** * Get the amount of space available for writing. * * @returns Number of available bytes. * @param pRingBuf The ring buffer. */ DECLINLINE(uint32_t) INTNETRingGetWritable(PINTNETRINGBUF pRingBuf) { return pRingBuf->offRead <= pRingBuf->offWrite ? pRingBuf->offEnd - pRingBuf->offWrite + pRingBuf->offRead - pRingBuf->offStart - 1 : pRingBuf->offRead - pRingBuf->offWrite - 1; } /** * Get the amount of data ready for reading. * * @returns Number of ready bytes. * @param pRingBuf The ring buffer. */ DECLINLINE(uint32_t) INTNETRingGetReadable(PINTNETRINGBUF pRingBuf) { return pRingBuf->offRead <= pRingBuf->offWrite ? pRingBuf->offWrite - pRingBuf->offRead : pRingBuf->offEnd - pRingBuf->offRead + pRingBuf->offWrite - pRingBuf->offStart; } /** * A interface buffer. */ typedef struct INTNETBUF { /** The size of the entire buffer. */ uint32_t cbBuf; /** The size of the send area. */ uint32_t cbSend; /** The size of the receive area. */ uint32_t cbRecv; /** Alignment. */ uint32_t u32Align; /** The receive buffer. */ INTNETRINGBUF Recv; /** The send buffer. */ INTNETRINGBUF Send; /** Number of times yields help solve an overflow. */ STAMCOUNTER cStatYieldsOk; /** Number of times yields didn't help solve an overflow. */ STAMCOUNTER cStatYieldsNok; /** Number of lost packets due to overflows. */ STAMCOUNTER cStatLost; /** Number of packets received (not counting lost ones). */ STAMCOUNTER cStatRecvs; /** Number of frame bytes received (not couting lost frames). */ STAMCOUNTER cbStatRecv; /** Number of packets received. */ STAMCOUNTER cStatSends; /** Number of frame bytes sent. */ STAMCOUNTER cbStatSend; } INTNETBUF; /** Pointer to an interface buffer. */ typedef INTNETBUF *PINTNETBUF; /** Pointer to a const interface buffer. */ typedef INTNETBUF const *PCINTNETBUF; /** Internal networking interface handle. */ typedef uint32_t INTNETIFHANDLE; /** Pointer to an internal networking interface handle. */ typedef INTNETIFHANDLE *PINTNETIFHANDLE; /** Or mask to obscure the handle index. */ #define INTNET_HANDLE_MAGIC 0x88880000 /** Mask to extract the handle index. */ #define INTNET_HANDLE_INDEX_MASK 0xffff /** The maximum number of handles (exclusive) */ #define INTNET_HANDLE_MAX 0xffff /** Invalid handle. */ #define INTNET_HANDLE_INVALID (0) /** * The packet header. * * The header is intentionally 8 bytes long. It will always * start at an 8 byte aligned address. Assuming that the buffer * size is a multiple of 8 bytes, that means that we can guarantee * that the entire header is contiguous in both virtual and physical * memory. */ #pragma pack(1) typedef struct INTNETHDR { /** Header type. This is currently serving as a magic, it * can be extended later to encode special command packets and stuff. */ uint16_t u16Type; /** The size of the frame. */ uint16_t cbFrame; /** The offset from the start of this header to where the actual frame starts. * This is used to keep the frame it self continguous in virtual memory and * thereby both simplify reading and */ int32_t offFrame; } INTNETHDR; #pragma pack() /** Pointer to a packet header.*/ typedef INTNETHDR *PINTNETHDR; /** Pointer to a const packet header.*/ typedef INTNETHDR const *PCINTNETHDR; /** INTNETHDR::u16Type value for normal frames. */ #define INTNETHDR_TYPE_FRAME 0x2442 /** * Calculates the pointer to the frame. * * @returns Pointer to the start of the frame. * @param pHdr Pointer to the packet header * @param pBuf The buffer the header is within. Only used in strict builds. */ DECLINLINE(void *) INTNETHdrGetFramePtr(PCINTNETHDR pHdr, PCINTNETBUF pBuf) { uint8_t *pu8 = (uint8_t *)pHdr + pHdr->offFrame; #ifdef VBOX_STRICT const uintptr_t off = (uintptr_t)pu8 - (uintptr_t)pBuf; Assert(pHdr->u16Type == INTNETHDR_TYPE_FRAME); Assert(off < pBuf->cbBuf); Assert(off + pHdr->cbFrame <= pBuf->cbBuf); #endif NOREF(pBuf); return pu8; } /** * Skips to the next (read) frame in the buffer. * * @param pBuf The buffer. * @param pRingBuf The ring buffer in question. */ DECLINLINE(void) INTNETRingSkipFrame(PINTNETBUF pBuf, PINTNETRINGBUF pRingBuf) { uint32_t offRead = pRingBuf->offRead; PINTNETHDR pHdr = (PINTNETHDR)((uint8_t *)pBuf + offRead); Assert(pRingBuf->offRead < pBuf->cbBuf); Assert(pRingBuf->offRead >= pRingBuf->offStart); Assert(pRingBuf->offRead < pRingBuf->offEnd); /* skip the frame */ offRead += pHdr->offFrame + pHdr->cbFrame; offRead = RT_ALIGN_32(offRead, sizeof(INTNETHDR)); Assert(offRead <= pRingBuf->offEnd && offRead >= pRingBuf->offStart); if (offRead >= pRingBuf->offEnd) offRead = pRingBuf->offStart; ASMAtomicXchgU32(&pRingBuf->offRead, offRead); } /** * Scatter / Gather segment (internal networking). */ typedef struct INTNETSEG { /** The physical address. NIL_RTHCPHYS is not set. */ RTHCPHYS Phys; /** Pointer to the segment data. */ void *pv; /** The segment size. */ uint32_t cb; } INTNETSEG; /** Pointer to a internal networking packet segment. */ typedef INTNETSEG *PINTNETSEG; /** Pointer to a internal networking packet segment. */ typedef INTNETSEG const *PCINTNETSEG; /** * Scatter / Gather list (internal networking). * * This is used when communicating with the trunk port. */ typedef struct INTNETSG { /** Owner data, don't touch! */ void *pvOwnerData; /** User data. */ void *pvUserData; /** User data 2 in case anyone needs it. */ void *pvUserData2; /** The total length of the scatter gather list. */ uint32_t cbTotal; /** The number of users (references). * This is used by the SGRelease code to decide when it can be freed. */ uint16_t volatile cUsers; /** Flags, see INTNETSG_FLAGS_* */ uint16_t volatile fFlags; /** The number of segments allocated. */ uint16_t cSegsAlloc; /** The number of segments actually used. */ uint16_t cSegsUsed; /** Variable sized list of segments. */ INTNETSEG aSegs[1]; } INTNETSG; /** Pointer to a scatter / gather list. */ typedef INTNETSG *PINTNETSG; /** Pointer to a const scatter / gather list. */ typedef INTNETSG const *PCINTNETSG; /** @name INTNETSG::fFlags definitions. * @{ */ /** Set if the SG is free. */ #define INTNETSG_FLAGS_FREE RT_BIT_32(1) /** Set if the SG is a temporary one that will become invalid upon return. * Try to finish using it before returning, and if that's not possible copy * to other buffers. * When not set, the callee should always free the SG. * Attempts to free it made by the callee will be quietly ignored. */ #define INTNETSG_FLAGS_TEMP RT_BIT_32(2) /** ARP packet, IPv4 + MAC. * @internal */ #define INTNETSG_FLAGS_ARP_IPV4 RT_BIT_32(3) /** Copied to the temporary buffer. * @internal */ #define INTNETSG_FLAGS_PKT_CP_IN_TMP RT_BIT_32(4) /** @} */ /** @name Direction (packet source or destination) * @{ */ /** To/From the wire. */ #define INTNETTRUNKDIR_WIRE RT_BIT_32(0) /** To/From the host. */ #define INTNETTRUNKDIR_HOST RT_BIT_32(1) /** Mask of valid bits. */ #define INTNETTRUNKDIR_VALID_MASK UINT32_C(3) /** @} */ /** Pointer to the switch side of a trunk port. */ typedef struct INTNETTRUNKSWPORT *PINTNETTRUNKSWPORT; /** * This is the port on the internal network 'switch', i.e. * what the driver is connected to. * * This is only used for the in-kernel trunk connections. */ typedef struct INTNETTRUNKSWPORT { /** Structure version number. (INTNETTRUNKSWPORT_VERSION) */ uint32_t u32Version; /** * Selects whether outgoing SGs should have their physical address set. * * By enabling physical addresses in the scatter / gather segments it should * be possible to save some unnecessary address translation and memory locking * in the network stack. (Internal networking knows the physical address for * all the INTNETBUF data and that it's locked memory.) There is a negative * side effects though, frames that crosses page boundraries will require * multiple scather / gather segments. * * @returns The old setting. * * @param pSwitchPort Pointer to this structure. * @param fEnable Whether to enable or disable it. * * @remarks Will grab the network semaphore. */ DECLR0CALLBACKMEMBER(bool, pfnSetSGPhys,(PINTNETTRUNKSWPORT pSwitchPort, bool fEnable)); /** * Incoming frame. * * The frame may be modified when the trunk port on the switch is set to share * the mac address of the host when hitting the wire. Currently rames containing * ARP packets are subject to this, later other protocols like NDP/ICMPv6 may * need editing as well when operating in this mode. * * @returns true if we've handled it and it should be dropped. * false if it should hit the wire. * * @param pSwitchPort Pointer to this structure. * @param pSG The (scatter /) gather structure for the frame. * This will only be use during the call, so a temporary one can * be used. The Phys member will not be used. * @param fSrc Where this frame comes from. Only one bit should be set! * * @remarks Will grab the network semaphore. * * @remarks NAT and TAP will use this interface. * * @todo Do any of the host require notification before frame modifications? If so, * we'll add a callback to INTNETTRUNKIFPORT for this (pfnSGModifying) and * a SG flag. */ DECLR0CALLBACKMEMBER(bool, pfnRecv,(PINTNETTRUNKSWPORT pSwitchPort, PINTNETSG pSG, uint32_t fSrc)); /** * Retain a SG. * * @param pSwitchPort Pointer to this structure. * @param pSG Pointer to the (scatter /) gather structure. * * @remarks Will not grab any locks. */ DECLR0CALLBACKMEMBER(void, pfnSGRetain,(PINTNETTRUNKSWPORT pSwitchPort, PINTNETSG pSG)); /** * Release a SG. * * This is called by the pfnXmit code when done with a SG. This may safe * be done in an asynchronous manner. * * @param pSwitchPort Pointer to this structure. * @param pSG Pointer to the (scatter /) gather structure. * * @remarks Will grab the network semaphore. */ DECLR0CALLBACKMEMBER(void, pfnSGRelease,(PINTNETTRUNKSWPORT pSwitchPort, PINTNETSG pSG)); /** Structure version number. (INTNETTRUNKSWPORT_VERSION) */ uint32_t u32VersionEnd; } INTNETTRUNKSWPORT; /** Version number for the INTNETTRUNKIFPORT::u32Version and INTNETTRUNKIFPORT::u32VersionEnd fields. */ #define INTNETTRUNKSWPORT_VERSION UINT32_C(0xA2CDf001) /** Pointer to the interface side of a trunk port. */ typedef struct INTNETTRUNKIFPORT *PINTNETTRUNKIFPORT; /** * This is the port on the trunk interface, i.e. the driver * side which the internal network is connected to. * * This is only used for the in-kernel trunk connections. * * @remarks The internal network side is responsible for serializing all calls * to this interface. This is (assumed) to be implemented using a lock * that is only ever taken before a call to this interface. The lock * is referred to as the out-bound trunk port lock. */ typedef struct INTNETTRUNKIFPORT { /** Structure version number. (INTNETTRUNKIFPORT_VERSION) */ uint32_t u32Version; /** * Retain the object. * * It will normally be called while owning the internal network semaphore. * * @param pIfPort Pointer to this structure. * * @remarks The caller may own any locks or none at all, we don't care. */ DECLR0CALLBACKMEMBER(void, pfnRetain,(PINTNETTRUNKIFPORT pIfPort)); /** * Releases the object. * * This must be called for every pfnRetain call. * * * @param pIfPort Pointer to this structure. * * @remarks Only the out-bound trunk port lock, unless the caller is certain the * call is not going to cause destruction (wont happen). */ DECLR0CALLBACKMEMBER(void, pfnRelease,(PINTNETTRUNKIFPORT pIfPort)); /** * Disconnect from the switch and release the object. * * The is the counter action of the * INTNETTRUNKNETFLTFACTORY::pfnCreateAndConnect method. * * @param pIfPort Pointer to this structure. * * @remarks Called holding the out-bound trunk port lock. */ DECLR0CALLBACKMEMBER(void, pfnDisconnectAndRelease,(PINTNETTRUNKIFPORT pIfPort)); /** * Changes the active state of the interface. * * The interface is created in the suspended (non-active) state and then activated * when the VM/network is started. It may be suspended and re-activated later * for various reasons. It will finally be suspended again before disconnecting * the interface from the internal network, however, this might be done immediately * before disconnecting and may leave an incoming frame waiting on the internal network * semaphore. So, after the final suspend a pfnWaitForIdle is always called to make sure * the interface is idle before pfnDisconnectAndRelease is called. * * A typical operation to performed by this method is to enable/disable promiscuous * mode on the host network interface. (This is the reason we cannot call this when * owning any semaphores.) * * @returns The previous state. * * @param pIfPort Pointer to this structure. * @param fActive True if the new state is 'active', false if the new state is 'suspended'. * * @remarks Called holding the out-bound trunk port lock. */ DECLR0CALLBACKMEMBER(bool, pfnSetActive,(PINTNETTRUNKIFPORT pIfPort, bool fActive)); /** * Waits for the interface to become idle. * * This method must be called before disconnecting and releasing the * object in order to prevent racing incoming/outgoing packets and * device enabling/disabling. * * @returns IPRT status code (see RTSemEventWait). * @param pIfPort Pointer to this structure. * @param cMillies The number of milliseconds to wait. 0 means * no waiting at all. Use RT_INDEFINITE_WAIT for * an indefinite wait. * * @remarks Called holding the out-bound trunk port lock. */ DECLR0CALLBACKMEMBER(int, pfnWaitForIdle,(PINTNETTRUNKIFPORT pIfPort, uint32_t cMillies)); /** * Gets the MAC address of the host network interface that we're attached to. * * @param pIfPort Pointer to this structure. * @param pMac Where to store the host MAC address. * * @remarks Called while owning the network and the out-bound trunk port semaphores. */ DECLR0CALLBACKMEMBER(void, pfnGetMacAddress,(PINTNETTRUNKIFPORT pIfPort, PRTMAC pMac)); /** * Tests if the mac address belongs to any of the host NICs * and should take the host route. * * @returns true / false. * * @param pIfPort Pointer to this structure. * @param pMac Pointer to the mac address. * * @remarks Called while owning the network and the out-bound trunk port semaphores. * * @remarks TAP and NAT will compare with their own MAC address and let all their * traffic take the host direction. * * @remarks This didn't quiet work out the way it should... perhaps obsolete this * with pfnGetHostMac? */ DECLR0CALLBACKMEMBER(bool, pfnIsHostMac,(PINTNETTRUNKIFPORT pIfPort, PCRTMAC pMac)); /** * Tests whether the host is operating the interface is promiscuous mode. * * The default behavior of the internal networking 'switch' is to 'autodetect' * promiscuous mode on the trunk port, which is when this method is used. * For security reasons this default may of course be overridden so that the * host cannot sniff at what's going on. * * Note that this differs from operating the trunk port on the switch in * 'promiscuous' mode, because that relates to the bits going to the wire. * * @returns true / false. * * @param pIfPort Pointer to this structure. * * @remarks Called while owning the network and the out-bound trunk port semaphores. */ DECLR0CALLBACKMEMBER(bool, pfnIsPromiscuous,(PINTNETTRUNKIFPORT pIfPort)); /** * Transmit a frame. * * @return VBox status code. Error generally means we'll drop the packet. * @param pIfPort Pointer to this structure. * @param pSG Pointer to the (scatter /) gather structure for the frame. * This may or may not be a temporary buffer. If it's temporary * the transmit operation(s) then it's required to make a copy * of the frame unless it can be transmitted synchronously. * @param fDst The destination mask. At least one bit will be set. * * @remarks Called holding the out-bound trunk port lock. * * @remarks TAP and NAT will use this interface for all their traffic, see pfnIsHostMac. * * @todo */ DECLR0CALLBACKMEMBER(int, pfnXmit,(PINTNETTRUNKIFPORT pIfPort, PINTNETSG pSG, uint32_t fDst)); /** Structure version number. (INTNETTRUNKIFPORT_VERSION) */ uint32_t u32VersionEnd; } INTNETTRUNKIFPORT; /** Version number for the INTNETTRUNKIFPORT::u32Version and INTNETTRUNKIFPORT::u32VersionEnd fields. */ #define INTNETTRUNKIFPORT_VERSION UINT32_C(0xA2CDe001) /** * The component factory interface for create a network * interface filter (like VBoxNetFlt). */ typedef struct INTNETTRUNKFACTORY { /** * Release this factory. * * SUPR0ComponentQueryFactory (SUPDRVFACTORY::pfnQueryFactoryInterface to be precise) * will retain a reference to the factory and the caller has to call this method to * release it once the pfnCreateAndConnect call(s) has been done. * * @param pIfFactory Pointer to this structure. */ DECLR0CALLBACKMEMBER(void, pfnRelease,(struct INTNETTRUNKFACTORY *pIfFactory)); /** * Create an instance for the specfied host interface and connects it * to the internal network trunk port. * * The initial interface active state is false (suspended). * * * @returns VBox status code. * @retval VINF_SUCCESS and *ppIfPort set on success. * @retval VERR_INTNET_FLT_IF_NOT_FOUND if the interface was not found. * @retval VERR_INTNET_FLT_IF_BUSY if the interface is already connected. * @retval VERR_INTNET_FLT_IF_FAILED if it failed for some other reason. * * @param pIfFactory Pointer to this structure. * @param pszName The interface name (OS specific). * @param pSwitchPort Pointer to the port interface on the switch that * this interface is being connected to. * @param fFlags Creation flags, see below. * @param ppIfPort Where to store the pointer to the interface port * on success. * * @remarks Called while owning the network and the out-bound trunk semaphores. */ DECLR0CALLBACKMEMBER(int, pfnCreateAndConnect,(struct INTNETTRUNKFACTORY *pIfFactory, const char *pszName, PINTNETTRUNKSWPORT pSwitchPort, uint32_t fFlags, PINTNETTRUNKIFPORT *ppIfPort)); } INTNETTRUNKFACTORY; /** Pointer to the trunk factory. */ typedef INTNETTRUNKFACTORY *PINTNETTRUNKFACTORY; /** The UUID for the (current) trunk factory. (case sensitive) */ #define INTNETTRUNKFACTORY_UUID_STR "449a2799-7564-464d-b4b2-7a877418fd0c" /** @name INTNETTRUNKFACTORY::pfnCreateAndConnect flags. * @{ */ /** Don't put the filtered interface in promiscuous mode. * This is used for wireless interface since these can misbehave if * we try to put them in promiscuous mode. (Wireless interfaces are * normally bridged on level 3 instead of level 2.) */ #define INTNETTRUNKFACTORY_FLAG_NO_PROMISC RT_BIT_32(0) /** @} */ /** * The trunk connection type. * * Used by INTNETR0Open and assoicated interfaces. */ typedef enum INTNETTRUNKTYPE { /** Invalid trunk type. */ kIntNetTrunkType_Invalid = 0, /** No trunk connection. */ kIntNetTrunkType_None, /** We don't care which kind of trunk connection if the network exists, * if it doesn't exist create it without a connection. */ kIntNetTrunkType_WhateverNone, /** VirtualBox host network interface filter driver. * The trunk name is the name of the host network interface. */ kIntNetTrunkType_NetFlt, /** VirtualBox adapter host driver. */ kIntNetTrunkType_NetAdp, /** Nat service (ring-0). */ kIntNetTrunkType_SrvNat, /** The end of valid types. */ kIntNetTrunkType_End, /** The usual 32-bit hack. */ kIntNetTrunkType_32bitHack = 0x7fffffff } INTNETTRUNKTYPE; /** @name INTNETR0Open flags. * @{ */ /** Share the MAC address with the host when sending something to the wire via the trunk. * This is typically used when the trunk is a NetFlt for a wireless interface. */ #define INTNET_OPEN_FLAGS_SHARED_MAC_ON_WIRE RT_BIT_32(0) /** Whether new participants should be subjected to access check or not. */ #define INTNET_OPEN_FLAGS_PUBLIC RT_BIT_32(1) /** Ignore any requests for promiscuous mode. */ #define INTNET_OPEN_FLAGS_IGNORE_PROMISC RT_BIT_32(2) /** Ignore any requests for promiscuous mode, quietly applied/ignored on open. */ #define INTNET_OPEN_FLAGS_QUIETLY_IGNORE_PROMISC RT_BIT_32(3) /** Ignore any requests for promiscuous mode on the trunk wire connection. */ #define INTNET_OPEN_FLAGS_IGNORE_PROMISC_TRUNK_WIRE RT_BIT_32(4) /** Ignore any requests for promiscuous mode on the trunk wire connection, quietly applied/ignored on open. */ #define INTNET_OPEN_FLAGS_QUIETLY_IGNORE_PROMISC_TRUNK_WIRE RT_BIT_32(5) /** Ignore any requests for promiscuous mode on the trunk host connection. */ #define INTNET_OPEN_FLAGS_IGNORE_PROMISC_TRUNK_HOST RT_BIT_32(6) /** Ignore any requests for promiscuous mode on the trunk host connection, quietly applied/ignored on open. */ #define INTNET_OPEN_FLAGS_QUIETLY_IGNORE_PROMISC_TRUNK_HOST RT_BIT_32(7) /** The mask of flags which causes flag incompatibilities. */ #define INTNET_OPEN_FLAGS_COMPATIBILITY_XOR_MASK (RT_BIT_32(0) | RT_BIT_32(1) | RT_BIT_32(2) | RT_BIT_32(4) | RT_BIT_32(6)) /** The mask of flags is always ORed in, even on open. (the quiet stuff) */ #define INTNET_OPEN_FLAGS_SECURITY_OR_MASK (RT_BIT_32(3) | RT_BIT_32(5) | RT_BIT_32(7)) /** The mask of valid flags. */ #define INTNET_OPEN_FLAGS_MASK UINT32_C(0x000000ff) /** @} */ /** The maximum length of a network name. */ #define INTNET_MAX_NETWORK_NAME 128 /** The maximum length of a trunk name. */ #define INTNET_MAX_TRUNK_NAME 64 /** * Request buffer for INTNETR0OpenReq / VMMR0_DO_INTNET_OPEN. * @see INTNETR0Open. */ typedef struct INTNETOPENREQ { /** The request header. */ SUPVMMR0REQHDR Hdr; /** Alternative to passing the taking the session from the VM handle. * Either use this member or use the VM handle, don't do both. */ PSUPDRVSESSION pSession; /** The network name. (input) */ char szNetwork[INTNET_MAX_NETWORK_NAME]; /** What to connect to the trunk port. (input) * This is specific to the trunk type below. */ char szTrunk[INTNET_MAX_TRUNK_NAME]; /** The type of trunk link (NAT, Filter, TAP, etc). (input) */ INTNETTRUNKTYPE enmTrunkType; /** Flags, see INTNET_OPEN_FLAGS_*. (input) */ uint32_t fFlags; /** The size of the send buffer. (input) */ uint32_t cbSend; /** The size of the receive buffer. (input) */ uint32_t cbRecv; /** The handle to the network interface. (output) */ INTNETIFHANDLE hIf; } INTNETOPENREQ; /** Pointer to an INTNETR0OpenReq / VMMR0_DO_INTNET_OPEN request buffer. */ typedef INTNETOPENREQ *PINTNETOPENREQ; INTNETR0DECL(int) INTNETR0OpenReq(PINTNET pIntNet, PSUPDRVSESSION pSession, PINTNETOPENREQ pReq); /** * Request buffer for INTNETR0IfCloseReq / VMMR0_DO_INTNET_IF_CLOSE. * @see INTNETR0IfClose. */ typedef struct INTNETIFCLOSEREQ { /** The request header. */ SUPVMMR0REQHDR Hdr; /** Alternative to passing the taking the session from the VM handle. * Either use this member or use the VM handle, don't do both. */ PSUPDRVSESSION pSession; /** The handle to the network interface. */ INTNETIFHANDLE hIf; } INTNETIFCLOSEREQ; /** Pointer to an INTNETR0IfCloseReq / VMMR0_DO_INTNET_IF_CLOSE request buffer. */ typedef INTNETIFCLOSEREQ *PINTNETIFCLOSEREQ; INTNETR0DECL(int) INTNETR0IfCloseReq(PINTNET pIntNet, PSUPDRVSESSION pSession, PINTNETIFCLOSEREQ pReq); /** * Request buffer for INTNETR0IfGetRing3BufferReq / VMMR0_DO_INTNET_IF_GET_RING3_BUFFER. * @see INTNETR0IfGetRing3Buffer. */ typedef struct INTNETIFGETRING3BUFFERREQ { /** The request header. */ SUPVMMR0REQHDR Hdr; /** Alternative to passing the taking the session from the VM handle. * Either use this member or use the VM handle, don't do both. */ PSUPDRVSESSION pSession; /** Handle to the interface. */ INTNETIFHANDLE hIf; /** The pointer to the ring3 buffer. (output) */ R3PTRTYPE(PINTNETBUF) pRing3Buf; } INTNETIFGETRING3BUFFERREQ; /** Pointer to an INTNETR0IfGetRing3BufferReq / VMMR0_DO_INTNET_IF_GET_RING3_BUFFER request buffer. */ typedef INTNETIFGETRING3BUFFERREQ *PINTNETIFGETRING3BUFFERREQ; INTNETR0DECL(int) INTNETR0IfGetRing3BufferReq(PINTNET pIntNet, PSUPDRVSESSION pSession, PINTNETIFGETRING3BUFFERREQ pReq); /** * Request buffer for INTNETR0IfSetPromiscuousModeReq / VMMR0_DO_INTNET_IF_SET_PROMISCUOUS_MODE. * @see INTNETR0IfSetPromiscuousMode. */ typedef struct INTNETIFSETPROMISCUOUSMODEREQ { /** The request header. */ SUPVMMR0REQHDR Hdr; /** Alternative to passing the taking the session from the VM handle. * Either use this member or use the VM handle, don't do both. */ PSUPDRVSESSION pSession; /** Handle to the interface. */ INTNETIFHANDLE hIf; /** The new promiscuous mode. */ bool fPromiscuous; } INTNETIFSETPROMISCUOUSMODEREQ; /** Pointer to an INTNETR0IfSetPromiscuousModeReq / VMMR0_DO_INTNET_IF_SET_PROMISCUOUS_MODE request buffer. */ typedef INTNETIFSETPROMISCUOUSMODEREQ *PINTNETIFSETPROMISCUOUSMODEREQ; INTNETR0DECL(int) INTNETR0IfSetPromiscuousModeReq(PINTNET pIntNet, PSUPDRVSESSION pSession, PINTNETIFSETPROMISCUOUSMODEREQ pReq); /** * Request buffer for INTNETR0IfSetMacAddressReq / VMMR0_DO_INTNET_IF_SET_MAC_ADDRESS. * @see INTNETR0IfSetMacAddress. */ typedef struct INTNETIFSETMACADDRESSREQ { /** The request header. */ SUPVMMR0REQHDR Hdr; /** Alternative to passing the taking the session from the VM handle. * Either use this member or use the VM handle, don't do both. */ PSUPDRVSESSION pSession; /** Handle to the interface. */ INTNETIFHANDLE hIf; /** The new MAC address. */ RTMAC Mac; } INTNETIFSETMACADDRESSREQ; /** Pointer to an INTNETR0IfSetMacAddressReq / VMMR0_DO_INTNET_IF_SET_MAC_ADDRESS request buffer. */ typedef INTNETIFSETMACADDRESSREQ *PINTNETIFSETMACADDRESSREQ; INTNETR0DECL(int) INTNETR0IfSetMacAddressReq(PINTNET pIntNet, PSUPDRVSESSION pSession, PINTNETIFSETMACADDRESSREQ pReq); /** * Request buffer for INTNETR0IfSetActiveReq / VMMR0_DO_INTNET_IF_SET_ACTIVE. * @see INTNETR0IfSetActive. */ typedef struct INTNETIFSETACTIVEREQ { /** The request header. */ SUPVMMR0REQHDR Hdr; /** Alternative to passing the taking the session from the VM handle. * Either use this member or use the VM handle, don't do both. */ PSUPDRVSESSION pSession; /** Handle to the interface. */ INTNETIFHANDLE hIf; /** The new state. */ bool fActive; } INTNETIFSETACTIVEREQ; /** Pointer to an INTNETR0IfSetActiveReq / VMMR0_DO_INTNET_IF_SET_ACTIVE request buffer. */ typedef INTNETIFSETACTIVEREQ *PINTNETIFSETACTIVEREQ; INTNETR0DECL(int) INTNETR0IfSetActiveReq(PINTNET pIntNet, PSUPDRVSESSION pSession, PINTNETIFSETACTIVEREQ pReq); /** * Request buffer for INTNETR0IfSendReq / VMMR0_DO_INTNET_IF_SEND. * @see INTNETR0IfSend. */ typedef struct INTNETIFSENDREQ { /** The request header. */ SUPVMMR0REQHDR Hdr; /** Alternative to passing the taking the session from the VM handle. * Either use this member or use the VM handle, don't do both. */ PSUPDRVSESSION pSession; /** Handle to the interface. */ INTNETIFHANDLE hIf; } INTNETIFSENDREQ; /** Pointer to an INTNETR0IfSend() argument package. */ typedef INTNETIFSENDREQ *PINTNETIFSENDREQ; INTNETR0DECL(int) INTNETR0IfSendReq(PINTNET pIntNet, PSUPDRVSESSION pSession, PINTNETIFSENDREQ pReq); /** * Request buffer for INTNETR0IfWaitReq / VMMR0_DO_INTNET_IF_WAIT. * @see INTNETR0IfWait. */ typedef struct INTNETIFWAITREQ { /** The request header. */ SUPVMMR0REQHDR Hdr; /** Alternative to passing the taking the session from the VM handle. * Either use this member or use the VM handle, don't do both. */ PSUPDRVSESSION pSession; /** Handle to the interface. */ INTNETIFHANDLE hIf; /** The number of milliseconds to wait. */ uint32_t cMillies; } INTNETIFWAITREQ; /** Pointer to an INTNETR0IfWaitReq / VMMR0_DO_INTNET_IF_WAIT request buffer. */ typedef INTNETIFWAITREQ *PINTNETIFWAITREQ; INTNETR0DECL(int) INTNETR0IfWaitReq(PINTNET pIntNet, PSUPDRVSESSION pSession, PINTNETIFWAITREQ pReq); #if defined(IN_RING0) || defined(IN_INTNET_TESTCASE) /** @name * @{ */ /** * Create an instance of the Ring-0 internal networking service. * * @returns VBox status code. * @param ppIntNet Where to store the instance pointer. */ INTNETR0DECL(int) INTNETR0Create(PINTNET *ppIntNet); /** * Destroys an instance of the Ring-0 internal networking service. * * @param pIntNet Pointer to the instance data. */ INTNETR0DECL(void) INTNETR0Destroy(PINTNET pIntNet); /** * Opens a network interface and connects it to the specified network. * * @returns VBox status code. * @param pIntNet The internal network instance. * @param pSession The session handle. * @param pszNetwork The network name. * @param enmTrunkType The trunk type. * @param pszTrunk The trunk name. Its meaning is specfic to the type. * @param fFlags Flags, see INTNET_OPEN_FLAGS_*. * @param fRestrictAccess Whether new participants should be subjected to access check or not. * @param cbSend The send buffer size. * @param cbRecv The receive buffer size. * @param phIf Where to store the handle to the network interface. */ INTNETR0DECL(int) INTNETR0Open(PINTNET pIntNet, PSUPDRVSESSION pSession, const char *pszNetwork, INTNETTRUNKTYPE enmTrunkType, const char *pszTrunk, uint32_t fFlags, unsigned cbSend, unsigned cbRecv, PINTNETIFHANDLE phIf); /** * Close an interface. * * @returns VBox status code. * @param pIntNet The instance handle. * @param hIf The interface handle. * @param pSession The caller's session. */ INTNETR0DECL(int) INTNETR0IfClose(PINTNET pIntNet, INTNETIFHANDLE hIf, PSUPDRVSESSION pSession); /** * Gets the ring-0 address of the current buffer. * * @returns VBox status code. * @param pIntNet The instance data. * @param hIf The interface handle. * @param pSession The caller's session. * @param ppRing0Buf Where to store the address of the ring-3 mapping. */ INTNETR0DECL(int) INTNETR0IfGetRing0Buffer(PINTNET pIntNet, INTNETIFHANDLE hIf, PSUPDRVSESSION pSession, PINTNETBUF *ppRing0Buf); /** * Maps the default buffer into ring 3. * * @returns VBox status code. * @param pIntNet The instance data. * @param hIf The interface handle. * @param pSession The caller's session. * @param ppRing3Buf Where to store the address of the ring-3 mapping. */ INTNETR0DECL(int) INTNETR0IfGetRing3Buffer(PINTNET pIntNet, INTNETIFHANDLE hIf, PSUPDRVSESSION pSession, R3PTRTYPE(PINTNETBUF) *ppRing3Buf); /** * Sets the promiscuous mode property of an interface. * * @returns VBox status code. * @param pIntNet The instance handle. * @param hIf The interface handle. * @param pSession The caller's session. * @param fPromiscuous Set if the interface should be in promiscuous mode, clear if not. */ INTNETR0DECL(int) INTNETR0IfSetPromiscuousMode( PINTNET pIntNet, INTNETIFHANDLE hIf, PSUPDRVSESSION pSession, bool fPromiscuous); INTNETR0DECL(int) INTNETR0IfSetMacAddress( PINTNET pIntNet, INTNETIFHANDLE hIf, PSUPDRVSESSION pSession, PCRTMAC pMac); INTNETR0DECL(int) INTNETR0IfSetActive( PINTNET pIntNet, INTNETIFHANDLE hIf, PSUPDRVSESSION pSession, bool fActive); /** * Sends one or more frames. * * The function will first the frame which is passed as the optional * arguments pvFrame and cbFrame. These are optional since it also * possible to chain together one or more frames in the send buffer * which the function will process after considering it's arguments. * * @returns VBox status code. * @param pIntNet The instance data. * @param hIf The interface handle. * @param pSession The caller's session. * @param pvFrame Pointer to the frame. Optional, please don't use. * @param cbFrame Size of the frame. Optional, please don't use. */ INTNETR0DECL(int) INTNETR0IfSend(PINTNET pIntNet, INTNETIFHANDLE hIf, PSUPDRVSESSION pSession, const void *pvFrame, unsigned cbFrame); /** * Wait for the interface to get signaled. * The interface will be signaled when is put into the receive buffer. * * @returns VBox status code. * @param pIntNet The instance handle. * @param hIf The interface handle. * @param pSession The caller's session. * @param cMillies Number of milliseconds to wait. RT_INDEFINITE_WAIT should be * used if indefinite wait is desired. */ INTNETR0DECL(int) INTNETR0IfWait(PINTNET pIntNet, INTNETIFHANDLE hIf, PSUPDRVSESSION pSession, uint32_t cMillies); /** @} */ #endif /* IN_RING0 */ RT_C_DECLS_END #endif