diff options
| author | Michael Meskes <meskes@debian.org> | 2010-06-04 09:49:50 +0200 |
|---|---|---|
| committer | Michael Meskes <meskes@debian.org> | 2010-06-04 09:49:50 +0200 |
| commit | e13debb062071c46f2707d0d0e59c57675b49360 (patch) | |
| tree | 922f54068563b5cf3274bae8ba8122ce4b4ede1d /src/VBox/Devices/Network | |
| parent | abd0051802e55207e88435a185ff8d6e6b8d17d5 (diff) | |
| download | virtualbox-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.cpp | 9 | ||||
| -rw-r--r-- | src/VBox/Devices/Network/DrvIntNet.cpp | 84 | ||||
| -rw-r--r-- | src/VBox/Devices/Network/SrvIntNetR0.cpp | 130 | ||||
| -rw-r--r-- | src/VBox/Devices/Network/slirp/bootp.c | 24 | ||||
| -rw-r--r-- | src/VBox/Devices/Network/slirp/slirp.c | 31 | ||||
| -rw-r--r-- | src/VBox/Devices/Network/slirp/slirp.h | 4 | ||||
| -rw-r--r-- | src/VBox/Devices/Network/slirp/slirp_state.h | 1 | ||||
| -rw-r--r-- | src/VBox/Devices/Network/slirp/socket.c | 7 |
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) |
