VirtualBox

source: vbox/trunk/src/VBox/Devices/Network/DrvNAT.cpp@ 11444

Last change on this file since 11444 was 11284, checked in by vboxsync, 16 years ago

Devices: %Vrc -> %Rrc (just preferred, not mandatory (yet))

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 22.4 KB
Line 
1/** @file
2 *
3 * VBox network devices:
4 * NAT network transport driver
5 */
6
7/*
8 * Copyright (C) 2006-2007 Sun Microsystems, Inc.
9 *
10 * This file is part of VirtualBox Open Source Edition (OSE), as
11 * available from http://www.virtualbox.org. This file is free software;
12 * you can redistribute it and/or modify it under the terms of the GNU
13 * General Public License (GPL) as published by the Free Software
14 * Foundation, in version 2 as it comes in the "COPYING" file of the
15 * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
16 * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
17 *
18 * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa
19 * Clara, CA 95054 USA or visit http://www.sun.com if you need
20 * additional information or have any questions.
21 */
22
23
24/*******************************************************************************
25* Header Files *
26*******************************************************************************/
27#define LOG_GROUP LOG_GROUP_DRV_NAT
28#define __STDC_LIMIT_MACROS
29#define __STDC_CONSTANT_MACROS
30#ifndef VBOX_NAT_SOURCES
31#include "Network/slirp/libslirp.h"
32#else
33#include <sys/types.h>
34#include <sys/socket.h>
35
36#include <netinet/in.h>
37
38#include <errno.h>
39
40#include <unistd.h>
41
42#include <fcntl.h>
43
44#include <string.h>
45
46#include "Network/nat/nat.h"
47#endif
48#include <VBox/pdmdrv.h>
49#include <iprt/assert.h>
50#include <iprt/file.h>
51#include <iprt/string.h>
52#include <iprt/critsect.h>
53#include <iprt/cidr.h>
54
55#include "Builtins.h"
56
57
58/*******************************************************************************
59* Structures and Typedefs *
60*******************************************************************************/
61/**
62 * NAT network transport driver instance data.
63 */
64typedef struct DRVNAT
65{
66 /** The network interface. */
67 PDMINETWORKCONNECTOR INetworkConnector;
68 /** The port we're attached to. */
69 PPDMINETWORKPORT pPort;
70 /** The network config of the port we're attached to. */
71 PPDMINETWORKCONFIG pConfig;
72 /** Pointer to the driver instance. */
73 PPDMDRVINS pDrvIns;
74 /** Slirp critical section. */
75 RTCRITSECT CritSect;
76 /** Link state */
77 PDMNETWORKLINKSTATE enmLinkState;
78 /** NAT state for this instance. */
79#ifndef VBOX_NAT_SOURCES
80 PNATState pNATState;
81#endif
82 /** TFTP directory prefix. */
83 char *pszTFTPPrefix;
84 /** Boot file name to provide in the DHCP server response. */
85 char *pszBootFile;
86} DRVNAT, *PDRVNAT;
87
88/** Converts a pointer to NAT::INetworkConnector to a PRDVNAT. */
89#define PDMINETWORKCONNECTOR_2_DRVNAT(pInterface) ( (PDRVNAT)((uintptr_t)pInterface - RT_OFFSETOF(DRVNAT, INetworkConnector)) )
90
91
92/*******************************************************************************
93* Global Variables *
94*******************************************************************************/
95#if 0
96/** If set the thread should terminate. */
97static bool g_fThreadTerm = false;
98/** The thread id of the select thread (drvNATSelectThread()). */
99static RTTHREAD g_ThreadSelect;
100#endif
101
102
103/*******************************************************************************
104* Internal Functions *
105*******************************************************************************/
106
107
108#ifdef VBOX_NAT_SOURCES
109/*
110 * Sends data to guest called from NAT glue code
111 */
112static DECLCALLBACK(void) drvNATOutput(const void * data, const uint8_t *msg, size_t size)
113{
114 PDRVNAT pThis = (PDRVNAT)(void *)data;
115 LogFlow(("output: pvBuf=%p cb=%#x\n", msg, size));
116 int rc = pThis->pPort->pfnWaitReceiveAvail(pThis->pPort, 0);
117 if (RT_SUCCESS(rc))
118 pThis->pPort->pfnReceive(pThis->pPort, msg, size);
119 LogFlow(("output: exit\n"));
120}
121
122#endif
123
124/**
125 * Send data to the network.
126 *
127 * @returns VBox status code.
128 * @param pInterface Pointer to the interface structure containing the called function pointer.
129 * @param pvBuf Data to send.
130 * @param cb Number of bytes to send.
131 * @thread EMT
132 */
133static DECLCALLBACK(int) drvNATSend(PPDMINETWORKCONNECTOR pInterface, const void *pvBuf, size_t cb)
134{
135 PDRVNAT pThis = PDMINETWORKCONNECTOR_2_DRVNAT(pInterface);
136
137 LogFlow(("drvNATSend: pvBuf=%p cb=%#x\n", pvBuf, cb));
138 Log2(("drvNATSend: pvBuf=%p cb=%#x\n"
139 "%.*Vhxd\n",
140 pvBuf, cb, cb, pvBuf));
141
142 int rc = RTCritSectEnter(&pThis->CritSect);
143 AssertReleaseRC(rc);
144
145 Assert(pThis->enmLinkState == PDMNETWORKLINKSTATE_UP);
146 if (pThis->enmLinkState == PDMNETWORKLINKSTATE_UP) {
147#ifndef VBOX_NAT_SOURCES
148 slirp_input(pThis->pNATState, (uint8_t *)pvBuf, cb);
149#else
150 ether_chk(pThis, pvBuf, cb);
151#endif
152 }
153 RTCritSectLeave(&pThis->CritSect);
154 LogFlow(("drvNATSend: end\n"));
155 return VINF_SUCCESS;
156}
157
158
159/**
160 * Set promiscuous mode.
161 *
162 * This is called when the promiscuous mode is set. This means that there doesn't have
163 * to be a mode change when it's called.
164 *
165 * @param pInterface Pointer to the interface structure containing the called function pointer.
166 * @param fPromiscuous Set if the adaptor is now in promiscuous mode. Clear if it is not.
167 * @thread EMT
168 */
169static DECLCALLBACK(void) drvNATSetPromiscuousMode(PPDMINETWORKCONNECTOR pInterface, bool fPromiscuous)
170{
171 LogFlow(("drvNATSetPromiscuousMode: fPromiscuous=%d\n", fPromiscuous));
172 /* nothing to do */
173}
174
175
176/**
177 * Notification on link status changes.
178 *
179 * @param pInterface Pointer to the interface structure containing the called function pointer.
180 * @param enmLinkState The new link state.
181 * @thread EMT
182 */
183static DECLCALLBACK(void) drvNATNotifyLinkChanged(PPDMINETWORKCONNECTOR pInterface, PDMNETWORKLINKSTATE enmLinkState)
184{
185 PDRVNAT pThis = PDMINETWORKCONNECTOR_2_DRVNAT(pInterface);
186
187 LogFlow(("drvNATNotifyLinkChanged: enmLinkState=%d\n", enmLinkState));
188
189 int rc = RTCritSectEnter(&pThis->CritSect);
190 AssertReleaseRC(rc);
191 pThis->enmLinkState = enmLinkState;
192
193 switch (enmLinkState)
194 {
195 case PDMNETWORKLINKSTATE_UP:
196 LogRel(("NAT: link up\n"));
197#ifndef VBOX_NAT_SOURCES
198 slirp_link_up(pThis->pNATState);
199#endif
200 break;
201
202 case PDMNETWORKLINKSTATE_DOWN:
203 case PDMNETWORKLINKSTATE_DOWN_RESUME:
204 LogRel(("NAT: link down\n"));
205#ifndef VBOX_NAT_SOURCES
206 slirp_link_down(pThis->pNATState);
207#endif
208 break;
209
210 default:
211 AssertMsgFailed(("drvNATNotifyLinkChanged: unexpected link state %d\n", enmLinkState));
212 }
213 RTCritSectLeave(&pThis->CritSect);
214}
215
216
217/**
218 * Poller callback.
219 */
220static DECLCALLBACK(void) drvNATPoller(PPDMDRVINS pDrvIns)
221{
222 PDRVNAT pThis = PDMINS_2_DATA(pDrvIns, PDRVNAT);
223 fd_set ReadFDs;
224 fd_set WriteFDs;
225 fd_set XcptFDs;
226 int cFDs = -1;
227 FD_ZERO(&ReadFDs);
228 FD_ZERO(&WriteFDs);
229 FD_ZERO(&XcptFDs);
230
231 int rc = RTCritSectEnter(&pThis->CritSect);
232 AssertReleaseRC(rc);
233
234#ifndef VBOX_NAT_SOURCES
235 slirp_select_fill(pThis->pNATState, &cFDs, &ReadFDs, &WriteFDs, &XcptFDs);
236#else
237 nat_select_fill(NULL, &cFDs, &ReadFDs, &WriteFDs, &XcptFDs);
238#endif
239
240 struct timeval tv = {0, 0}; /* no wait */
241 int cReadFDs = select(cFDs + 1, &ReadFDs, &WriteFDs, &XcptFDs, &tv);
242#ifndef VBOX_NAT_SOURCES
243 if (cReadFDs >= 0)
244 slirp_select_poll(pThis->pNATState, &ReadFDs, &WriteFDs, &XcptFDs);
245#else
246 if (cReadFDs >= 0) {
247 nat_select_poll(pThis, &ReadFDs, &WriteFDs, &XcptFDs);
248 }
249#endif
250
251 RTCritSectLeave(&pThis->CritSect);
252}
253
254#ifndef VBOX_NAT_SOURCES
255/**
256 * Function called by slirp to check if it's possible to feed incoming data to the network port.
257 * @returns 1 if possible.
258 * @returns 0 if not possible.
259 */
260int slirp_can_output(void *pvUser)
261{
262 PDRVNAT pThis = (PDRVNAT)pvUser;
263
264 Assert(pThis);
265
266 /** Happens during termination */
267 if (!RTCritSectIsOwner(&pThis->CritSect))
268 return 0;
269
270 int rc = pThis->pPort->pfnWaitReceiveAvail(pThis->pPort, 0);
271 return RT_SUCCESS(rc);
272}
273
274
275/**
276 * Function called by slirp to feed incoming data to the network port.
277 */
278void slirp_output(void *pvUser, const uint8_t *pu8Buf, int cb)
279{
280 PDRVNAT pThis = (PDRVNAT)pvUser;
281
282 LogFlow(("slirp_output BEGIN %x %d\n", pu8Buf, cb));
283 Log2(("slirp_output: pu8Buf=%p cb=%#x (pThis=%p)\n"
284 "%.*Vhxd\n",
285 pu8Buf, cb, pThis,
286 cb, pu8Buf));
287
288 Assert(pThis);
289
290 /** Happens during termination */
291 if (!RTCritSectIsOwner(&pThis->CritSect))
292 return;
293
294 int rc = pThis->pPort->pfnReceive(pThis->pPort, pu8Buf, cb);
295 AssertRC(rc);
296 LogFlow(("slirp_output END %x %d\n", pu8Buf, cb));
297}
298#endif
299
300/**
301 * Queries an interface to the driver.
302 *
303 * @returns Pointer to interface.
304 * @returns NULL if the interface was not supported by the driver.
305 * @param pInterface Pointer to this interface structure.
306 * @param enmInterface The requested interface identification.
307 * @thread Any thread.
308 */
309static DECLCALLBACK(void *) drvNATQueryInterface(PPDMIBASE pInterface, PDMINTERFACE enmInterface)
310{
311 PPDMDRVINS pDrvIns = PDMIBASE_2_PDMDRV(pInterface);
312 PDRVNAT pThis = PDMINS_2_DATA(pDrvIns, PDRVNAT);
313 switch (enmInterface)
314 {
315 case PDMINTERFACE_BASE:
316 return &pDrvIns->IBase;
317 case PDMINTERFACE_NETWORK_CONNECTOR:
318 return &pThis->INetworkConnector;
319 default:
320 return NULL;
321 }
322}
323
324
325/**
326 * Destruct a driver instance.
327 *
328 * Most VM resources are freed by the VM. This callback is provided so that any non-VM
329 * resources can be freed correctly.
330 *
331 * @param pDrvIns The driver instance data.
332 */
333static DECLCALLBACK(void) drvNATDestruct(PPDMDRVINS pDrvIns)
334{
335 PDRVNAT pThis = PDMINS_2_DATA(pDrvIns, PDRVNAT);
336
337 LogFlow(("drvNATDestruct:\n"));
338
339 int rc = RTCritSectEnter(&pThis->CritSect);
340 AssertReleaseRC(rc);
341#ifndef VBOX_NAT_SOURCES
342 slirp_term(pThis->pNATState);
343 pThis->pNATState = NULL;
344#endif
345 RTCritSectLeave(&pThis->CritSect);
346
347 RTCritSectDelete(&pThis->CritSect);
348}
349
350
351/**
352 * Sets up the redirectors.
353 *
354 * @returns VBox status code.
355 * @param pCfgHandle The drivers configuration handle.
356 */
357static int drvNATConstructRedir(unsigned iInstance, PDRVNAT pThis, PCFGMNODE pCfgHandle, RTIPV4ADDR Network)
358{
359#ifndef VBOX_NAT_SOURCES
360 /*
361 * Enumerate redirections.
362 */
363 for (PCFGMNODE pNode = CFGMR3GetFirstChild(pCfgHandle); pNode; pNode = CFGMR3GetNextChild(pNode))
364 {
365 /*
366 * Validate the port forwarding config.
367 */
368 if (!CFGMR3AreValuesValid(pNode, "Protocol\0UDP\0HostPort\0GuestPort\0GuestIP\0"))
369 return PDMDRV_SET_ERROR(pThis->pDrvIns, VERR_PDM_DRVINS_UNKNOWN_CFG_VALUES, N_("Unknown configuration in port forwarding"));
370
371 /* protocol type */
372 bool fUDP;
373 char szProtocol[32];
374 int rc = CFGMR3QueryString(pNode, "Protocol", &szProtocol[0], sizeof(szProtocol));
375 if (rc == VERR_CFGM_VALUE_NOT_FOUND)
376 {
377 rc = CFGMR3QueryBool(pNode, "UDP", &fUDP);
378 if (rc == VERR_CFGM_VALUE_NOT_FOUND)
379 fUDP = false;
380 else if (RT_FAILURE(rc))
381 return PDMDrvHlpVMSetError(pThis->pDrvIns, rc, RT_SRC_POS, N_("NAT#%d: configuration query for \"UDP\" boolean failed"), iInstance);
382 }
383 else if (RT_SUCCESS(rc))
384 {
385 if (!RTStrICmp(szProtocol, "TCP"))
386 fUDP = false;
387 else if (!RTStrICmp(szProtocol, "UDP"))
388 fUDP = true;
389 else
390 return PDMDrvHlpVMSetError(pThis->pDrvIns, VERR_INVALID_PARAMETER, RT_SRC_POS, N_("NAT#%d: Invalid configuration value for \"Protocol\": \"%s\""), iInstance, szProtocol);
391 }
392 else
393 return PDMDrvHlpVMSetError(pThis->pDrvIns, rc, RT_SRC_POS, N_("NAT#%d: configuration query for \"Protocol\" string failed"), iInstance);
394
395 /* host port */
396 int32_t iHostPort;
397 rc = CFGMR3QueryS32(pNode, "HostPort", &iHostPort);
398 if (RT_FAILURE(rc))
399 return PDMDrvHlpVMSetError(pThis->pDrvIns, rc, RT_SRC_POS, N_("NAT#%d: configuration query for \"HostPort\" integer failed"), iInstance);
400
401 /* guest port */
402 int32_t iGuestPort;
403 rc = CFGMR3QueryS32(pNode, "GuestPort", &iGuestPort);
404 if (RT_FAILURE(rc))
405 return PDMDrvHlpVMSetError(pThis->pDrvIns, rc, RT_SRC_POS, N_("NAT#%d: configuration query for \"GuestPort\" integer failed"), iInstance);
406
407 /* guest address */
408 char szGuestIP[32];
409 rc = CFGMR3QueryString(pNode, "GuestIP", &szGuestIP[0], sizeof(szGuestIP));
410 if (rc == VERR_CFGM_VALUE_NOT_FOUND)
411 RTStrPrintf(szGuestIP, sizeof(szGuestIP), "%d.%d.%d.%d",
412 (Network & 0xFF000000) >> 24, (Network & 0xFF0000) >> 16, (Network & 0xFF00) >> 8, (Network & 0xE0) | 15);
413 else if (RT_FAILURE(rc))
414 return PDMDrvHlpVMSetError(pThis->pDrvIns, rc, RT_SRC_POS, N_("NAT#%d: configuration query for \"GuestIP\" string failed"), iInstance);
415 struct in_addr GuestIP;
416 if (!inet_aton(szGuestIP, &GuestIP))
417 return PDMDrvHlpVMSetError(pThis->pDrvIns, VERR_NAT_REDIR_GUEST_IP, RT_SRC_POS, N_("NAT#%d: configuration error: invalid \"GuestIP\"=\"%s\", inet_aton failed"), iInstance, szGuestIP);
418
419 /*
420 * Call slirp about it.
421 */
422 Log(("drvNATConstruct: Redir %d -> %s:%d\n", iHostPort, szGuestIP, iGuestPort));
423 if (slirp_redir(pThis->pNATState, fUDP, iHostPort, GuestIP, iGuestPort) < 0)
424 return PDMDrvHlpVMSetError(pThis->pDrvIns, VERR_NAT_REDIR_SETUP, RT_SRC_POS, N_("NAT#%d: configuration error: failed to set up redirection of %d to %s:%d. Probably a conflict with existing services or other rules"), iInstance, iHostPort, szGuestIP, iGuestPort);
425 } /* for each redir rule */
426#endif
427
428 return VINF_SUCCESS;
429}
430
431/**
432 * Get the MAC address into the slirp stack.
433 */
434static void drvNATSetMac(PDRVNAT pThis)
435{
436#ifndef VBOX_NAT_SOURCES
437 if (pThis->pConfig)
438 {
439 RTMAC Mac;
440 pThis->pConfig->pfnGetMac(pThis->pConfig, &Mac);
441 slirp_set_ethaddr(pThis->pNATState, Mac.au8);
442 }
443#endif
444}
445
446
447/**
448 * After loading we have to pass the MAC address of the ethernet device to the slirp stack.
449 * Otherwise the guest is not reachable until it performs a DHCP request or an ARP request
450 * (usually done during guest boot).
451 */
452static DECLCALLBACK(int) drvNATLoadDone(PPDMDRVINS pDrvIns, PSSMHANDLE pSSMHandle)
453{
454 PDRVNAT pThis = PDMINS_2_DATA(pDrvIns, PDRVNAT);
455 drvNATSetMac(pThis);
456 return VINF_SUCCESS;
457}
458
459
460/**
461 * Some guests might not use DHCP to retrieve an IP but use a static IP.
462 */
463static DECLCALLBACK(void) drvNATPowerOn(PPDMDRVINS pDrvIns)
464{
465 PDRVNAT pThis = PDMINS_2_DATA(pDrvIns, PDRVNAT);
466 drvNATSetMac(pThis);
467}
468
469
470/**
471 * Construct a NAT network transport driver instance.
472 *
473 * @returns VBox status.
474 * @param pDrvIns The driver instance data.
475 * If the registration structure is needed, pDrvIns->pDrvReg points to it.
476 * @param pCfgHandle Configuration node handle for the driver. Use this to obtain the configuration
477 * of the driver instance. It's also found in pDrvIns->pCfgHandle, but like
478 * iInstance it's expected to be used a bit in this function.
479 */
480static DECLCALLBACK(int) drvNATConstruct(PPDMDRVINS pDrvIns, PCFGMNODE pCfgHandle)
481{
482 PDRVNAT pThis = PDMINS_2_DATA(pDrvIns, PDRVNAT);
483 char szNetAddr[16];
484 char szNetwork[32]; /* xxx.xxx.xxx.xxx/yy */
485 LogFlow(("drvNATConstruct:\n"));
486
487 /*
488 * Validate the config.
489 */
490 if (!CFGMR3AreValuesValid(pCfgHandle, "PassDomain\0TFTPPrefix\0BootFile\0Network\0"))
491 return PDMDRV_SET_ERROR(pDrvIns, VERR_PDM_DRVINS_UNKNOWN_CFG_VALUES, N_("Unknown NAT configuration option, only supports PassDomain, TFTPPrefix, BootFile and Network"));
492
493 /*
494 * Init the static parts.
495 */
496 pThis->pDrvIns = pDrvIns;
497#ifndef VBOX_NAT_SOURCES
498 pThis->pNATState = NULL;
499#endif
500 pThis->pszTFTPPrefix = NULL;
501 pThis->pszBootFile = NULL;
502 /* IBase */
503 pDrvIns->IBase.pfnQueryInterface = drvNATQueryInterface;
504 /* INetwork */
505 pThis->INetworkConnector.pfnSend = drvNATSend;
506 pThis->INetworkConnector.pfnSetPromiscuousMode = drvNATSetPromiscuousMode;
507 pThis->INetworkConnector.pfnNotifyLinkChanged = drvNATNotifyLinkChanged;
508
509 /*
510 * Get the configuration settings.
511 */
512 bool fPassDomain = true;
513 int rc = CFGMR3QueryBool(pCfgHandle, "PassDomain", &fPassDomain);
514 if (rc == VERR_CFGM_VALUE_NOT_FOUND)
515 fPassDomain = true;
516 else if (RT_FAILURE(rc))
517 return PDMDrvHlpVMSetError(pDrvIns, rc, RT_SRC_POS, N_("NAT#%d: configuration query for \"PassDomain\" boolean failed"), pDrvIns->iInstance);
518
519 rc = CFGMR3QueryStringAlloc(pCfgHandle, "TFTPPrefix", &pThis->pszTFTPPrefix);
520 if (RT_FAILURE(rc) && rc != VERR_CFGM_VALUE_NOT_FOUND)
521 return PDMDrvHlpVMSetError(pDrvIns, rc, RT_SRC_POS, N_("NAT#%d: configuration query for \"TFTPPrefix\" string failed"), pDrvIns->iInstance);
522 rc = CFGMR3QueryStringAlloc(pCfgHandle, "BootFile", &pThis->pszBootFile);
523 if (RT_FAILURE(rc) && rc != VERR_CFGM_VALUE_NOT_FOUND)
524 return PDMDrvHlpVMSetError(pDrvIns, rc, RT_SRC_POS, N_("NAT#%d: configuration query for \"BootFile\" string failed"), pDrvIns->iInstance);
525
526 /*
527 * Query the network port interface.
528 */
529 pThis->pPort = (PPDMINETWORKPORT)pDrvIns->pUpBase->pfnQueryInterface(pDrvIns->pUpBase, PDMINTERFACE_NETWORK_PORT);
530 if (!pThis->pPort)
531 return PDMDRV_SET_ERROR(pDrvIns, VERR_PDM_MISSING_INTERFACE_ABOVE,
532 N_("Configuration error: the above device/driver didn't export the network port interface"));
533 pThis->pConfig = (PPDMINETWORKCONFIG)pDrvIns->pUpBase->pfnQueryInterface(pDrvIns->pUpBase, PDMINTERFACE_NETWORK_CONFIG);
534 if (!pThis->pConfig)
535 return PDMDRV_SET_ERROR(pDrvIns, VERR_PDM_MISSING_INTERFACE_ABOVE,
536 N_("Configuration error: the above device/driver didn't export the network config interface"));
537
538 /* Generate a network address for this network card. */
539 rc = CFGMR3QueryString(pCfgHandle, "Network", szNetwork, sizeof(szNetwork));
540 if (rc == VERR_CFGM_VALUE_NOT_FOUND)
541 RTStrPrintf(szNetwork, sizeof(szNetwork), "10.0.%d.0/24", pDrvIns->iInstance + 2);
542 else if (RT_FAILURE(rc))
543 return PDMDrvHlpVMSetError(pDrvIns, rc, RT_SRC_POS, N_("NAT#%d: configuration query for \"Network\" string failed"), pDrvIns->iInstance);
544
545 RTIPV4ADDR Network;
546 RTIPV4ADDR Netmask;
547 rc = RTCidrStrToIPv4(szNetwork, &Network, &Netmask);
548 if (RT_FAILURE(rc))
549 return PDMDrvHlpVMSetError(pDrvIns, rc, RT_SRC_POS, N_("NAT#%d: Configuration error: network '%s' describes not a valid IPv4 network"), pDrvIns->iInstance, szNetwork);
550
551 RTStrPrintf(szNetAddr, sizeof(szNetAddr), "%d.%d.%d.%d",
552 (Network & 0xFF000000) >> 24, (Network & 0xFF0000) >> 16, (Network & 0xFF00) >> 8, Network & 0xFF);
553
554 /*
555 * The slirp lock..
556 */
557 rc = RTCritSectInit(&pThis->CritSect);
558 if (RT_FAILURE(rc))
559 return rc;
560#if 0
561 rc = RTSemEventCreate(&g_EventSem);
562 if (RT_SUCCESS(rc))
563 {
564 /*
565 * Start the select thread. (it'll block on the sem)
566 */
567 g_fThreadTerm = false;
568 rc = RTThreadCreate(&g_ThreadSelect, drvNATSelectThread, 0, NULL, "NATSEL");
569 if (RT_SUCCESS(rc))
570 {
571#endif
572#ifndef VBOX_NAT_SOURCES
573 /*
574 * Initialize slirp.
575 */
576 rc = slirp_init(&pThis->pNATState, &szNetAddr[0], Netmask, fPassDomain, pThis->pszTFTPPrefix, pThis->pszBootFile, pThis);
577 if (RT_SUCCESS(rc))
578 {
579 int rc2 = drvNATConstructRedir(pDrvIns->iInstance, pThis, pCfgHandle, Network);
580 if (RT_SUCCESS(rc2))
581 {
582 /*
583 * Register a load done notification to get the MAC address into the slirp
584 * engine after we loaded a guest state.
585 */
586 rc2 = PDMDrvHlpSSMRegister(pDrvIns, pDrvIns->pDrvReg->szDriverName,
587 pDrvIns->iInstance, 0, 0,
588 NULL, NULL, NULL, NULL, NULL, drvNATLoadDone);
589 AssertRC(rc2);
590 pDrvIns->pDrvHlp->pfnPDMPollerRegister(pDrvIns, drvNATPoller);
591
592 pThis->enmLinkState = PDMNETWORKLINKSTATE_UP;
593#if 0
594 RTSemEventSignal(g_EventSem);
595 RTThreadSleep(0);
596#endif
597 /* might return VINF_NAT_DNS */
598 return rc;
599 }
600 /* failure path */
601 rc = rc2;
602 slirp_term(pThis->pNATState);
603 pThis->pNATState = NULL;
604 }
605 else
606 {
607 PDMDRV_SET_ERROR(pDrvIns, rc, N_("Unknown error during NAT networking setup: "));
608 AssertMsgFailed(("Add error message for rc=%d (%Rrc)\n", rc, rc));
609 }
610#else
611 pDrvIns->pDrvHlp->pfnPDMPollerRegister(pDrvIns, drvNATPoller);
612 pThis->enmLinkState = PDMNETWORKLINKSTATE_UP;
613 mbuf_init(NULL);
614 struct nat_output_callbacks cb;
615 cb.noc_guest_out = drvNATOutput;
616#if 0
617 cb.noc_host_udp_out = host_udp_out;
618 cb.noc_host_udp_in = host_udp_in;
619#endif
620 nat_init(&cb);
621 ipfw_nat_init();
622#endif
623#if 0
624 g_fThreadTerm = true;
625 RTSemEventSignal(g_EventSem);
626 RTThreadSleep(0);
627 }
628 RTSemEventDestroy(g_EventSem);
629 g_EventSem = NULL;
630 }
631#endif
632#ifndef VBOX_NAT_SOURCES
633 RTCritSectDelete(&pThis->CritSect);
634#endif
635 return rc;
636}
637
638
639
640/**
641 * NAT network transport driver registration record.
642 */
643const PDMDRVREG g_DrvNAT =
644{
645 /* u32Version */
646 PDM_DRVREG_VERSION,
647 /* szDriverName */
648 "NAT",
649 /* pszDescription */
650 "NAT Network Transport Driver",
651 /* fFlags */
652 PDM_DRVREG_FLAGS_HOST_BITS_DEFAULT,
653 /* fClass. */
654 PDM_DRVREG_CLASS_NETWORK,
655 /* cMaxInstances */
656 16,
657 /* cbInstance */
658 sizeof(DRVNAT),
659 /* pfnConstruct */
660 drvNATConstruct,
661 /* pfnDestruct */
662 drvNATDestruct,
663 /* pfnIOCtl */
664 NULL,
665 /* pfnPowerOn */
666 drvNATPowerOn,
667 /* pfnReset */
668 NULL,
669 /* pfnSuspend */
670 NULL,
671 /* pfnResume */
672 NULL,
673 /* pfnDetach */
674 NULL,
675 /* pfnPowerOff */
676 NULL
677};
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