VirtualBox

source: vbox/trunk/src/VBox/Devices/Network/DrvVMNet.m@ 91418

Last change on this file since 91418 was 91418, checked in by vboxsync, 3 years ago

Devices: bugref:9932 More build fixes for r147096

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 22.8 KB
Line 
1/* $Id: DrvVMNet.m 91418 2021-09-28 07:13:29Z vboxsync $ */
2/** @file
3 * DrvVMNet - Network filter driver that uses MAC OS VMNET API.
4 */
5
6/*
7 * Copyright (C) 2021 Oracle Corporation
8 *
9 * This file is part of VirtualBox Open Source Edition (OSE), as
10 * available from http://www.virtualbox.org. This file is free software;
11 * you can redistribute it and/or modify it under the terms of the GNU
12 * General Public License (GPL) as published by the Free Software
13 * Foundation, in version 2 as it comes in the "COPYING" file of the
14 * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
15 * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
16 */
17
18
19/*********************************************************************************************************************************
20* Header Files *
21*********************************************************************************************************************************/
22#define LOG_GROUP LOG_GROUP_DRV_VMNET
23#include <VBox/vmm/pdmdrv.h>
24#include <VBox/vmm/pdmnetifs.h>
25#include <VBox/vmm/pdmnetinline.h>
26#include <VBox/intnet.h>
27
28#include <VBox/log.h>
29#include <iprt/assert.h>
30#include <iprt/critsect.h>
31#include <iprt/file.h>
32#include <iprt/mem.h>
33#include <iprt/process.h>
34#include <iprt/string.h>
35#include <iprt/time.h>
36#include <iprt/uuid.h>
37#include <iprt/path.h>
38#include <VBox/param.h>
39
40#include "Pcap.h"
41#include "VBoxDD.h"
42
43#include <sys/uio.h>
44#import <vmnet/vmnet.h>
45
46#define VMNET_MAX_HOST_INTERFACE_NAME_LENGTH 16
47#define VMNET_MAX_IP_ADDRESS_STRING_LENGTH 48
48
49/* Force release logging for debug builds */
50#if 0
51# undef Log
52# undef LogFlow
53# undef Log2
54# undef Log3
55# define Log LogRel
56# define LogFlow LogRel
57# define Log2 LogRel
58# define Log3 LogRel
59#endif
60
61
62/*********************************************************************************************************************************
63* Structures and Typedefs *
64*********************************************************************************************************************************/
65/**
66 * VMNET driver instance data.
67 *
68 * @implements PDMINETWORKUP
69 * @implements PDMINETWORKCONFIG
70 */
71typedef struct DRVVMNET
72{
73 /** The network interface. */
74 PDMINETWORKUP INetworkUp;
75 /** The port we're attached to. */
76 PPDMINETWORKDOWN pIAboveNet;
77 /** The config port interface we're attached to. */
78 PPDMINETWORKCONFIG pIAboveConfig;
79 /** Pointer to the driver instance. */
80 PPDMDRVINS pDrvIns;
81 /** For when we're the leaf driver. */
82 RTCRITSECT XmitLock;
83 /** VMNET interface queue handle. */
84 dispatch_queue_t InterfaceQueue;
85 /** VMNET interface handle. */
86 interface_ref Interface;
87 /** The unique id for this network. */
88 uuid_t uuid;
89 /** The operation mode: bridged or host. */
90 uint32_t uMode;
91 /** The host interface name for bridge mode. */
92 char szHostInterface[VMNET_MAX_HOST_INTERFACE_NAME_LENGTH];
93 /** The network mask for host mode. */
94 char szNetworkMask[VMNET_MAX_IP_ADDRESS_STRING_LENGTH];
95 /** The lower IP address of DHCP range for host mode. */
96 char szLowerIP[VMNET_MAX_IP_ADDRESS_STRING_LENGTH];
97 /** The upper IP address of DHCP range for host mode. */
98 char szUpperIP[VMNET_MAX_IP_ADDRESS_STRING_LENGTH];
99} DRVVMNET, *PDRVVMNET;
100
101
102
103/**
104 * @interface_method_impl{PDMINETWORKUP,pfnBeginXmit}
105 */
106static DECLCALLBACK(int) drvVMNetUp_BeginXmit(PPDMINETWORKUP pInterface, bool fOnWorkerThread)
107{
108 RT_NOREF(fOnWorkerThread);
109 PDRVVMNET pThis = RT_FROM_MEMBER(pInterface, DRVVMNET, INetworkUp);
110 LogFlow(("drvVMNetUp_BeginXmit:\n"));
111 int rc = RTCritSectTryEnter(&pThis->XmitLock);
112 if (RT_UNLIKELY(rc == VERR_SEM_BUSY))
113 rc = VERR_TRY_AGAIN;
114 return rc;
115}
116
117
118/**
119 * @interface_method_impl{PDMINETWORKUP,pfnAllocBuf}
120 */
121static DECLCALLBACK(int) drvVMNetUp_AllocBuf(PPDMINETWORKUP pInterface, size_t cbMin,
122 PCPDMNETWORKGSO pGso, PPPDMSCATTERGATHER ppSgBuf)
123{
124 RT_NOREF(pInterface);
125 //PDRVVMNET pThis = RT_FROM_MEMBER(pInterface, DRVVMNET, INetworkUp);
126 LogFlow(("drvVMNetUp_AllocBuf: cb=%llu%s\n", cbMin, pGso == NULL ? "" : " GSO"));
127 /*
128 * Allocate a scatter / gather buffer descriptor that is immediately
129 * followed by the buffer space of its single segment. The GSO context
130 * comes after that again.
131 */
132 PPDMSCATTERGATHER pSgBuf = (PPDMSCATTERGATHER)RTMemAlloc( RT_ALIGN_Z(sizeof(*pSgBuf), 16)
133 + RT_ALIGN_Z(cbMin, 16)
134 + (pGso ? RT_ALIGN_Z(sizeof(*pGso), 16) : 0));
135 if (!pSgBuf)
136 return VERR_NO_MEMORY;
137
138 /*
139 * Initialize the S/G buffer and return.
140 */
141 pSgBuf->fFlags = PDMSCATTERGATHER_FLAGS_MAGIC | PDMSCATTERGATHER_FLAGS_OWNER_1;
142 pSgBuf->cbUsed = 0;
143 pSgBuf->cbAvailable = RT_ALIGN_Z(cbMin, 16);
144 pSgBuf->pvAllocator = NULL;
145 if (!pGso)
146 pSgBuf->pvUser = NULL;
147 else
148 {
149 pSgBuf->pvUser = (uint8_t *)(pSgBuf + 1) + pSgBuf->cbAvailable;
150 *(PPDMNETWORKGSO)pSgBuf->pvUser = *pGso;
151 }
152 pSgBuf->cSegs = 1;
153 pSgBuf->aSegs[0].cbSeg = pSgBuf->cbAvailable;
154 pSgBuf->aSegs[0].pvSeg = pSgBuf + 1;
155
156 LogFlow(("drvVMNetUp_AllocBuf: successful %p\n", pSgBuf));
157 *ppSgBuf = pSgBuf;
158 return VINF_SUCCESS;
159}
160
161
162/**
163 * @interface_method_impl{PDMINETWORKUP,pfnFreeBuf}
164 */
165static DECLCALLBACK(int) drvVMNetUp_FreeBuf(PPDMINETWORKUP pInterface, PPDMSCATTERGATHER pSgBuf)
166{
167 PDRVVMNET pThis = RT_FROM_MEMBER(pInterface, DRVVMNET, INetworkUp);
168 LogFlow(("drvVMNetUp_FreeBuf: %p\n", pSgBuf));
169 Assert(RTCritSectIsOwner(&pThis->XmitLock));
170 if (pSgBuf)
171 {
172 Assert((pSgBuf->fFlags & PDMSCATTERGATHER_FLAGS_MAGIC_MASK) == PDMSCATTERGATHER_FLAGS_MAGIC);
173 pSgBuf->fFlags = 0;
174 RTMemFree(pSgBuf);
175 }
176 return VINF_SUCCESS;
177}
178
179
180static int drvVMNetReceive(PDRVVMNET pThis, const uint8_t *pbFrame, uint32_t cbFrame)
181{
182 Log(("drvVMNetReceive: Incoming packet: %RTmac <= %RTmac (%d bytes)\n", pbFrame, pbFrame + 6, cbFrame));
183 Log2(("%.*Rhxd\n", cbFrame, pbFrame));
184 if (pThis->pIAboveNet && pThis->pIAboveNet->pfnReceive)
185 return pThis->pIAboveNet->pfnReceive(pThis->pIAboveNet, pbFrame, cbFrame);
186 return VERR_TRY_AGAIN;
187}
188
189
190static int drvVMNetSend(PDRVVMNET pThis, const uint8_t *pbFrame, uint32_t cbFrame)
191{
192 Log(("drvVMNetSend: Outgoing packet (%d bytes)\n", cbFrame));
193 Log2(("%.*Rhxd\n", cbFrame, pbFrame));
194
195 struct iovec io;
196 struct vmpktdesc packets;
197 int packet_count = 1;
198
199 io.iov_base = (void*)pbFrame;
200 io.iov_len = cbFrame;
201 packets.vm_pkt_size = cbFrame;
202 packets.vm_pkt_iov = &io;
203 packets.vm_pkt_iovcnt = 1;
204 packets.vm_flags = 0;
205
206 vmnet_return_t rc = vmnet_write(pThis->Interface, &packets, &packet_count);
207 if (rc != VMNET_SUCCESS)
208 Log(("drvVMNetSend: Failed to send a packet with error code %d\n", rc));
209 return (rc == VMNET_SUCCESS) ? VINF_SUCCESS : VERR_GENERAL_FAILURE;
210}
211
212/**
213 * @interface_method_impl{PDMINETWORKUP,pfnSendBuf}
214 */
215static DECLCALLBACK(int) drvVMNetUp_SendBuf(PPDMINETWORKUP pInterface, PPDMSCATTERGATHER pSgBuf, bool fOnWorkerThread)
216{
217 RT_NOREF(fOnWorkerThread);
218 PDRVVMNET pThis = RT_FROM_MEMBER(pInterface, DRVVMNET, INetworkUp);
219
220 LogFlow(("drvVMNetUp_SendBuf: %p\n", pSgBuf));
221 Assert(RTCritSectIsOwner(&pThis->XmitLock));
222
223 int rc;
224 if (!pSgBuf->pvUser)
225 {
226 rc = drvVMNetSend(pThis, pSgBuf->aSegs[0].pvSeg, pSgBuf->cbUsed);
227 }
228 else
229 {
230 uint8_t abHdrScratch[256];
231 uint8_t const *pbFrame = (uint8_t const *)pSgBuf->aSegs[0].pvSeg;
232 PCPDMNETWORKGSO pGso = (PCPDMNETWORKGSO)pSgBuf->pvUser;
233 uint32_t const cSegs = PDMNetGsoCalcSegmentCount(pGso, pSgBuf->cbUsed); Assert(cSegs > 1);
234 rc = VINF_SUCCESS;
235 for (uint32_t iSeg = 0; iSeg < cSegs && RT_SUCCESS(rc); iSeg++)
236 {
237 uint32_t cbSegFrame;
238 void *pvSegFrame = PDMNetGsoCarveSegmentQD(pGso, (uint8_t *)pbFrame, pSgBuf->cbUsed, abHdrScratch,
239 iSeg, cSegs, &cbSegFrame);
240 rc = drvVMNetSend(pThis, pvSegFrame, cbSegFrame);
241 }
242 }
243
244 LogFlow(("drvVMNetUp_SendBuf: free %p\n", pSgBuf));
245 pSgBuf->fFlags = 0;
246 RTMemFree(pSgBuf);
247 return rc;
248}
249
250
251/**
252 * @interface_method_impl{PDMINETWORKUP,pfnEndXmit}
253 */
254static DECLCALLBACK(void) drvVMNetUp_EndXmit(PPDMINETWORKUP pInterface)
255{
256 LogFlow(("drvVMNetUp_EndXmit:\n"));
257 PDRVVMNET pThis = RT_FROM_MEMBER(pInterface, DRVVMNET, INetworkUp);
258 RTCritSectLeave(&pThis->XmitLock);
259}
260
261
262/**
263 * @interface_method_impl{PDMINETWORKUP,pfnSetPromiscuousMode}
264 */
265static DECLCALLBACK(void) drvVMNetUp_SetPromiscuousMode(PPDMINETWORKUP pInterface, bool fPromiscuous)
266{
267 RT_NOREF(pInterface);
268 LogFlow(("drvVMNetUp_SetPromiscuousMode: fPromiscuous=%d\n", fPromiscuous));
269 // PDRVVMNET pThis = RT_FROM_MEMBER(pInterface, DRVVMNET, INetworkUp);
270}
271
272
273/**
274 * @interface_method_impl{PDMINETWORKUP,pfnNotifyLinkChanged}
275 */
276static DECLCALLBACK(void) drvVMNetUp_NotifyLinkChanged(PPDMINETWORKUP pInterface, PDMNETWORKLINKSTATE enmLinkState)
277{
278 RT_NOREF(pInterface);
279 LogFlow(("drvVMNetUp_NotifyLinkChanged: enmLinkState=%d\n", enmLinkState));
280 // PDRVVMNET pThis = RT_FROM_MEMBER(pInterface, DRVVMNET, INetworkUp);
281}
282
283
284/**
285 * @interface_method_impl{PDMIBASE,pfnQueryInterface}
286 */
287static DECLCALLBACK(void *) drvVMNetQueryInterface(PPDMIBASE pInterface, const char *pszIID)
288{
289 PPDMDRVINS pDrvIns = PDMIBASE_2_PDMDRV(pInterface);
290 PDRVVMNET pThis = PDMINS_2_DATA(pDrvIns, PDRVVMNET);
291 PDMIBASE_RETURN_INTERFACE(pszIID, PDMIBASE, &pDrvIns->IBase);
292 PDMIBASE_RETURN_INTERFACE(pszIID, PDMINETWORKUP, &pThis->INetworkUp);
293 //PDMIBASE_RETURN_INTERFACE(pszIID, PDMINETWORKVMNETCONFIG, &pThis->INetworkVmnetConfig);
294 return NULL;
295}
296
297
298static vmnet_return_t drvVMNetAttach(PDRVVMNET pThis)
299{
300 xpc_object_t interface_desc;
301 dispatch_semaphore_t operation_done;
302 __block vmnet_return_t vmnet_status = VMNET_SUCCESS;
303 __block size_t max_packet_size = 0;
304 //__block RTMAC MacAddress;
305
306 pThis->InterfaceQueue = dispatch_queue_create("VMNET", DISPATCH_QUEUE_SERIAL);
307 operation_done = dispatch_semaphore_create(0);
308 interface_desc = xpc_dictionary_create(NULL, NULL, 0);
309 xpc_dictionary_set_uuid(interface_desc, vmnet_interface_id_key, pThis->uuid);
310 xpc_dictionary_set_bool(interface_desc, vmnet_allocate_mac_address_key, false);
311 xpc_dictionary_set_uint64(interface_desc, vmnet_operation_mode_key, pThis->uMode);
312 if (pThis->uMode == VMNET_BRIDGED_MODE)
313 {
314 LogFlow(("drvVMNetAttach: mode=briged hostInterface='%s'\n", pThis->szHostInterface));
315 xpc_dictionary_set_string(interface_desc, vmnet_shared_interface_name_key, pThis->szHostInterface);
316 }
317 else
318 {
319#ifdef LOG_ENABLED
320 char szUUID[40];
321 uuid_unparse(pThis->uuid, szUUID);
322 LogFlow(("drvVMNetAttach: mode=host id='%s' netmask='%s' start='%s' end='%s'\n", szUUID, pThis->szNetworkMask, pThis->szLowerIP, pThis->szUpperIP));
323#endif
324 xpc_dictionary_set_string(interface_desc, vmnet_subnet_mask_key, pThis->szNetworkMask);
325 xpc_dictionary_set_string(interface_desc, vmnet_start_address_key, pThis->szLowerIP);
326 xpc_dictionary_set_string(interface_desc, vmnet_end_address_key, pThis->szUpperIP);
327 }
328 pThis->Interface = vmnet_start_interface(interface_desc, pThis->InterfaceQueue,
329 ^(vmnet_return_t status, xpc_object_t interface_param)
330 {
331 // Log(("Callback reached!\n"));
332 vmnet_status = status;
333 if (status != VMNET_SUCCESS)
334 Log(("Failed to start VMNET interface. Status = %d.\n", status));
335 else if (interface_param == NULL)
336 Log(("No interface parameters provided!\n"));
337 else
338 {
339 Log(("VMNET interface has been started. Status = %d.\n", status));
340#if 0
341 const char *pcszMacAddress = xpc_dictionary_get_string(interface_param, vmnet_mac_address_key);
342 int rc = VERR_NOT_FOUND;
343 if (pcszMacAddress)
344 rc = RTNetStrToMacAddr(pcszMacAddress, &pThis->MacAddress);
345 if (RT_FAILURE(rc))
346 Log(("drvVMNetAttachBridged: Failed to convert '%s' to MAC address (%Rrc)\n", pcszMacAddress ? pcszMacAddress : "(null)", rc));
347#endif
348 max_packet_size = xpc_dictionary_get_uint64(interface_param, vmnet_max_packet_size_key);
349 // Log(("MAC address: %s\n", xpc_dictionary_get_string(interface_param, vmnet_mac_address_key)));
350 Log(("Max packet size: %zu\n", max_packet_size));
351 Log(("MTU size: %llu\n", xpc_dictionary_get_uint64(interface_param, vmnet_mtu_key)));
352 Log(("Avaliable keys:\n"));
353 xpc_dictionary_apply(interface_param, ^bool(const char * _Nonnull key, xpc_object_t _Nonnull value) {
354 Log(("%s=%s\n", key, value));
355 return true;
356 });
357 }
358 dispatch_semaphore_signal(operation_done);
359 });
360 dispatch_semaphore_wait(operation_done, DISPATCH_TIME_FOREVER);
361
362 if (vmnet_status != VMNET_SUCCESS)
363 return vmnet_status;
364
365 if (pThis->Interface == NULL)
366 {
367 Log(("Failed to start VMNET interface with unknown status!\n"));
368 return VMNET_FAILURE;
369 }
370
371 vmnet_interface_set_event_callback(pThis->Interface, VMNET_INTERFACE_PACKETS_AVAILABLE, pThis->InterfaceQueue, ^(interface_event_t event_mask, xpc_object_t _Nonnull event) {
372 if (event_mask & VMNET_INTERFACE_PACKETS_AVAILABLE)
373 {
374 int rc;
375 struct vmpktdesc packets;
376 struct iovec io;
377 int packet_count = (int)xpc_dictionary_get_uint64(event, vmnet_estimated_packets_available_key);
378 if (packet_count == 1)
379 Log3(("Incoming packets available: %d\n", packet_count));
380 else
381 Log(("WARNING! %d incoming packets available, but we will fetch just one.\n", packet_count));
382 packet_count = 1;
383 io.iov_base = malloc(max_packet_size);
384 io.iov_len = max_packet_size;
385 packets.vm_pkt_iov = &io;
386 packets.vm_pkt_iovcnt = 1;
387 packets.vm_pkt_size = max_packet_size;
388 packets.vm_flags = 0;
389 rc = vmnet_read(pThis->Interface, &packets, &packet_count);
390 if (rc != VMNET_SUCCESS)
391 Log(("Failed to read packets\n"));
392 else
393 {
394 Log3(("Successfully read %d packets:\n", packet_count));
395 for (int i = 0; i < packet_count; ++i)
396 {
397 rc = drvVMNetReceive(pThis, io.iov_base, packets.vm_pkt_size);
398 }
399 }
400 free(io.iov_base);
401 }
402 });
403
404 return vmnet_status;
405}
406
407static int drvVMNetDetach(PDRVVMNET pThis)
408{
409 if (pThis->Interface)
410 vmnet_stop_interface(pThis->Interface, pThis->InterfaceQueue, ^(vmnet_return_t status){
411 Log(("VMNET interface has been stopped. Status = %d.\n", status));
412 });
413 if (pThis->InterfaceQueue)
414 dispatch_release(pThis->InterfaceQueue);
415
416 return 0;
417}
418
419
420/**
421 * @interface_method_impl{PDMDRVREG,pfnDestruct}
422 */
423static DECLCALLBACK(void) drvVMNetDestruct(PPDMDRVINS pDrvIns)
424{
425 PDRVVMNET pThis = PDMINS_2_DATA(pDrvIns, PDRVVMNET);
426 PDMDRV_CHECK_VERSIONS_RETURN_VOID(pDrvIns);
427
428 LogFlow(("drvVMNetDestruct: %p\n", pDrvIns));
429 drvVMNetDetach(pThis);
430 if (RTCritSectIsInitialized(&pThis->XmitLock))
431 RTCritSectDelete(&pThis->XmitLock);
432}
433
434
435/**
436 * @interface_method_impl{Construct a NAT network transport driver instance,
437 * PDMDRVREG,pfnDestruct}
438 */
439static DECLCALLBACK(int) drvVMNetConstruct(PPDMDRVINS pDrvIns, PCFGMNODE pCfg, uint32_t fFlags)
440{
441 RT_NOREF(fFlags);
442 PDRVVMNET pThis = PDMINS_2_DATA(pDrvIns, PDRVVMNET);
443 LogFlow(("drvVMNetConstruct: %p\n", pDrvIns));
444 PDMDRV_CHECK_VERSIONS_RETURN(pDrvIns);
445
446 /*
447 * Init the static parts.
448 */
449 pThis->pDrvIns = pDrvIns;
450 /* IBase */
451 pDrvIns->IBase.pfnQueryInterface = drvVMNetQueryInterface;
452 /* INetworkUp */
453 pThis->INetworkUp.pfnBeginXmit = drvVMNetUp_BeginXmit;
454 pThis->INetworkUp.pfnAllocBuf = drvVMNetUp_AllocBuf;
455 pThis->INetworkUp.pfnFreeBuf = drvVMNetUp_FreeBuf;
456 pThis->INetworkUp.pfnSendBuf = drvVMNetUp_SendBuf;
457 pThis->INetworkUp.pfnEndXmit = drvVMNetUp_EndXmit;
458 pThis->INetworkUp.pfnSetPromiscuousMode = drvVMNetUp_SetPromiscuousMode;
459 pThis->INetworkUp.pfnNotifyLinkChanged = drvVMNetUp_NotifyLinkChanged;
460
461 /*
462 * Create the locks.
463 */
464 int rc = RTCritSectInit(&pThis->XmitLock);
465 AssertRCReturn(rc, rc);
466
467 /*
468 * Validate the config.
469 */
470 PDMDRV_VALIDATE_CONFIG_RETURN(pDrvIns,
471 "Network"
472 "|Id"
473 "|Trunk"
474 "|TrunkType"
475 "|NetworkMask"
476 "|LowerIP"
477 "|UpperIP",
478 "");
479
480 /** @cfgm{GUID, string}
481 * The unique id of the VMNET interface.
482 */
483 char szUUID[40];
484 rc = CFGMR3QueryString(pCfg, "Id", szUUID, sizeof(szUUID));
485 if (rc == VERR_CFGM_VALUE_NOT_FOUND)
486 uuid_generate_random(pThis->uuid);
487 else if (RT_FAILURE(rc))
488 return PDMDRV_SET_ERROR(pDrvIns, rc,
489 N_("Configuration error: Failed to get the \"Id\" value"));
490 else if (uuid_parse(szUUID, pThis->uuid))
491 return PDMDrvHlpVMSetError(pDrvIns, VERR_INVALID_PARAMETER, RT_SRC_POS,
492 N_("Configuration error: Invalid \"Id\" value: %s"), szUUID);
493
494 /** @cfgm{TrunkType, uint32_t}
495 * The trunk connection type see INTNETTRUNKTYPE.
496 */
497 uint32_t u32TrunkType;
498 rc = CFGMR3QueryU32(pCfg, "TrunkType", &u32TrunkType);
499 if (RT_FAILURE(rc))
500 return PDMDRV_SET_ERROR(pDrvIns, rc,
501 N_("Configuration error: Failed to get the \"TrunkType\" value"));
502
503 switch ((INTNETTRUNKTYPE)u32TrunkType)
504 {
505 case kIntNetTrunkType_NetAdp:
506 /*
507 * Get the network mask.
508 */
509 rc = CFGMR3QueryString(pCfg, "NetworkMask", pThis->szNetworkMask, sizeof(pThis->szNetworkMask));
510#if 0
511 if (rc == VERR_CFGM_VALUE_NOT_FOUND)
512 {
513 LogRel(("No network mask specified for \"%s\", 255.255.255.0 assumed.\n", pThis->szNetwork))
514 }
515#endif
516 if (RT_FAILURE(rc))
517 return PDMDRV_SET_ERROR(pDrvIns, rc,
518 N_("Configuration error: Failed to get the \"NetworkMask\" value"));
519
520 /*
521 * Get the network mask.
522 */
523 rc = CFGMR3QueryString(pCfg, "LowerIP", pThis->szLowerIP, sizeof(pThis->szLowerIP));
524 if (RT_FAILURE(rc))
525 return PDMDRV_SET_ERROR(pDrvIns, rc,
526 N_("Configuration error: Failed to get the \"LowerIP\" value"));
527
528 /*
529 * Get the network mask.
530 */
531 rc = CFGMR3QueryString(pCfg, "UpperIP", pThis->szUpperIP, sizeof(pThis->szUpperIP));
532 if (RT_FAILURE(rc))
533 return PDMDRV_SET_ERROR(pDrvIns, rc,
534 N_("Configuration error: Failed to get the \"UpperIP\" value"));
535
536 pThis->uMode = VMNET_HOST_MODE;
537 LogRel(("VMNet: host network with mask %s (%s to %s)\n", pThis->szNetworkMask, pThis->szLowerIP, pThis->szUpperIP));
538 break;
539
540 case kIntNetTrunkType_NetFlt:
541 /** @cfgm{Trunk, string}
542 * The name of the host interface to use for bridging.
543 */
544 rc = CFGMR3QueryString(pCfg, "Trunk", pThis->szHostInterface, sizeof(pThis->szHostInterface));
545 if (RT_FAILURE(rc))
546 return PDMDRV_SET_ERROR(pDrvIns, rc,
547 N_("Configuration error: Failed to get the \"Trunk\" value"));
548 pThis->uMode = VMNET_BRIDGED_MODE;
549 LogRel(("VMNet: bridge to %s\n", pThis->szHostInterface));
550 break;
551
552 default:
553 return PDMDRV_SET_ERROR(pDrvIns, rc,
554 N_("Configuration error: Unsupported \"TrunkType\" value"));
555 }
556
557 /*
558 * Check that no-one is attached to us.
559 */
560 AssertMsgReturn(PDMDrvHlpNoAttach(pDrvIns) == VERR_PDM_NO_ATTACHED_DRIVER,
561 ("Configuration error: Not possible to attach anything to this driver!\n"),
562 VERR_PDM_DRVINS_NO_ATTACH);
563
564 /*
565 * Query the network port interface.
566 */
567 pThis->pIAboveNet = PDMIBASE_QUERY_INTERFACE(pDrvIns->pUpBase, PDMINETWORKDOWN);
568 if (!pThis->pIAboveNet)
569 {
570 AssertMsgFailed(("Configuration error: the above device/driver didn't export the network port interface!\n"));
571 return VERR_PDM_MISSING_INTERFACE_ABOVE;
572 }
573
574 /*
575 * Query the network config interface.
576 */
577 pThis->pIAboveConfig = PDMIBASE_QUERY_INTERFACE(pDrvIns->pUpBase, PDMINETWORKCONFIG);
578 if (!pThis->pIAboveConfig)
579 {
580 AssertMsgFailed(("Configuration error: the above device/driver didn't export the network config interface!\n"));
581 return VERR_PDM_MISSING_INTERFACE_ABOVE;
582 }
583
584 vmnet_return_t status = drvVMNetAttach(pThis);
585 if (status != VMNET_SUCCESS)
586 return PDMDrvHlpVMSetError(pDrvIns, VERR_INVALID_PARAMETER, RT_SRC_POS,
587 N_("Error: vmnet_start_interface returned %d"), status);
588
589 return VINF_SUCCESS;
590}
591
592
593
594/**
595 * Network sniffer filter driver registration record.
596 */
597const PDMDRVREG g_DrvVMNet =
598{
599 /* u32Version */
600 PDM_DRVREG_VERSION,
601 /* szName */
602 "VMNet",
603 /* szRCMod */
604 "",
605 /* szR0Mod */
606 "",
607 /* pszDescription */
608 "VMNET Filter Driver",
609 /* fFlags */
610 PDM_DRVREG_FLAGS_HOST_BITS_DEFAULT,
611 /* fClass. */
612 PDM_DRVREG_CLASS_NETWORK,
613 /* cMaxInstances */
614 UINT32_MAX,
615 /* cbInstance */
616 sizeof(DRVVMNET),
617 /* pfnConstruct */
618 drvVMNetConstruct,
619 /* pfnDestruct */
620 drvVMNetDestruct,
621 /* pfnRelocate */
622 NULL,
623 /* pfnIOCtl */
624 NULL,
625 /* pfnPowerOn */
626 NULL,
627 /* pfnReset */
628 NULL,
629 /* pfnSuspend */
630 NULL,
631 /* pfnResume */
632 NULL,
633 /* pfnAttach */
634 NULL,
635 /* pfnDetach */
636 NULL,
637 /* pfnPowerOff */
638 NULL,
639 /* pfnSoftReset */
640 NULL,
641 /* u32EndVersion */
642 PDM_DRVREG_VERSION
643};
644
Note: See TracBrowser for help on using the repository browser.

© 2024 Oracle Support Privacy / Do Not Sell My Info Terms of Use Trademark Policy Automated Access Etiquette