summaryrefslogtreecommitdiff
path: root/src/VBox/Devices/Network
diff options
context:
space:
mode:
authorMichael Meskes <meskes@debian.org>2010-06-04 09:49:50 +0200
committerMichael Meskes <meskes@debian.org>2010-06-04 09:49:50 +0200
commite13debb062071c46f2707d0d0e59c57675b49360 (patch)
tree922f54068563b5cf3274bae8ba8122ce4b4ede1d /src/VBox/Devices/Network
parentabd0051802e55207e88435a185ff8d6e6b8d17d5 (diff)
downloadvirtualbox-upstream/3.2.2-dfsg.tar.gz
Imported Upstream version 3.2.2-dfsgupstream/3.2.2-dfsg
Diffstat (limited to 'src/VBox/Devices/Network')
-rw-r--r--src/VBox/Devices/Network/DevE1000.cpp9
-rw-r--r--src/VBox/Devices/Network/DrvIntNet.cpp84
-rw-r--r--src/VBox/Devices/Network/SrvIntNetR0.cpp130
-rw-r--r--src/VBox/Devices/Network/slirp/bootp.c24
-rw-r--r--src/VBox/Devices/Network/slirp/slirp.c31
-rw-r--r--src/VBox/Devices/Network/slirp/slirp.h4
-rw-r--r--src/VBox/Devices/Network/slirp/slirp_state.h1
-rw-r--r--src/VBox/Devices/Network/slirp/socket.c7
8 files changed, 203 insertions, 87 deletions
diff --git a/src/VBox/Devices/Network/DevE1000.cpp b/src/VBox/Devices/Network/DevE1000.cpp
index b71bc605a..2f3b9f679 100644
--- a/src/VBox/Devices/Network/DevE1000.cpp
+++ b/src/VBox/Devices/Network/DevE1000.cpp
@@ -1,4 +1,4 @@
-/* $Id: DevE1000.cpp 29439 2010-05-13 00:32:18Z vboxsync $ */
+/* $Id: DevE1000.cpp 29685 2010-05-20 11:36:28Z vboxsync $ */
/** @file
* DevE1000 - Intel 82540EM Ethernet Controller Emulation.
*
@@ -2643,7 +2643,12 @@ static int e1kRegWriteRDT(E1KSTATE* pState, uint32_t offset, uint32_t index, uin
e1kCsRxLeave(pState);
if (RT_SUCCESS(rc))
{
-#ifdef IN_RING3 /** @todo bird: Use SUPSem* for this so we can signal it in ring-0 as well. (reduces latency) */
+/** @todo bird: Use SUPSem* for this so we can signal it in ring-0 as well
+ * without requiring any context switches. We should also check the
+ * wait condition before bothering to queue the item as we're currently
+ * queuing thousands of items per second here in a normal transmit
+ * scenario. Expect performance changes when fixing this! */
+#ifdef IN_RING3
/* Signal that we have more receive descriptors avalable. */
e1kWakeupReceive(pState->CTX_SUFF(pDevIns));
#else
diff --git a/src/VBox/Devices/Network/DrvIntNet.cpp b/src/VBox/Devices/Network/DrvIntNet.cpp
index ae3afe4ba..29d66c4db 100644
--- a/src/VBox/Devices/Network/DrvIntNet.cpp
+++ b/src/VBox/Devices/Network/DrvIntNet.cpp
@@ -1,4 +1,4 @@
-/* $Id: DrvIntNet.cpp 29598 2010-05-18 08:32:49Z vboxsync $ */
+/* $Id: DrvIntNet.cpp 29669 2010-05-19 17:42:48Z vboxsync $ */
/** @file
* DrvIntNet - Internal network transport driver.
*/
@@ -1102,34 +1102,31 @@ static DECLCALLBACK(void) drvR3IntNetDestruct(PPDMDRVINS pDrvIns)
PDMDRV_CHECK_VERSIONS_RETURN_VOID(pDrvIns);
/*
- * Indicate to the thread that it's time to quit.
+ * Indicate to the receive thread that it's time to quit.
*/
ASMAtomicXchgSize(&pThis->enmRecvState, RECVSTATE_TERMINATE);
ASMAtomicXchgSize(&pThis->fLinkDown, true);
RTSEMEVENT hRecvEvt = pThis->hRecvEvt;
pThis->hRecvEvt = NIL_RTSEMEVENT;
- /*
- * Close the interface
- */
+ if (hRecvEvt != NIL_RTSEMEVENT)
+ RTSemEventSignal(hRecvEvt);
+
if (pThis->hIf != INTNET_HANDLE_INVALID)
{
- INTNETIFCLOSEREQ CloseReq;
- CloseReq.Hdr.u32Magic = SUPVMMR0REQHDR_MAGIC;
- CloseReq.Hdr.cbReq = sizeof(CloseReq);
- CloseReq.pSession = NIL_RTR0PTR;
- CloseReq.hIf = pThis->hIf;
- pThis->hIf = INTNET_HANDLE_INVALID;
- int rc = PDMDrvHlpSUPCallVMMR0Ex(pDrvIns, VMMR0_DO_INTNET_IF_CLOSE, &CloseReq, sizeof(CloseReq));
+ INTNETIFABORTWAITREQ AbortWaitReq;
+ AbortWaitReq.Hdr.u32Magic = SUPVMMR0REQHDR_MAGIC;
+ AbortWaitReq.Hdr.cbReq = sizeof(AbortWaitReq);
+ AbortWaitReq.pSession = NIL_RTR0PTR;
+ AbortWaitReq.hIf = pThis->hIf;
+ AbortWaitReq.fNoMoreWaits = true;
+ int rc = PDMDrvHlpSUPCallVMMR0Ex(pDrvIns, VMMR0_DO_INTNET_IF_ABORT_WAIT, &AbortWaitReq, sizeof(AbortWaitReq));
AssertRC(rc);
}
/*
- * Wait for the thread to terminate.
+ * Wait for the threads to terminate.
*/
- if (hRecvEvt != NIL_RTSEMEVENT)
- RTSemEventSignal(hRecvEvt);
-
if (pThis->pXmitThread)
{
int rc = PDMR3ThreadDestroy(pThis->pXmitThread, NULL);
@@ -1144,30 +1141,11 @@ static DECLCALLBACK(void) drvR3IntNetDestruct(PPDMDRVINS pDrvIns)
pThis->hRecvThread = NIL_RTTHREAD;
}
-
/*
- * Destroy the semaphores, S/G cache and xmit lock.
+ * Deregister statistics in case we're being detached.
*/
- if (hRecvEvt != NIL_RTSEMEVENT)
- RTSemEventDestroy(hRecvEvt);
-
- if (pThis->hXmitEvt != NIL_SUPSEMEVENT)
- {
- SUPSemEventClose(pThis->pSupDrvSession, pThis->hXmitEvt);
- pThis->hXmitEvt = NIL_SUPSEMEVENT;
- }
-
- RTMemCacheDestroy(pThis->hSgCache);
- pThis->hSgCache = NIL_RTMEMCACHE;
-
- if (PDMCritSectIsInitialized(&pThis->XmitLock))
- PDMR3CritSectDelete(&pThis->XmitLock);
-
if (pThis->pBufR3)
{
- /*
- * Deregister statistics in case we're being detached.
- */
PDMDrvHlpSTAMDeregister(pDrvIns, &pThis->pBufR3->Recv.cStatFrames);
PDMDrvHlpSTAMDeregister(pDrvIns, &pThis->pBufR3->Recv.cbStatWritten);
PDMDrvHlpSTAMDeregister(pDrvIns, &pThis->pBufR3->Recv.cOverflows);
@@ -1185,6 +1163,40 @@ static DECLCALLBACK(void) drvR3IntNetDestruct(PPDMDRVINS pDrvIns)
PDMDrvHlpSTAMDeregister(pDrvIns, &pThis->StatTransmit);
#endif
}
+
+ /*
+ * Close the interface
+ */
+ if (pThis->hIf != INTNET_HANDLE_INVALID)
+ {
+ INTNETIFCLOSEREQ CloseReq;
+ CloseReq.Hdr.u32Magic = SUPVMMR0REQHDR_MAGIC;
+ CloseReq.Hdr.cbReq = sizeof(CloseReq);
+ CloseReq.pSession = NIL_RTR0PTR;
+ CloseReq.hIf = pThis->hIf;
+ pThis->hIf = INTNET_HANDLE_INVALID;
+ int rc = PDMDrvHlpSUPCallVMMR0Ex(pDrvIns, VMMR0_DO_INTNET_IF_CLOSE, &CloseReq, sizeof(CloseReq));
+ AssertRC(rc);
+ }
+
+
+ /*
+ * Destroy the semaphores, S/G cache and xmit lock.
+ */
+ if (hRecvEvt != NIL_RTSEMEVENT)
+ RTSemEventDestroy(hRecvEvt);
+
+ if (pThis->hXmitEvt != NIL_SUPSEMEVENT)
+ {
+ SUPSemEventClose(pThis->pSupDrvSession, pThis->hXmitEvt);
+ pThis->hXmitEvt = NIL_SUPSEMEVENT;
+ }
+
+ RTMemCacheDestroy(pThis->hSgCache);
+ pThis->hSgCache = NIL_RTMEMCACHE;
+
+ if (PDMCritSectIsInitialized(&pThis->XmitLock))
+ PDMR3CritSectDelete(&pThis->XmitLock);
}
diff --git a/src/VBox/Devices/Network/SrvIntNetR0.cpp b/src/VBox/Devices/Network/SrvIntNetR0.cpp
index 8338e71ad..9fd7e40e7 100644
--- a/src/VBox/Devices/Network/SrvIntNetR0.cpp
+++ b/src/VBox/Devices/Network/SrvIntNetR0.cpp
@@ -1,4 +1,4 @@
-/* $Id: SrvIntNetR0.cpp 29635 2010-05-18 13:42:54Z vboxsync $ */
+/* $Id: SrvIntNetR0.cpp 29707 2010-05-20 16:49:16Z vboxsync $ */
/** @file
* Internal networking - The ring 0 service.
*/
@@ -220,7 +220,8 @@ typedef struct INTNETIF
/** Whether the interface is active or not.
* This is shadowed by INTNETMACTABENTRY::fActive. */
bool fActive;
- /** Whether someone is currently in the destructor. */
+ /** Whether someone is currently in the destructor or has indicated that
+ * the end is nigh by means of IntNetR0IfAbortWait. */
bool volatile fDestroying;
/** Number of yields done to try make the interface read pending data.
* We will stop yielding when this reaches a threshold assuming that the VM is
@@ -264,6 +265,8 @@ typedef struct INTNETIF
* This is NULL when it's in use as a precaution against unserialized
* transmitting. This is grown when new interfaces are added to the network. */
PINTNETDSTTAB volatile pDstTab;
+ /** Pointer to the trunk's per interface data. Can be NULL. */
+ void *pvIfData;
} INTNETIF;
/** Pointer to an internal network interface. */
typedef INTNETIF *PINTNETIF;
@@ -2474,10 +2477,11 @@ static void intnetR0IfSend(PINTNETIF pIf, PINTNETIF pIfSender, PINTNETSG pSG, PC
* The caller holds the trunk lock.
*
* @param pThis The trunk.
+ * @param pIfSender The IF sending the frame.
* @param pSG Pointer to the gather list.
* @param fDst The destination flags.
*/
-static int intnetR0TrunkIfSendGsoFallback(PINTNETTRUNKIF pThis, PINTNETSG pSG, uint32_t fDst)
+static int intnetR0TrunkIfSendGsoFallback(PINTNETTRUNKIF pThis, PINTNETIF pIfSender, PINTNETSG pSG, uint32_t fDst)
{
/*
* Since we're only using this for GSO frame comming from the internal
@@ -2512,7 +2516,7 @@ static int intnetR0TrunkIfSendGsoFallback(PINTNETTRUNKIF pThis, PINTNETSG pSG, u
u.SG.aSegs[1].pv = (uint8_t *)pSG->aSegs[0].pv + offSegPayload;
u.SG.aSegs[1].cb = (uint32_t)cbSegPayload;
- int rc = pThis->pIfPort->pfnXmit(pThis->pIfPort, &u.SG, fDst);
+ int rc = pThis->pIfPort->pfnXmit(pThis->pIfPort, pIfSender->pvIfData, &u.SG, fDst);
if (RT_FAILURE(rc))
return rc;
}
@@ -2635,9 +2639,9 @@ static void intnetR0TrunkIfSend(PINTNETTRUNKIF pThis, PINTNETNETWORK pNetwork, P
int rc;
if ( pSG->GsoCtx.u8Type == PDMNETWORKGSOTYPE_INVALID
|| intnetR0TrunkIfCanHandleGsoFrame(pThis, pSG, fDst) )
- rc = pThis->pIfPort->pfnXmit(pThis->pIfPort, pSG, fDst);
+ rc = pThis->pIfPort->pfnXmit(pThis->pIfPort, pIfSender->pvIfData, pSG, fDst);
else
- rc = intnetR0TrunkIfSendGsoFallback(pThis, pSG, fDst);
+ rc = intnetR0TrunkIfSendGsoFallback(pThis, pIfSender, pSG, fDst);
/** @todo failure statistics? */
Log2(("intnetR0TrunkIfSend: %Rrc fDst=%d\n", rc, fDst)); NOREF(rc);
@@ -3639,7 +3643,7 @@ INTNETR0DECL(int) IntNetR0IfSetMacAddress(INTNETIFHANDLE hIf, PSUPDRVSESSION pSe
Log(("IntNetR0IfSetMacAddress: pfnNotifyMacAddress hIf=%RX32\n", hIf));
PINTNETTRUNKIFPORT pIfPort = pTrunk->pIfPort;
if (pIfPort)
- pIfPort->pfnNotifyMacAddress(pIfPort, hIf, pMac);
+ pIfPort->pfnNotifyMacAddress(pIfPort, pIf->pvIfData, pMac);
intnetR0BusyDecTrunk(pTrunk);
}
}
@@ -3840,10 +3844,14 @@ INTNETR0DECL(int) IntNetR0IfWait(INTNETIFHANDLE hIf, PSUPDRVSESSION pSession, ui
Log(("IntNetR0IfWait: returns VERR_INVALID_HANDLE\n"));
return VERR_INVALID_HANDLE;
}
- const INTNETIFHANDLE hIfSelf = pIf->hIf;
- const RTSEMEVENT hRecvEvent = pIf->hRecvEvent;
+
+ const INTNETIFHANDLE hIfSelf = pIf->hIf;
+ const RTSEMEVENT hRecvEvent = pIf->hRecvEvent;
+ const bool fDestroying = ASMAtomicReadBool(&pIf->fDestroying);
if ( hIfSelf != hIf /* paranoia */
- && hRecvEvent != NIL_RTSEMEVENT)
+ || hRecvEvent == NIL_RTSEMEVENT
+ || fDestroying
+ )
{
Log(("IntNetR0IfWait: returns VERR_SEM_DESTROYED\n"));
return VERR_SEM_DESTROYED;
@@ -3898,6 +3906,79 @@ INTNETR0DECL(int) IntNetR0IfWaitReq(PSUPDRVSESSION pSession, PINTNETIFWAITREQ pR
/**
+ * Wake up any threads waiting on the interface.
+ *
+ * @returns VBox status code.
+ * @param hIf The interface handle.
+ * @param pSession The caller's session.
+ * @param fNoMoreWaits When set, no more waits are permitted.
+ */
+INTNETR0DECL(int) IntNetR0IfAbortWait(INTNETIFHANDLE hIf, PSUPDRVSESSION pSession, bool fNoMoreWaits)
+{
+ Log4(("IntNetR0IfAbortWait: hIf=%RX32 fNoMoreWaits=%RTbool\n", hIf, fNoMoreWaits));
+
+ /*
+ * Get and validate essential handles.
+ */
+ PINTNET pIntNet = g_pIntNet;
+ AssertPtrReturn(pIntNet, VERR_INVALID_PARAMETER);
+ AssertReturn(pIntNet->u32Magic, VERR_INVALID_MAGIC);
+
+ PINTNETIF pIf = (PINTNETIF)RTHandleTableLookupWithCtx(pIntNet->hHtIfs, hIf, pSession);
+ if (!pIf)
+ {
+ Log(("IntNetR0IfAbortWait: returns VERR_INVALID_HANDLE\n"));
+ return VERR_INVALID_HANDLE;
+ }
+
+ const INTNETIFHANDLE hIfSelf = pIf->hIf;
+ const RTSEMEVENT hRecvEvent = pIf->hRecvEvent;
+ const bool fDestroying = ASMAtomicReadBool(&pIf->fDestroying);
+ if ( hIfSelf != hIf /* paranoia */
+ || hRecvEvent == NIL_RTSEMEVENT
+ || fDestroying
+ )
+ {
+ Log(("IntNetR0IfAbortWait: returns VERR_SEM_DESTROYED\n"));
+ return VERR_SEM_DESTROYED;
+ }
+
+ /*
+ * Set fDestroying if requested to do so and then wake up all the sleeping
+ * threads (usually just one). We leave the semaphore in the signalled
+ * state so the next caller will return immediately.
+ */
+ if (fNoMoreWaits)
+ ASMAtomicWriteBool(&pIf->fDestroying, true);
+
+ uint32_t cSleepers = ASMAtomicReadU32(&pIf->cSleepers) + 1;
+ while (cSleepers-- > 0)
+ {
+ int rc = RTSemEventSignal(pIf->hRecvEvent);
+ AssertRC(rc);
+ }
+
+ Log4(("IntNetR0IfWait: returns %Rrc\n", VINF_SUCCESS));
+ return VINF_SUCCESS;
+}
+
+
+/**
+ * VMMR0 request wrapper for IntNetR0IfAbortWait.
+ *
+ * @returns see IntNetR0IfWait.
+ * @param pSession The caller's session.
+ * @param pReq The request packet.
+ */
+INTNETR0DECL(int) IntNetR0IfAbortWaitReq(PSUPDRVSESSION pSession, PINTNETIFABORTWAITREQ pReq)
+{
+ if (RT_UNLIKELY(pReq->Hdr.cbReq != sizeof(*pReq)))
+ return VERR_INVALID_PARAMETER;
+ return IntNetR0IfAbortWait(pReq->hIf, pSession, pReq->fNoMoreWaits);
+}
+
+
+/**
* Close an interface.
*
* @returns VBox status code.
@@ -3911,34 +3992,18 @@ INTNETR0DECL(int) IntNetR0IfClose(INTNETIFHANDLE hIf, PSUPDRVSESSION pSession)
/*
* Validate and free the handle.
- *
- * We grab the big mutex before we free the handle to avoid any handle
- * confusion on the trunk.
*/
PINTNET pIntNet = g_pIntNet;
AssertPtrReturn(pIntNet, VERR_INVALID_PARAMETER);
AssertReturn(pIntNet->u32Magic, VERR_INVALID_MAGIC);
- RTSemMutexRequest(pIntNet->hMtxCreateOpenDestroy, RT_INDEFINITE_WAIT);
-
PINTNETIF pIf = (PINTNETIF)RTHandleTableFreeWithCtx(pIntNet->hHtIfs, hIf, pSession);
if (!pIf)
- {
- RTSemMutexRelease(pIntNet->hMtxCreateOpenDestroy);
return VERR_INVALID_HANDLE;
- }
/* Mark the handle as freed so intnetR0IfDestruct won't free it again. */
ASMAtomicWriteU32(&pIf->hIf, INTNET_HANDLE_INVALID);
- /* Notify the trunk that the interface has been disconnected. */
- PINTNETNETWORK pNetwork = pIf->pNetwork;
- PINTNETTRUNKIF pTrunk = pNetwork ? pNetwork->MacTab.pTrunk : NULL;
- if (pTrunk && pTrunk->pIfPort)
- pTrunk->pIfPort->pfnDisconnectInterface(pTrunk->pIfPort, hIf);
-
- RTSemMutexRelease(pIntNet->hMtxCreateOpenDestroy);
-
/*
* Signal the event semaphore to wake up any threads in IntNetR0IfWait
* and give them a moment to get out and release the interface.
@@ -4042,10 +4107,9 @@ static DECLCALLBACK(void) intnetR0IfDestruct(void *pvObj, void *pvUser1, void *p
RTSpinlockReleaseNoInts(pNetwork->hAddrSpinlock, &Tmp);
- /* If we freed the handle just now, notify the trunk about the
- interface being destroyed. */
- if (hIf != INTNET_HANDLE_INVALID && pTrunk && pTrunk->pIfPort)
- pTrunk->pIfPort->pfnDisconnectInterface(pTrunk->pIfPort, hIf);
+ /* Notify the trunk about the interface being destroyed. */
+ if (pTrunk && pTrunk->pIfPort)
+ pTrunk->pIfPort->pfnDisconnectInterface(pTrunk->pIfPort, pIf->pvIfData);
/* Wait for the interface to quiesce while we still can. */
intnetR0BusyWait(pNetwork, &pIf->cBusy);
@@ -4189,6 +4253,7 @@ static int intnetR0NetworkCreateIf(PINTNETNETWORK pNetwork, PSUPDRVSESSION pSess
pIf->hRecvInSpinlock = NIL_RTSPINLOCK;
pIf->cBusy = 0;
//pIf->pDstTab = NULL;
+ //pIf->pvIfData = NULL;
for (int i = kIntNetAddrType_Invalid + 1; i < kIntNetAddrType_End && RT_SUCCESS(rc); i++)
rc = intnetR0IfAddrCacheInit(&pIf->aAddrCache[i], (INTNETADDRTYPE)i,
@@ -4259,7 +4324,7 @@ static int intnetR0NetworkCreateIf(PINTNETNETWORK pNetwork, PSUPDRVSESSION pSess
{
Log(("intnetR0NetworkCreateIf: pfnConnectInterface hIf=%RX32\n", pIf->hIf));
if (pTrunk->pIfPort)
- rc = pTrunk->pIfPort->pfnConnectInterface(pTrunk->pIfPort, pIf->hIf);
+ rc = pTrunk->pIfPort->pfnConnectInterface(pTrunk->pIfPort, pIf, &pIf->pvIfData);
intnetR0BusyDecTrunk(pTrunk);
}
if (RT_SUCCESS(rc))
@@ -4409,13 +4474,14 @@ static DECLCALLBACK(INTNETSWDECISION) intnetR0TrunkIfPortPreRecv(PINTNETTRUNKSWP
/** @copydoc INTNETTRUNKSWPORT::pfnRecv */
-static DECLCALLBACK(bool) intnetR0TrunkIfPortRecv(PINTNETTRUNKSWPORT pSwitchPort, PINTNETSG pSG, uint32_t fSrc)
+static DECLCALLBACK(bool) intnetR0TrunkIfPortRecv(PINTNETTRUNKSWPORT pSwitchPort, void *pvIf, PINTNETSG pSG, uint32_t fSrc)
{
PINTNETTRUNKIF pThis = INTNET_SWITCHPORT_2_TRUNKIF(pSwitchPort);
/* assert some sanity */
AssertPtr(pSG);
Assert(fSrc);
+ NOREF(pvIf); /* later */
/*
* Mark the trunk as busy, make sure we've got a network and that there are
diff --git a/src/VBox/Devices/Network/slirp/bootp.c b/src/VBox/Devices/Network/slirp/bootp.c
index 833298eb8..26bbda60d 100644
--- a/src/VBox/Devices/Network/slirp/bootp.c
+++ b/src/VBox/Devices/Network/slirp/bootp.c
@@ -1,4 +1,4 @@
-/* $Id: bootp.c 29506 2010-05-17 07:14:47Z vboxsync $ */
+/* $Id: bootp.c 29656 2010-05-19 06:05:09Z vboxsync $ */
/** @file
* NAT - BOOTP/DHCP server emulation.
*/
@@ -635,6 +635,7 @@ static void dhcp_decode(PNATState pData, struct bootp_t *bp, const uint8_t *buf,
int pmsg_type;
struct in_addr req_ip;
int fDhcpDiscover = 0;
+ uint8_t *parameter_list = NULL;
struct mbuf *m = NULL;
pmsg_type = 0;
@@ -650,6 +651,27 @@ static void dhcp_decode(PNATState pData, struct bootp_t *bp, const uint8_t *buf,
Assert(p);
if (p == NULL)
return;
+ /*
+ * We're going update dns list at least once per DHCP transaction (!not on every operation
+ * within transaction), assuming that transaction can't be longer than 1 min.
+ */
+ if ( !pData->fUseHostResolver
+ && ( pData->dnsLastUpdate == 0
+ || curtime - pData->dnsLastUpdate > 60 * 1000)) /* one minute*/
+ {
+ uint8_t i = 2; /* i = 0 - tag, i == 1 - length */
+ parameter_list = dhcp_find_option(&bp->bp_vend[0], RFC2132_PARAM_LIST);
+ for (;parameter_list && i < parameter_list[1]; ++i)
+ {
+ if (parameter_list[i] == RFC1533_DNS)
+ {
+ slirp_release_dns_list(pData);
+ slirp_init_dns_list(pData);
+ pData->dnsLastUpdate = curtime;
+ break;
+ }
+ }
+ }
#ifndef VBOX_WITH_SLIRP_BSD_MBUF
if ((m = m_get(pData)) == NULL)
diff --git a/src/VBox/Devices/Network/slirp/slirp.c b/src/VBox/Devices/Network/slirp/slirp.c
index fa7a03f12..e8f855045 100644
--- a/src/VBox/Devices/Network/slirp/slirp.c
+++ b/src/VBox/Devices/Network/slirp/slirp.c
@@ -1,4 +1,4 @@
-/* $Id: slirp.c 29506 2010-05-17 07:14:47Z vboxsync $ */
+/* $Id: slirp.c 29946 2010-06-01 12:53:39Z vboxsync $ */
/** @file
* NAT - slirp glue.
*/
@@ -419,7 +419,8 @@ static int get_dns_addr_domain(PNATState pData, bool fVerbose,
char buff[512];
char buff2[256];
RTFILE f;
- int fFoundNameserver = 0;
+ int cNameserversFound = 0;
+ int fWarnTooManyDnsServers = 0;
struct in_addr tmp_addr;
int rc;
size_t bytes;
@@ -467,11 +468,19 @@ static int get_dns_addr_domain(PNATState pData, bool fVerbose,
*ppszDomain = NULL;
Log(("NAT: DNS Servers:\n"));
- while ( RT_SUCCESS(rc = RTFileGets(f, buff, 512, &bytes))
+ while ( RT_SUCCESS(rc = RTFileGets(f, buff, sizeof(buff), &bytes))
&& rc != VERR_EOF)
{
struct dns_entry *pDns = NULL;
- if (sscanf(buff, "nameserver%*[ \t]%256s", buff2) == 1)
+ if ( cNameserversFound == 4
+ && fWarnTooManyDnsServers == 0
+ && sscanf(buff, "nameserver%*[ \t]%255s", buff2) == 1)
+ {
+ fWarnTooManyDnsServers = 1;
+ LogRel(("NAT: too many nameservers registered.\n"));
+ }
+ if ( sscanf(buff, "nameserver%*[ \t]%255s", buff2) == 1
+ && cNameserversFound < 4) /* Unix doesn't accept more than 4 name servers*/
{
if (!inet_aton(buff2, &tmp_addr))
continue;
@@ -491,7 +500,7 @@ static int get_dns_addr_domain(PNATState pData, bool fVerbose,
pDns->de_addr.s_addr = RT_H2N_U32(RT_N2H_U32(pData->special_addr.s_addr) | CTL_ALIAS);
}
TAILQ_INSERT_HEAD(&pData->pDnsList, pDns, de_list);
- fFoundNameserver++;
+ cNameserversFound++;
}
if ((!strncmp(buff, "domain", 6) || !strncmp(buff, "search", 6)))
{
@@ -524,21 +533,21 @@ static int get_dns_addr_domain(PNATState pData, bool fVerbose,
}
}
RTFileClose(f);
- if (!fFoundNameserver)
+ if (!cNameserversFound)
return -1;
return 0;
}
#endif /* !RT_OS_WINDOWS */
-static int slirp_init_dns_list(PNATState pData)
+int slirp_init_dns_list(PNATState pData)
{
TAILQ_INIT(&pData->pDnsList);
LIST_INIT(&pData->pDomainList);
return get_dns_addr_domain(pData, true, NULL, NULL);
}
-static void slirp_release_dns_list(PNATState pData)
+void slirp_release_dns_list(PNATState pData)
{
struct dns_entry *pDns = NULL;
struct dns_domain_entry *pDomain = NULL;
@@ -1711,10 +1720,10 @@ static uint32_t find_guest_ip(PNATState pData, const uint8_t *eth_addr)
*/
static void activate_port_forwarding(PNATState pData, const uint8_t *h_source)
{
- struct port_forward_rule *rule;
+ struct port_forward_rule *rule, *tmp;
/* check mac here */
- LIST_FOREACH(rule, &pData->port_forward_rule_head, list)
+ LIST_FOREACH_SAFE(rule, &pData->port_forward_rule_head, list, tmp)
{
struct socket *so;
struct alias_link *alias_link;
@@ -1780,7 +1789,7 @@ static void activate_port_forwarding(PNATState pData, const uint8_t *h_source)
lib = LibAliasInit(pData, NULL);
flags = LibAliasSetMode(lib, 0, 0);
- flags |= pData->i32AliasMode;
+ flags |= pData->i32AliasMode;
flags |= PKT_ALIAS_REVERSE; /* set reverse */
flags = LibAliasSetMode(lib, flags, ~0);
diff --git a/src/VBox/Devices/Network/slirp/slirp.h b/src/VBox/Devices/Network/slirp/slirp.h
index 3e0597b7e..044815ab0 100644
--- a/src/VBox/Devices/Network/slirp/slirp.h
+++ b/src/VBox/Devices/Network/slirp/slirp.h
@@ -1,4 +1,4 @@
-/* $Id: slirp.h 29506 2010-05-17 07:14:47Z vboxsync $ */
+/* $Id: slirp.h 29656 2010-05-19 06:05:09Z vboxsync $ */
/** @file
* NAT - slirp (declarations/defines).
*/
@@ -340,6 +340,8 @@ void slirp_arp_who_has(PNATState pData, uint32_t dst);
int slirp_arp_cache_update(PNATState pData, uint32_t dst, const uint8_t *mac);
void slirp_arp_cache_add(PNATState pData, uint32_t ip, const uint8_t *ether);
int slirp_arp_cache_update_or_add(PNATState pData, uint32_t dst, const uint8_t *mac);
+int slirp_init_dns_list(PNATState pData);
+void slirp_release_dns_list(PNATState pData);
#define MIN_MRU 128
#define MAX_MRU 16384
diff --git a/src/VBox/Devices/Network/slirp/slirp_state.h b/src/VBox/Devices/Network/slirp/slirp_state.h
index 459bbb837..e1f76c9a3 100644
--- a/src/VBox/Devices/Network/slirp/slirp_state.h
+++ b/src/VBox/Devices/Network/slirp/slirp_state.h
@@ -174,6 +174,7 @@ typedef struct NATState
struct dns_domain_list_head pDomainList;
struct in_addr tftp_server;
struct in_addr loopback_addr;
+ uint32_t dnsLastUpdate;
uint32_t netmask;
#ifndef VBOX_WITH_NAT_SERVICE
uint8_t client_ethaddr[6];
diff --git a/src/VBox/Devices/Network/slirp/socket.c b/src/VBox/Devices/Network/slirp/socket.c
index dc6ce7153..3366b9729 100644
--- a/src/VBox/Devices/Network/slirp/socket.c
+++ b/src/VBox/Devices/Network/slirp/socket.c
@@ -1,4 +1,4 @@
-/* $Id: socket.c 28800 2010-04-27 08:22:32Z vboxsync $ */
+/* $Id: socket.c 29968 2010-06-02 04:44:43Z vboxsync $ */
/** @file
* NAT - socket handling.
*/
@@ -728,10 +728,9 @@ sorecvfrom(PNATState pData, struct socket *so)
* last argument should be changed if Slirp will inject IP attributes
* Note: Here we can't check if dnsproxy's sent initial request
*/
-#ifndef VBOX_WITH_SLIRP_BSD_MBUF
- if (so->so_fport == RT_H2N_U16_C(53))
+ if ( pData->fUseDnsProxy
+ && so->so_fport == RT_H2N_U16_C(53))
dnsproxy_answer(pData, so, m);
-#endif
#if 0
if (m->m_len == len)