root/trunk/include/VBox/intnet.h
| Revision 11157, 36.1 kB (checked in by vboxsync, 4 months ago) | |
|---|---|
| |
| Line | |
|---|---|
| 1 | /** @file |
| 2 | * INETNET - Internal Networking. |
| 3 | */ |
| 4 | |
| 5 | /* |
| 6 | * Copyright (C) 2006-2007 Sun Microsystems, Inc. |
| 7 | * |
| 8 | * This file is part of VirtualBox Open Source Edition (OSE), as |
| 9 | * available from http://www.virtualbox.org. This file is free software; |
| 10 | * you can redistribute it and/or modify it under the terms of the GNU |
| 11 | * General Public License (GPL) as published by the Free Software |
| 12 | * Foundation, in version 2 as it comes in the "COPYING" file of the |
| 13 | * VirtualBox OSE distribution. VirtualBox OSE is distributed in the |
| 14 | * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind. |
| 15 | * |
| 16 | * The contents of this file may alternatively be used under the terms |
| 17 | * of the Common Development and Distribution License Version 1.0 |
| 18 | * (CDDL) only, as it comes in the "COPYING.CDDL" file of the |
| 19 | * VirtualBox OSE distribution, in which case the provisions of the |
| 20 | * CDDL are applicable instead of those of the GPL. |
| 21 | * |
| 22 | * You may elect to license modified versions of this file under the |
| 23 | * terms and conditions of either the GPL or the CDDL or both. |
| 24 | * |
| 25 | * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa |
| 26 | * Clara, CA 95054 USA or visit http://www.sun.com if you need |
| 27 | * additional information or have any questions. |
| 28 | */ |
| 29 | |
| 30 | #ifndef ___VBox_intnet_h |
| 31 | #define ___VBox_intnet_h |
| 32 | |
| 33 | #include <VBox/types.h> |
| 34 | #include <VBox/stam.h> |
| 35 | #include <VBox/sup.h> |
| 36 | #include <iprt/assert.h> |
| 37 | #include <iprt/asm.h> |
| 38 | |
| 39 | __BEGIN_DECLS |
| 40 | |
| 41 | |
| 42 | /** Pointer to an internal network ring-0 instance. */ |
| 43 | typedef struct INTNET *PINTNET; |
| 44 | |
| 45 | /** |
| 46 | * Generic two-sided ring buffer. |
| 47 | * |
| 48 | * The deal is that there is exactly one writer and one reader. |
| 49 | * When offRead equals offWrite the buffer is empty. In the other |
| 50 | * extreme the writer will not use the last free byte in the buffer. |
| 51 | */ |
| 52 | typedef struct INTNETRINGBUF |
| 53 | { |
| 54 | /** The start of the buffer offset relative to the. (inclusive) */ |
| 55 | uint32_t offStart; |
| 56 | /** The offset to the end of the buffer. (exclusive) */ |
| 57 | uint32_t offEnd; |
| 58 | /** The current read offset. */ |
| 59 | uint32_t volatile offRead; |
| 60 | /** The current write offset. */ |
| 61 | uint32_t volatile offWrite; |
| 62 | } INTNETRINGBUF; |
| 63 | /** Pointer to a ring buffer. */ |
| 64 | typedef INTNETRINGBUF *PINTNETRINGBUF; |
| 65 | |
| 66 | /** |
| 67 | * Get the amount of space available for writing. |
| 68 | * |
| 69 | * @returns Number of available bytes. |
| 70 | * @param pRingBuf The ring buffer. |
| 71 | */ |
| 72 | DECLINLINE(uint32_t) INTNETRingGetWritable(PINTNETRINGBUF pRingBuf) |
| 73 | { |
| 74 | return pRingBuf->offRead <= pRingBuf->offWrite |
| 75 | ? pRingBuf->offEnd - pRingBuf->offWrite + pRingBuf->offRead - pRingBuf->offStart - 1 |
| 76 | : pRingBuf->offRead - pRingBuf->offWrite - 1; |
| 77 | } |
| 78 | |
| 79 | |
| 80 | /** |
| 81 | * Get the amount of data ready for reading. |
| 82 | * |
| 83 | * @returns Number of ready bytes. |
| 84 | * @param pRingBuf The ring buffer. |
| 85 | */ |
| 86 | DECLINLINE(uint32_t) INTNETRingGetReadable(PINTNETRINGBUF pRingBuf) |
| 87 | { |
| 88 | return pRingBuf->offRead <= pRingBuf->offWrite |
| 89 | ? pRingBuf->offWrite - pRingBuf->offRead |
| 90 | : pRingBuf->offEnd - pRingBuf->offRead + pRingBuf->offWrite - pRingBuf->offStart; |
| 91 | } |
| 92 | |
| 93 | |
| 94 | /** |
| 95 | * A interface buffer. |
| 96 | */ |
| 97 | typedef struct INTNETBUF |
| 98 | { |
| 99 | /** The size of the entire buffer. */ |
| 100 | uint32_t cbBuf; |
| 101 | /** The size of the send area. */ |
| 102 | uint32_t cbSend; |
| 103 | /** The size of the receive area. */ |
| 104 | uint32_t cbRecv; |
| 105 | /** The receive buffer. */ |
| 106 | INTNETRINGBUF Recv; |
| 107 | /** The send buffer. */ |
| 108 | INTNETRINGBUF Send; |
| 109 | /** Number of times yields help solve an overflow. */ |
| 110 | STAMCOUNTER cStatYieldsOk; |
| 111 | /** Number of times yields didn't help solve an overflow. */ |
| 112 | STAMCOUNTER cStatYieldsNok; |
| 113 | /** Number of lost packets due to overflows. */ |
| 114 | STAMCOUNTER cStatLost; |
| 115 | /** Number of packets received (not counting lost ones). */ |
| 116 | STAMCOUNTER cStatRecvs; |
| 117 | /** Number of frame bytes received (not couting lost frames). */ |
| 118 | STAMCOUNTER cbStatRecv; |
| 119 | /** Number of packets received. */ |
| 120 | STAMCOUNTER cStatSends; |
| 121 | /** Number of frame bytes sent. */ |
| 122 | STAMCOUNTER cbStatSend; |
| 123 | } INTNETBUF; |
| 124 | /** Pointer to an interface buffer. */ |
| 125 | typedef INTNETBUF *PINTNETBUF; |
| 126 | /** Pointer to a const interface buffer. */ |
| 127 | typedef INTNETBUF const *PCINTNETBUF; |
| 128 | |
| 129 | /** Internal networking interface handle. */ |
| 130 | typedef uint32_t INTNETIFHANDLE; |
| 131 | /** Pointer to an internal networking interface handle. */ |
| 132 | typedef INTNETIFHANDLE *PINTNETIFHANDLE; |
| 133 | |
| 134 | /** Or mask to obscure the handle index. */ |
| 135 | #define INTNET_HANDLE_MAGIC 0x88880000 |
| 136 | /** Mask to extract the handle index. */ |
| 137 | #define INTNET_HANDLE_INDEX_MASK 0xffff |
| 138 | /** The maximum number of handles (exclusive) */ |
| 139 | #define INTNET_HANDLE_MAX 0xffff |
| 140 | /** Invalid handle. */ |
| 141 | #define INTNET_HANDLE_INVALID (0) |
| 142 | |
| 143 | |
| 144 | /** |
| 145 | * The packet header. |
| 146 | * |
| 147 | * The header is intentionally 8 bytes long. It will always |
| 148 | * start at an 8 byte aligned address. Assuming that the buffer |
| 149 | * size is a multiple of 8 bytes, that means that we can guarantee |
| 150 | * that the entire header is contiguous in both virtual and physical |
| 151 | * memory. |
| 152 | */ |
| 153 | #pragma pack(1) |
| 154 | typedef struct INTNETHDR |
| 155 | { |
| 156 | /** Header type. This is currently serving as a magic, it |
| 157 | * can be extended later to encode special command packets and stuff. */ |
| 158 | uint16_t u16Type; |
| 159 | /** The size of the frame. */ |
| 160 | uint16_t cbFrame; |
| 161 | /** The offset from the start of this header to where the actual frame starts. |
| 162 | * This is used to keep the frame it self continguous in virtual memory and |
| 163 | * thereby both simplify reading and */ |
| 164 | int32_t offFrame; |
| 165 | } INTNETHDR; |
| 166 | #pragma pack() |
| 167 | /** Pointer to a packet header.*/ |
| 168 | typedef INTNETHDR *PINTNETHDR; |
| 169 | /** Pointer to a const packet header.*/ |
| 170 | typedef INTNETHDR const *PCINTNETHDR; |
| 171 | |
| 172 | /** INTNETHDR::u16Type value for normal frames. */ |
| 173 | #define INTNETHDR_TYPE_FRAME 0x2442 |
| 174 | |
| 175 | |
| 176 | /** |
| 177 | * Calculates the pointer to the frame. |
| 178 | * |
| 179 | * @returns Pointer to the start of the frame. |
| 180 | * @param pHdr Pointer to the packet header |
| 181 | * @param pBuf The buffer the header is within. Only used in strict builds. |
| 182 | */ |
| 183 | DECLINLINE(void *) INTNETHdrGetFramePtr(PCINTNETHDR pHdr, PCINTNETBUF pBuf) |
| 184 | { |
| 185 | uint8_t *pu8 = (uint8_t *)pHdr + pHdr->offFrame; |
| 186 | #ifdef VBOX_STRICT |
| 187 | const uintptr_t off = (uintptr_t)pu8 - (uintptr_t)pBuf; |
| 188 | Assert(pHdr->u16Type == INTNETHDR_TYPE_FRAME); |
| 189 | Assert(off < pBuf->cbBuf); |
| 190 | Assert(off + pHdr->cbFrame <= pBuf->cbBuf); |
| 191 | #endif |
| 192 | NOREF(pBuf); |
| 193 | return pu8; |
| 194 | } |
| 195 | |
| 196 | |
| 197 | /** |
| 198 | * Skips to the next (read) frame in the buffer. |
| 199 | * |
| 200 | * @param pBuf The buffer. |
| 201 | * @param pRingBuf The ring buffer in question. |
| 202 | */ |
| 203 | DECLINLINE(void) INTNETRingSkipFrame(PINTNETBUF pBuf, PINTNETRINGBUF pRingBuf) |
| 204 | { |
| 205 | uint32_t offRead = pRingBuf->offRead; |
| 206 | PINTNETHDR pHdr = (PINTNETHDR)((uint8_t *)pBuf + offRead); |
| 207 | Assert(pRingBuf->offRead < pBuf->cbBuf); |
| 208 | Assert(pRingBuf->offRead >= pRingBuf->offStart); |
| 209 | Assert(pRingBuf->offRead < pRingBuf->offEnd); |
| 210 | |
| 211 | /* skip the frame */ |
| 212 | offRead += pHdr->offFrame + pHdr->cbFrame; |
| 213 | offRead = RT_ALIGN_32(offRead, sizeof(INTNETHDR)); |
| 214 | Assert(offRead <= pRingBuf->offEnd && offRead >= pRingBuf->offStart); |
| 215 | if (offRead >= pRingBuf->offEnd) |
| 216 | offRead = pRingBuf->offStart; |
| 217 | ASMAtomicXchgU32(&pRingBuf->offRead, offRead); |
| 218 | } |
| 219 | |
| 220 | |
| 221 | /** |
| 222 | * Scatter / Gather segment (internal networking). |
| 223 | */ |
| 224 | typedef struct INTNETSEG |
| 225 | { |
| 226 | /** The physical address. NIL_RTHCPHYS is not set. */ |
| 227 | RTHCPHYS Phys; |
| 228 | /** Pointer to the segment data. */ |
| 229 | void *pv; |
| 230 | /** The segment size. */ |
| 231 | uint32_t cb; |
| 232 | } INTNETSEG; |
| 233 | /** Pointer to a internal networking packet segment. */ |
| 234 | typedef INTNETSEG *PINTNETSEG; |
| 235 | /** Pointer to a internal networking packet segment. */ |
| 236 | typedef INTNETSEG const *PCINTNETSEG; |
| 237 | |
| 238 | |
| 239 | /** |
| 240 | * Scatter / Gather list (internal networking). |
| 241 | * |
| 242 | * This is used when communicating with the trunk port. |
| 243 | */ |
| 244 | typedef struct INTNETSG |
| 245 | { |
| 246 | /** Owner data, don't touch! */ |
| 247 | void *pvOwnerData; |
| 248 | /** User data. */ |
| 249 | void *pvUserData; |
| 250 | /** User data 2 in case anyone needs it. */ |
| 251 | void *pvUserData2; |
| 252 | /** The total length of the scatter gather list. */ |
| 253 | uint32_t cbTotal; |
| 254 | /** The number of users (references). |
| 255 | * This is used by the SGRelease code to decide when it can be freed. */ |
| 256 | uint16_t volatile cUsers; |
| 257 | /** Flags, see INTNETSG_FLAGS_* */ |
| 258 | uint16_t volatile fFlags; |
| 259 | /** The number of segments allocated. */ |
| 260 | uint16_t cSegsAlloc; |
| 261 | /** The number of segments actually used. */ |
| 262 | uint16_t cSegsUsed; |
| 263 | /** Variable sized list of segments. */ |
| 264 | INTNETSEG aSegs[1]; |
| 265 | } INTNETSG; |
| 266 | /** Pointer to a scatter / gather list. */ |
| 267 | typedef INTNETSG *PINTNETSG; |
| 268 | /** Pointer to a const scatter / gather list. */ |
| 269 | typedef INTNETSG const *PCINTNETSG; |
| 270 | |
| 271 | /** @name INTNETSG::fFlags definitions. |
| 272 | * @{ */ |
| 273 | /** Set if the SG is free. */ |
| 274 | #define INTNETSG_FLAGS_FREE RT_BIT_32(1) |
| 275 | /** Set if the SG is a temporary one that will become invalid upon return. |
| 276 | * Try to finish using it before returning, and if that's not possible copy |
| 277 | * to other buffers. |
| 278 | * When not set, the callee should always free the SG. |
| 279 | * Attempts to free it made by the callee will be quietly ignored. */ |
| 280 | #define INTNETSG_FLAGS_TEMP RT_BIT_32(2) |
| 281 | /** ARP packet, IPv4 + MAC. |
| 282 | * @internal */ |
| 283 | #define INTNETSG_FLAGS_ARP_IPV4 RT_BIT_32(3) |
| 284 | /** Copied to the temporary buffer. |
| 285 | * @internal */ |
| 286 | #define INTNETSG_FLAGS_PKT_CP_IN_TMP RT_BIT_32(4) |
| 287 | /** @} */ |
| 288 | |
| 289 | |
| 290 | /** @name Direction (packet source or destination) |
| 291 | * @{ */ |
| 292 | /** To/From the wire. */ |
| 293 | #define INTNETTRUNKDIR_WIRE RT_BIT_32(0) |
| 294 | /** To/From the host. */ |
| 295 | #define INTNETTRUNKDIR_HOST RT_BIT_32(1) |
| 296 | /** Mask of valid bits. */ |
| 297 | #define INTNETTRUNKDIR_VALID_MASK UINT32_C(3) |
| 298 | /** @} */ |
| 299 | |
| 300 | |
| 301 | /** Pointer to the switch side of a trunk port. */ |
| 302 | typedef struct INTNETTRUNKSWPORT *PINTNETTRUNKSWPORT; |
| 303 | /** |
| 304 | * This is the port on the internal network 'switch', i.e. |
| 305 | * what the driver is connected to. |
| 306 | * |
| 307 | * This is only used for the in-kernel trunk connections. |
| 308 | */ |
| 309 | typedef struct INTNETTRUNKSWPORT |
| 310 | { |
| 311 | /** Structure version number. (INTNETTRUNKSWPORT_VERSION) */ |
| 312 | uint32_t u32Version; |
| 313 | |
| 314 | /** |
| 315 | * Selects whether outgoing SGs should have their physical address set. |
| 316 | * |
| 317 | * By enabling physical addresses in the scatter / gather segments it should |
| 318 | * be possible to save some unnecessary address translation and memory locking |
| 319 | * in the network stack. (Internal networking knows the physical address for |
| 320 | * all the INTNETBUF data and that it's locked memory.) There is a negative |
| 321 | * side effects though, frames that crosses page boundraries will require |
| 322 | * multiple scather / gather segments. |
| 323 | * |
| 324 | * @returns The old setting. |
| 325 | * |
| 326 | * @param pSwitchPort Pointer to this structure. |
| 327 | * @param fEnable Whether to enable or disable it. |
| 328 | * |
| 329 | * @remarks Will grab the network semaphore. |
| 330 | */ |
| 331 | DECLR0CALLBACKMEMBER(bool, pfnSetSGPhys,(PINTNETTRUNKSWPORT pSwitchPort, bool fEnable)); |
| 332 | |
| 333 | /** |
| 334 | * Incoming frame. |
| 335 | * |
| 336 | * The frame may be modified when the trunk port on the switch is set to share |
| 337 | * the mac address of the host when hitting the wire. Currently rames containing |
| 338 | * ARP packets are subject to this, later other protocols like NDP/ICMPv6 may |
| 339 | * need editing as well when operating in this mode. |
| 340 | * |
| 341 | * @returns true if we've handled it and it should be dropped. |
| 342 | * false if it should hit the wire. |
| 343 | * |
| 344 | * @param pSwitchPort Pointer to this structure. |
| 345 | * @param pSG The (scatter /) gather structure for the frame. |
| 346 | * This will only be use during the call, so a temporary one can |
| 347 | * be used. The Phys member will not be used. |
| 348 | * @param fSrc Where this frame comes from. Only one bit should be set! |
| 349 | * |
| 350 | * @remarks Will grab the network semaphore. |
| 351 | * |
| 352 | * @remarks NAT and TAP will use this interface. |
| 353 | * |
| 354 | * @todo Do any of the host require notification before frame modifications? If so, |
| 355 | * we'll add a callback to INTNETTRUNKIFPORT for this (pfnSGModifying) and |
| 356 | * a SG flag. |
| 357 | */ |
| 358 | DECLR0CALLBACKMEMBER(bool, pfnRecv,(PINTNETTRUNKSWPORT pSwitchPort, PINTNETSG pSG, uint32_t fSrc)); |
| 359 | |
| 360 | /** |
| 361 | * Retain a SG. |
| 362 | * |
| 363 | * @param pSwitchPort Pointer to this structure. |
| 364 | * @param pSG Pointer to the (scatter /) gather structure. |
| 365 | * |
| 366 | * @remarks Will not grab any locks. |
| 367 | */ |
| 368 | DECLR0CALLBACKMEMBER(void, pfnSGRetain,(PINTNETTRUNKSWPORT pSwitchPort, PINTNETSG pSG)); |
| 369 | |
| 370 | /** |
| 371 | * Release a SG. |
| 372 | * |
| 373 | * This is called by the pfnXmit code when done with a SG. This may safe |
| 374 | * be done in an asynchronous manner. |
| 375 | * |
| 376 | * @param pSwitchPort Pointer to this structure. |
| 377 | * @param pSG Pointer to the (scatter /) gather structure. |
| 378 | * |
| 379 | * @remarks Will grab the network semaphore. |
| 380 | */ |
| 381 | DECLR0CALLBACKMEMBER(void, pfnSGRelease,(PINTNETTRUNKSWPORT pSwitchPort, PINTNETSG pSG)); |
| 382 | |
| 383 | /** Structure version number. (INTNETTRUNKSWPORT_VERSION) */ |
| 384 | uint32_t u32VersionEnd; |
| 385 | } INTNETTRUNKSWPORT; |
| 386 | |
| 387 | /** Version number for the INTNETTRUNKIFPORT::u32Version and INTNETTRUNKIFPORT::u32VersionEnd fields. */ |
| 388 | #define INTNETTRUNKSWPORT_VERSION UINT32_C(0xA2CDf001) |
| 389 | |
| 390 | |
| 391 | /** Pointer to the interface side of a trunk port. */ |
| 392 | typedef struct INTNETTRUNKIFPORT *PINTNETTRUNKIFPORT; |
| 393 | /** |
| 394 | * This is the port on the trunk interface, i.e. the driver |
| 395 | * side which the internal network is connected to. |
| 396 | * |
| 397 | * This is only used for the in-kernel trunk connections. |
| 398 | * |
| 399 | * @remarks The internal network side is responsible for serializing all calls |
| 400 | * to this interface. This is (assumed) to be implemented using a lock |
| 401 | * that is only ever taken before a call to this interface. The lock |
| 402 | * is referred to as the out-bound trunk port lock. |
| 403 | */ |
| 404 | typedef struct INTNETTRUNKIFPORT |
| 405 | { |
| 406 | /** Structure version number. (INTNETTRUNKIFPORT_VERSION) */ |
| 407 | uint32_t u32Version; |
| 408 | |
| 409 | /** |
| 410 | * Retain the object. |
| 411 | * |
| 412 | * It will normally be called while owning the internal network semaphore. |
| 413 | * |
| 414 | * @param pIfPort Pointer to this structure. |
| 415 | * |
| 416 | * @remarks The caller may own any locks or none at all, we don't care. |
| 417 | */ |
| 418 | DECLR0CALLBACKMEMBER(void, pfnRetain,(PINTNETTRUNKIFPORT pIfPort)); |
| 419 | |
| 420 | /** |
| 421 | * Releases the object. |
| 422 | * |
| 423 | * This must be called for every pfnRetain call. |
| 424 | * |
| 425 | * |
| 426 | * @param pIfPort Pointer to this structure. |
| 427 | * |
| 428 | * @remarks Only the out-bound trunk port lock, unless the caller is certain the |
| 429 | * call is not going to cause destruction (wont happen). |
| 430 | */ |
| 431 | DECLR0CALLBACKMEMBER(void, pfnRelease,(PINTNETTRUNKIFPORT pIfPort)); |
| 432 | |
| 433 | /** |
| 434 | * Disconnect from the switch and release the object. |
| 435 | * |
| 436 | * The is the counter action of the |
| 437 | * INTNETTRUNKNETFLTFACTORY::pfnCreateAndConnect method. |
| 438 | * |
| 439 | * @param pIfPort Pointer to this structure. |
| 440 | * |
| 441 | * @remarks Called holding the out-bound trunk port lock. |
| 442 | */ |
| 443 | DECLR0CALLBACKMEMBER(void, pfnDisconnectAndRelease,(PINTNETTRUNKIFPORT pIfPort)); |
| 444 | |
| 445 | /** |
| 446 | * Changes the active state of the interface. |
| 447 | * |
| 448 | * The interface is created in the suspended (non-active) state and then activated |
| 449 | * when the VM/network is started. It may be suspended and re-activated later |
| 450 | * for various reasons. It will finally be suspended again before disconnecting |
| 451 | * the interface from the internal network, however, this might be done immediately |
| 452 | * before disconnecting and may leave an incoming frame waiting on the internal network |
| 453 | * semaphore. So, after the final suspend a pfnWaitForIdle is always called to make sure |
| 454 | * the interface is idle before pfnDisconnectAndRelease is called. |
| 455 | * |
| 456 | * A typical operation to performed by this method is to enable/disable promiscuous |
| 457 | * mode on the host network interface. (This is the reason we cannot call this when |
| 458 | * owning any semaphores.) |
| 459 | * |
| 460 | * @returns The previous state. |
| 461 | * |
| 462 | * @param pIfPort Pointer to this structure. |
| 463 | * @param fActive True if the new state is 'active', false if the new state is 'suspended'. |
| 464 | * |
| 465 | * @remarks Called holding the out-bound trunk port lock. |
| 466 | */ |
| 467 | DECLR0CALLBACKMEMBER(bool, pfnSetActive,(PINTNETTRUNKIFPORT pIfPort, bool fActive)); |
| 468 | |
| 469 | /** |
| 470 | * Waits for the interface to become idle. |
| 471 | * |
| 472 | * This method must be called before disconnecting and releasing the |
| 473 | * object in order to prevent racing incoming/outgoing packets and |
| 474 | * device enabling/disabling. |
| 475 | * |
| 476 | * @returns IPRT status code (see RTSemEventWait). |
| 477 | * @param pIfPort Pointer to this structure. |
| 478 | * @param cMillies The number of milliseconds to wait. 0 means |
| 479 | * no waiting at all. Use RT_INDEFINITE_WAIT for |
| 480 | * an indefinite wait. |
| 481 | * |
| 482 | * @remarks Called holding the out-bound trunk port lock. |
| 483 | */ |
| 484 | DECLR0CALLBACKMEMBER(int, pfnWaitForIdle,(PINTNETTRUNKIFPORT pIfPort, uint32_t cMillies)); |
| 485 | |
| 486 | /** |
| 487 | * Gets the MAC address of the host network interface that we're attached to. |
| 488 | * |
| 489 | * @param pIfPort Pointer to this structure. |
| 490 | * @param pMac Where to store the host MAC address. |
| 491 | * |
| 492 | * @remarks Called while owning the network and the out-bound trunk port semaphores. |
| 493 | */ |
| 494 | DECLR0CALLBACKMEMBER(void, pfnGetMacAddress,(PINTNETTRUNKIFPORT pIfPort, PRTMAC pMac)); |
| 495 | |
| 496 | /** |
| 497 | * Tests if the mac address belongs to any of the host NICs |
| 498 | * and should take the host route. |
| 499 | * |
| 500 | * @returns true / false. |
| 501 | * |
| 502 | * @param pIfPort Pointer to this structure. |
| 503 | * @param pMac Pointer to the mac address. |
| 504 | * |
| 505 | * @remarks Called while owning the network and the out-bound trunk port semaphores. |
| 506 | * |
| 507 | * @remarks TAP and NAT will compare with their own MAC address and let all their |
| 508 | * traffic take the host direction. |
| 509 | * |
| 510 | * @remarks This didn't quiet work out the way it should... perhaps obsolete this |
| 511 | * with pfnGetHostMac? |
| 512 | */ |
| 513 | DECLR0CALLBACKMEMBER(bool, pfnIsHostMac,(PINTNETTRUNKIFPORT pIfPort, PCRTMAC pMac)); |
| 514 | |
| 515 | /** |
| 516 | * Tests whether the host is operating the interface is promiscuous mode. |
| 517 | * |
| 518 | * The default behavior of the internal networking 'switch' is to 'autodetect' |
| 519 | * promiscuous mode on the trunk port, which is when this method is used. |
| 520 | * For security reasons this default may of course be overridden so that the |
| 521 | * host cannot sniff at what's going on. |
| 522 | * |
| 523 | * Note that this differs from operating the trunk port on the switch in |
| 524 | * 'promiscuous' mode, because that relates to the bits going to the wire. |
| 525 | * |
| 526 | * @returns true / false. |
| 527 | * |
| 528 | * @param pIfPort Pointer to this structure. |
| 529 | * |
| 530 | * @remarks Called while owning the network and the out-bound trunk port semaphores. |
| 531 | */ |
| 532 | DECLR0CALLBACKMEMBER(bool, pfnIsPromiscuous,(PINTNETTRUNKIFPORT pIfPort)); |
| 533 | |
| 534 | /** |
| 535 | * Transmit a frame. |
| 536 | * |
| 537 | * @return VBox status code. Error generally means we'll drop the packet. |
| 538 | * @param pIfPort Pointer to this structure. |
| 539 | * @param pSG Pointer to the (scatter /) gather structure for the frame. |
| 540 | * This may or may not be a temporary buffer. If it's temporary |
| 541 | * the transmit operation(s) then it's required to make a copy |
| 542 | * of the frame unless it can be transmitted synchronously. |
| 543 | * @param fDst The destination mask. At least one bit will be set. |
| 544 | * |
| 545 | * @remarks Called holding the out-bound trunk port lock. |
| 546 | * |
| 547 | * @remarks TAP and NAT will use this interface for all their traffic, see pfnIsHostMac. |
| 548 | * |
| 549 | * @todo |
| 550 | */ |
| 551 | DECLR0CALLBACKMEMBER(int, pfnXmit,(PINTNETTRUNKIFPORT pIfPort, PINTNETSG pSG, uint32_t fDst)); |
| 552 | |
| 553 | /** Structure version number. (INTNETTRUNKIFPORT_VERSION) */ |
| 554 | uint32_t u32VersionEnd; |
| 555 | } INTNETTRUNKIFPORT; |
| 556 | |
| 557 | /** Version number for the INTNETTRUNKIFPORT::u32Version and INTNETTRUNKIFPORT::u32VersionEnd fields. */ |
| 558 | #define INTNETTRUNKIFPORT_VERSION UINT32_C(0xA2CDe001) |
| 559 | |
| 560 | |
| 561 | /** |
| 562 | * The component factory interface for create a network |
| 563 | * interface filter (like VBoxNetFlt). |
| 564 | */ |
| 565 | typedef struct INTNETTRUNKFACTORY |
| 566 | { |
| 567 | /** |
| 568 | * Release this factory. |
| 569 | * |
| 570 | * SUPR0ComponentQueryFactory (SUPDRVFACTORY::pfnQueryFactoryInterface to be precise) |
| 571 | * will retain a reference to the factory and the caller has to call this method to |
| 572 | * release it once the pfnCreateAndConnect call(s) has been done. |
| 573 | * |
| 574 | * @param pIfFactory Pointer to this structure. |
| 575 | */ |
| 576 | DECLR0CALLBACKMEMBER(void, pfnRelease,(struct INTNETTRUNKFACTORY *pIfFactory)); |
| 577 | |
| 578 | /** |
| 579 | * Create an instance for the specfied host interface and connects it |
| 580 | * to the internal network trunk port. |
| 581 | * |
| 582 | * The initial interface active state is false (suspended). |
| 583 | * |
| 584 | * |
| 585 | * @returns VBox status code. |
| 586 | * @retval VINF_SUCCESS and *ppIfPort set on success. |
| 587 | * @retval VERR_INTNET_FLT_IF_NOT_FOUND if the interface was not found. |
| 588 | * @retval VERR_INTNET_FLT_IF_BUSY if the interface is already connected. |
| 589 | * @retval VERR_INTNET_FLT_IF_FAILED if it failed for some other reason. |
| 590 | * |
| 591 | * @param pIfFactory Pointer to this structure. |
| 592 | * @param pszName The interface name (OS specific). |
| 593 | * @param pSwitchPort Pointer to the port interface on the switch that |
| 594 | * this interface is being connected to. |
| 595 | * @param ppIfPort Where to store the pointer to the interface port |
| 596 | * on success. |
| 597 | * |
| 598 | * @remarks Called while owning the network and the out-bound trunk semaphores. |
| 599 | */ |
| 600 | DECLR0CALLBACKMEMBER(int, pfnCreateAndConnect,(struct INTNETTRUNKFACTORY *pIfFactory, const char *pszName, |
| 601 | PINTNETTRUNKSWPORT pSwitchPort, PINTNETTRUNKIFPORT *ppIfPort)); |
| 602 | } INTNETTRUNKFACTORY; |
| 603 | /** Pointer to the trunk factory. */ |
| 604 | typedef INTNETTRUNKFACTORY *PINTNETTRUNKFACTORY; |
| 605 | |
| 606 | /** The UUID for the (current) trunk factory. (case sensitive) */ |
| 607 | #define INTNETTRUNKFACTORY_UUID_STR "ae8fcb95-280c-42f4-a8f1-09f84e3bdab3" |
| 608 | |
| 609 | |
| 610 | /** |
| 611 | * The trunk connection type. |
| 612 | * |
| 613 | * Used by INTNETR0Open and assoicated interfaces. |
| 614 | */ |
| 615 | typedef enum INTNETTRUNKTYPE |
| 616 | { |
| 617 | /** Invalid trunk type. */ |
| 618 | kIntNetTrunkType_Invalid = 0, |
| 619 | /** No trunk connection. */ |
| 620 | kIntNetTrunkType_None, |
| 621 | /** We don't care which kind of trunk connection if the network exists, |
| 622 | * if it doesn't exist create it without a connection. */ |
| 623 | kIntNetTrunkType_WhateverNone, |
| 624 | /** VirtualBox host network interface filter driver. |
| 625 | * The trunk name is the name of the host network interface. */ |
| 626 | kIntNetTrunkType_NetFlt, |
| 627 | /** VirtualBox TAP host driver. */ |
| 628 | kIntNetTrunkType_NetTap, |
| 629 | /** Nat service (ring-0). */ |
| 630 | kIntNetTrunkType_SrvNat, |
| 631 | /** The end of valid types. */ |
| 632 | kIntNetTrunkType_End, |
| 633 | /** The usual 32-bit hack. */ |
| 634 | kIntNetTrunkType_32bitHack = 0x7fffffff |
| 635 | } INTNETTRUNKTYPE; |
| 636 | |
| 637 | /** @name INTNETR0Open flags. |
| 638 | * @{ */ |
| 639 | /** Share the MAC address with the host when sending something to the wire via the trunk. |
| 640 | * This is typically used when the trunk is a NetFlt for a wireless interface. */ |
| 641 | #define INTNET_OPEN_FLAGS_SHARED_MAC_ON_WIRE RT_BIT_32(0) |
| 642 | /** Whether new participants should be subjected to access check or not. */ |
| 643 | #define INTNET_OPEN_FLAGS_PUBLIC RT_BIT_32(1) |
| 644 | /** Ignore any requests for promiscuous mode. */ |
| 645 | #define INTNET_OPEN_FLAGS_IGNORE_PROMISC RT_BIT_32(2) |
| 646 | /** Ignore any requests for promiscuous mode, quietly applied/ignored on open. */ |
| 647 | #define INTNET_OPEN_FLAGS_QUIETLY_IGNORE_PROMISC RT_BIT_32(3) |
| 648 | /** Ignore any requests for promiscuous mode on the trunk wire connection. */ |
| 649 | #define INTNET_OPEN_FLAGS_IGNORE_PROMISC_TRUNK_WIRE RT_BIT_32(4) |
| 650 | /** Ignore any requests for promiscuous mode on the trunk wire connection, quietly applied/ignored on open. */ |
| 651 | #define INTNET_OPEN_FLAGS_QUIETLY_IGNORE_PROMISC_TRUNK_WIRE RT_BIT_32(5) |
| 652 | /** Ignore any requests for promiscuous mode on the trunk host connection. */ |
| 653 | #define INTNET_OPEN_FLAGS_IGNORE_PROMISC_TRUNK_HOST RT_BIT_32(6) |
| 654 | /** Ignore any requests for promiscuous mode on the trunk host connection, quietly applied/ignored on open. */ |
| 655 | #define INTNET_OPEN_FLAGS_QUIETLY_IGNORE_PROMISC_TRUNK_HOST RT_BIT_32(7) |
| 656 | /** The mask of flags which causes flag incompatibilities. */ |
| 657 | #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)) |
| 658 | /** The mask of flags is always ORed in, even on open. (the quiet stuff) */ |
| 659 | #define INTNET_OPEN_FLAGS_SECURITY_OR_MASK (RT_BIT_32(3) | RT_BIT_32(5) | RT_BIT_32(7)) |
| 660 | /** The mask of valid flags. */ |
| 661 | #define INTNET_OPEN_FLAGS_MASK UINT32_C(0x000000ff) |
| 662 | /** @} */ |
| 663 | |
| 664 | /** The maximum length of a network name. */ |
| 665 | #define INTNET_MAX_NETWORK_NAME 128 |
| 666 | |
| 667 | /** The maximum length of a trunk name. */ |
| 668 | #define INTNET_MAX_TRUNK_NAME 64 |
| 669 | |
| 670 | |
| 671 | /** |
| 672 | * Request buffer for INTNETR0OpenReq / VMMR0_DO_INTNET_OPEN. |
| 673 | * @see INTNETR0Open. |
| 674 | */ |
| 675 | typedef struct INTNETOPENREQ |
| 676 | { |
| 677 | /** The request header. */ |
| 678 | SUPVMMR0REQHDR Hdr; |
| 679 | /** Alternative to passing the taking the session from the VM handle. |
| 680 | * Either use this member or use the VM handle, don't do both. */ |
| 681 | PSUPDRVSESSION pSession; |
| 682 | /** The network name. (input) */ |
| 683 | char szNetwork[INTNET_MAX_NETWORK_NAME]; |
| 684 | /** What to connect to the trunk port. (input) |
| 685 | * This is specific to the trunk type below. */ |
| 686 | char szTrunk[INTNET_MAX_TRUNK_NAME]; |
| 687 | /** The type of trunk link (NAT, Filter, TAP, etc). (input) */ |
| 688 | INTNETTRUNKTYPE enmTrunkType; |
| 689 | /** Flags, see INTNET_OPEN_FLAGS_*. (input) */ |
| 690 | uint32_t fFlags; |
| 691 | /** The size of the send buffer. (input) */ |
| 692 | uint32_t cbSend; |
| 693 | /** The size of the receive buffer. (input) */ |
| 694 | uint32_t cbRecv; |
| 695 | /** The handle to the network interface. (output) */ |
| 696 | INTNETIFHANDLE hIf; |
| 697 | } INTNETOPENREQ; |
| 698 | /** Pointer to an INTNETR0OpenReq / VMMR0_DO_INTNET_OPEN request buffer. */ |
| 699 | typedef INTNETOPENREQ *PINTNETOPENREQ; |
| 700 | |
| 701 | INTNETR0DECL(int) INTNETR0OpenReq(PINTNET pIntNet, PSUPDRVSESSION pSession, PINTNETOPENREQ pReq); |
| 702 | |
| 703 | |
| 704 | /** |
| 705 | * Request buffer for INTNETR0IfCloseReq / VMMR0_DO_INTNET_IF_CLOSE. |
| 706 | * @see INTNETR0IfClose. |
| 707 | */ |
| 708 | typedef struct INTNETIFCLOSEREQ |
| 709 | { |
| 710 | /** The request header. */ |
| 711 | SUPVMMR0REQHDR Hdr; |
| 712 | /** Alternative to passing the taking the session from the VM handle. |
| 713 | * Either use this member or use the VM handle, don't do both. */ |
| 714 | PSUPDRVSESSION pSession; |
| 715 | /** The handle to the network interface. */ |
| 716 | INTNETIFHANDLE hIf; |
| 717 | } INTNETIFCLOSEREQ; |
| 718 | /** Pointer to an INTNETR0IfCloseReq / VMMR0_DO_INTNET_IF_CLOSE request buffer. */ |
| 719 | typedef INTNETIFCLOSEREQ *PINTNETIFCLOSEREQ; |
| 720 | |
| 721 | INTNETR0DECL(int) INTNETR0IfCloseReq(PINTNET pIntNet, PSUPDRVSESSION pSession, PINTNETIFCLOSEREQ pReq); |
| 722 | |
| 723 | |
| 724 | /** |
| 725 | * Request buffer for INTNETR0IfGetRing3BufferReq / VMMR0_DO_INTNET_IF_GET_RING3_BUFFER. |
| 726 | * @see INTNETR0IfGetRing3Buffer. |
| 727 | */ |
| 728 | typedef struct INTNETIFGETRING3BUFFERREQ |
| 729 | { |
| 730 | /** The request header. */ |
| 731 | SUPVMMR0REQHDR Hdr; |
| 732 | /** Alternative to passing the taking the session from the VM handle. |
| 733 | * Either use this member or use the VM handle, don't do both. */ |
| 734 | PSUPDRVSESSION pSession; |
| 735 | /** Handle to the interface. */ |
| 736 | INTNETIFHANDLE hIf; |
| 737 | /** The pointer to the ring3 buffer. (output) */ |
| 738 | R3PTRTYPE(PINTNETBUF) pRing3Buf; |
| 739 | } INTNETIFGETRING3BUFFERREQ; |
| 740 | /** Pointer to an INTNETR0IfGetRing3BufferReq / VMMR0_DO_INTNET_IF_GET_RING3_BUFFER request buffer. */ |
| 741 | typedef INTNETIFGETRING3BUFFERREQ *PINTNETIFGETRING3BUFFERREQ; |
| 742 | |
| 743 | INTNETR0DECL(int) INTNETR0IfGetRing3BufferReq(PINTNET pIntNet, PSUPDRVSESSION pSession, PINTNETIFGETRING3BUFFERREQ pReq); |
| 744 | |
| 745 | |
| 746 | /** |
| 747 | * Request buffer for INTNETR0IfSetPromiscuousModeReq / VMMR0_DO_INTNET_IF_SET_PROMISCUOUS_MODE. |
| 748 | * @see INTNETR0IfSetPromiscuousMode. |
| 749 | */ |
| 750 | typedef struct INTNETIFSETPROMISCUOUSMODEREQ |
| 751 | { |
| 752 | /** The request header. */ |
| 753 | SUPVMMR0REQHDR Hdr; |
| 754 | /** Alternative to passing the taking the session from the VM handle. |
| 755 | * Either use this member or use the VM handle, don't do both. */ |
| 756 | PSUPDRVSESSION pSession; |
| 757 | /** Handle to the interface. */ |
| 758 | INTNETIFHANDLE hIf; |
| 759 | /** The new promiscuous mode. */ |
| 760 | bool fPromiscuous; |
| 761 | } INTNETIFSETPROMISCUOUSMODEREQ; |
| 762 | /** Pointer to an INTNETR0IfSetPromiscuousModeReq / VMMR0_DO_INTNET_IF_SET_PROMISCUOUS_MODE request buffer. */ |
| 763 | typedef INTNETIFSETPROMISCUOUSMODEREQ *PINTNETIFSETPROMISCUOUSMODEREQ; |
| 764 | |
| 765 | INTNETR0DECL(int) INTNETR0IfSetPromiscuousModeReq(PINTNET pIntNet, PSUPDRVSESSION pSession, PINTNETIFSETPROMISCUOUSMODEREQ pReq); |
| 766 | |
| 767 | |
| 768 | /** |
| 769 | * Request buffer for INTNETR0IfSetMacAddressReq / VMMR0_DO_INTNET_IF_SET_MAC_ADDRESS. |
| 770 | * @see INTNETR0IfSetMacAddress. |
| 771 | */ |
| 772 | typedef struct INTNETIFSETMACADDRESSREQ |
| 773 | { |
| 774 | /** The request header. */ |
| 775 | SUPVMMR0REQHDR Hdr; |
| 776 | /** Alternative to passing the taking the session from the VM handle. |
| 777 | * Either use this member or use the VM handle, don't do both. */ |
| 778 | PSUPDRVSESSION pSession; |
| 779 | /** Handle to the interface. */ |
| 780 | INTNETIFHANDLE hIf; |
| 781 | /** The new MAC address. */ |
| 782 | RTMAC Mac; |
| 783 | } INTNETIFSETMACADDRESSREQ; |
| 784 | /** Pointer to an INTNETR0IfSetMacAddressReq / VMMR0_DO_INTNET_IF_SET_MAC_ADDRESS request buffer. */ |
| 785 | typedef INTNETIFSETMACADDRESSREQ *PINTNETIFSETMACADDRESSREQ; |
| 786 | |
| 787 | INTNETR0DECL(int) INTNETR0IfSetMacAddressReq(PINTNET pIntNet, PSUPDRVSESSION pSession, PINTNETIFSETMACADDRESSREQ pReq); |
| 788 | |
| 789 | |
| 790 | /** |
| 791 | * Request buffer for INTNETR0IfSetActiveReq / VMMR0_DO_INTNET_IF_SET_ACTIVE. |
| 792 | * @see INTNETR0IfSetActive. |
| 793 | */ |
| 794 | typedef struct INTNETIFSETACTIVEREQ |
| 795 | { |
| 796 | /** The request header. */ |
| 797 | SUPVMMR0REQHDR Hdr; |
| 798 | /** Alternative to passing the taking the session from the VM handle. |
| 799 | * Either use this member or use the VM handle, don't do both. */ |
| 800 | PSUPDRVSESSION pSession; |
| 801 | /** Handle to the interface. */ |
| 802 | INTNETIFHANDLE hIf; |
| 803 | /** The new state. */ |
| 804 | bool fActive; |
| 805 | } INTNETIFSETACTIVEREQ; |
| 806 | /** Pointer to an INTNETR0IfSetActiveReq / VMMR0_DO_INTNET_IF_SET_ACTIVE request buffer. */ |
| 807 | typedef INTNETIFSETACTIVEREQ *PINTNETIFSETACTIVEREQ; |
| 808 | |
| 809 | INTNETR0DECL(int) INTNETR0IfSetActiveReq(PINTNET pIntNet, PSUPDRVSESSION pSession, PINTNETIFSETACTIVEREQ pReq); |
| 810 | |
| 811 | |
| 812 | /** |
| 813 | * Request buffer for INTNETR0IfSendReq / VMMR0_DO_INTNET_IF_SEND. |
| 814 | * @see INTNETR0IfSend. |
| 815 | */ |
| 816 | typedef struct INTNETIFSENDREQ |
| 817 | { |
| 818 | /** The request header. */ |
| 819 | SUPVMMR0REQHDR Hdr; |
| 820 | /** Alternative to passing the taking the session from the VM handle. |
| 821 | * Either use this member or use the VM handle, don't do both. */ |
| 822 | PSUPDRVSESSION pSession; |
| 823 | /** Handle to the interface. */ |
| 824 | INTNETIFHANDLE hIf; |
| 825 | } INTNETIFSENDREQ; |
| 826 | /** Pointer to an INTNETR0IfSend() argument package. */ |
| 827 | typedef INTNETIFSENDREQ *PINTNETIFSENDREQ; |
| 828 | |
| 829 | INTNETR0DECL(int) INTNETR0IfSendReq(PINTNET pIntNet, PSUPDRVSESSION pSession, PINTNETIFSENDREQ pReq); |
| 830 | |
| 831 | |
| 832 | /** |
| 833 | * Request buffer for INTNETR0IfWaitReq / VMMR0_DO_INTNET_IF_WAIT. |
| 834 | * @see INTNETR0IfWait. |
| 835 | */ |
| 836 | typedef struct INTNETIFWAITREQ |
| 837 | { |
| 838 | /** The request header. */ |
| 839 | SUPVMMR0REQHDR Hdr; |
| 840 | /** Alternative to passing the taking the session from the VM handle. |
| 841 | * Either use this member or use the VM handle, don't do both. */ |
| 842 | PSUPDRVSESSION pSession; |
| 843 | /** Handle to the interface. */ |
| 844 | INTNETIFHANDLE hIf; |
| 845 | /** The number of milliseconds to wait. */ |
| 846 | uint32_t cMillies; |
| 847 | } INTNETIFWAITREQ; |
| 848 | /** Pointer to an INTNETR0IfWaitReq / VMMR0_DO_INTNET_IF_WAIT request buffer. */ |
| 849 | typedef INTNETIFWAITREQ *PINTNETIFWAITREQ; |
| 850 | |
| 851 | INTNETR0DECL(int) INTNETR0IfWaitReq(PINTNET pIntNet, PSUPDRVSESSION pSession, PINTNETIFWAITREQ pReq); |
| 852 | |
| 853 | |
| 854 | #if defined(IN_RING0) || defined(IN_INTNET_TESTCASE) |
| 855 | /** @name |
| 856 | * @{ |
| 857 | */ |
| 858 | |
| 859 | /** |
| 860 | * Create an instance of the Ring-0 internal networking service. |
| 861 | * |
| 862 | * @returns VBox status code. |
| 863 | * @param ppIntNet Where to store the instance pointer. |
| 864 | */ |
| 865 | INTNETR0DECL(int) INTNETR0Create(PINTNET *ppIntNet); |
| 866 | |
| 867 | /** |
| 868 | * Destroys an instance of the Ring-0 internal networking service. |
| 869 | * |
| 870 | * @param pIntNet Pointer to the instance data. |
| 871 | */ |
| 872 |

