Changeset 87826 in vbox
- Timestamp:
- Feb 21, 2021 11:08:44 PM (4 years ago)
- Location:
- trunk/src/VBox/NetworkServices/NAT
- Files:
-
- 2 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/VBox/NetworkServices/NAT/Makefile.kmk
r87743 r87826 93 93 VBoxNetNAT_SOURCES = \ 94 94 VBoxNetLwipNAT.cpp \ 95 ../NetLib/ VBoxNetBaseService.cpp \95 ../NetLib/IntNetIf.cpp \ 96 96 ../NetLib/VBoxNetPortForwardString.cpp \ 97 ../NetLib/VBoxNetIntIf.cpp \98 ../NetLib/VBoxNetUDP.cpp \99 ../NetLib/VBoxNetARP.cpp \100 97 $(addprefix ../../Devices/Network/lwip-new/,$(LWIP_SOURCES)) \ 101 98 proxy_pollmgr.c \ -
trunk/src/VBox/NetworkServices/NAT/VBoxNetLwipNAT.cpp
r87798 r87826 30 30 #include <VBox/com/errorprint.h> 31 31 #include <VBox/com/VirtualBox.h> 32 #include <VBox/com/NativeEventQueue.h> 32 33 33 34 #include <iprt/net.h> … … 81 82 #include <stdio.h> 82 83 83 #include "../NetLib/ VBoxNetBaseService.h"84 #include "../NetLib/IntNetIf.h" 84 85 #include "../NetLib/VBoxPortForwardString.h" 85 86 … … 127 128 128 129 class VBoxNetLwipNAT 129 : public VBoxNetBaseService 130 { 130 { 131 static RTGETOPTDEF s_aGetOptDef[]; 132 133 com::Utf8Str m_strNetworkName; 134 int m_uVerbosity; 135 136 ComPtr<IVirtualBoxClient> virtualboxClient; 137 ComPtr<IVirtualBox> virtualbox; 138 ComPtr<IHost> m_host; 139 ComPtr<INATNetwork> m_net; 140 141 RTMAC m_MacAddress; 142 IntNetIf m_IntNetIf; 143 RTTHREAD m_hThrRecv; 144 131 145 /** Home folder location; used as default directory for several paths. */ 132 146 com::Utf8Str m_strHome; … … 144 158 netif m_LwipNetIf; 145 159 146 /* Our NAT network descriptor in Main */147 ComPtr<INATNetwork> m_net;148 ComPtr<IHost> m_host;149 150 160 VECNATSERVICEPF m_vecPortForwardRule4; 151 161 VECNATSERVICEPF m_vecPortForwardRule6; … … 177 187 Listener m_ListenerVBoxClient; 178 188 179 static INTNETSEG aXmitSeg[64];180 181 static RTGETOPTDEF s_aGetOptDef[];182 183 189 public: 184 190 VBoxNetLwipNAT(); 185 virtual~VBoxNetLwipNAT();191 ~VBoxNetLwipNAT(); 186 192 187 193 RTEXITCODE parseArgs(int argc, char *argv[]); 188 194 189 virtual int init(); 190 virtual int run(); 195 int init(); 196 int run(); 197 void shutdown(); 191 198 192 199 private: 193 virtual int parseOpt(int c, const RTGETOPTUNION &Value); 194 virtual void usage(); 195 196 virtual bool isMainNeeded() const { return true; } 200 RTEXITCODE usage(); 197 201 198 202 int initCom(); … … 220 224 static DECLCALLBACK(void) onLwipTcpIpInit(void *arg); 221 225 static DECLCALLBACK(void) onLwipTcpIpFini(void *arg); 222 static err_tnetifInit(netif *pNetif) RT_NOTHROW_PROTO;223 224 virtualHRESULT HandleEvent(VBoxEventType_T aEventType, IEvent *pEvent);226 static DECLCALLBACK(err_t) netifInit(netif *pNetif) RT_NOTHROW_PROTO; 227 228 HRESULT HandleEvent(VBoxEventType_T aEventType, IEvent *pEvent); 225 229 226 230 const char **getHostNameservers(); … … 230 234 static int natServicePfRegister(NATSERVICEPORTFORWARDRULE &natServicePf); 231 235 236 static DECLCALLBACK(int) receiveThread(RTTHREAD hThreadSelf, void *pvUser); 237 232 238 /* input from intnet */ 233 virtual int processFrame(void *, size_t); 234 virtual int processGSO(PCPDMNETWORKGSO, size_t); 235 virtual int processUDP(void *, size_t) { return VERR_IGNORED; } 239 static DECLCALLBACK(void) processFrame(void *pvUser, void *pvFrame, uint32_t cbFrame); 236 240 237 241 /* output to intnet */ 238 static err_tnetifLinkoutput(netif *pNetif, pbuf *pBuf) RT_NOTHROW_PROTO;242 static DECLCALLBACK(err_t) netifLinkoutput(netif *pNetif, pbuf *pBuf) RT_NOTHROW_PROTO; 239 243 }; 240 244 241 INTNETSEG VBoxNetLwipNAT::aXmitSeg[64];242 243 245 244 246 245 247 VBoxNetLwipNAT::VBoxNetLwipNAT() 246 : VBoxNetBaseService("VBoxNetNAT", "") 248 : m_uVerbosity(0), 249 m_hThrRecv(NIL_RTTHREAD) 247 250 { 248 251 LogFlowFuncEnter(); … … 272 275 m_LwipNetIf.name[1] = 'T'; 273 276 274 RTMAC mac; 275 mac.au8[0] = 0x52; 276 mac.au8[1] = 0x54; 277 mac.au8[2] = 0; 278 mac.au8[3] = 0x12; 279 mac.au8[4] = 0x35; 280 mac.au8[5] = 0; 281 setMacAddress(mac); 282 277 m_MacAddress.au8[0] = 0x52; 278 m_MacAddress.au8[1] = 0x54; 279 m_MacAddress.au8[2] = 0; 280 m_MacAddress.au8[3] = 0x12; 281 m_MacAddress.au8[4] = 0x35; 282 m_MacAddress.au8[5] = 0; 283 284 RT_ZERO(m_lo2off); 283 285 m_loOptDescriptor.lomap = NULL; 284 286 m_loOptDescriptor.num_lomap = 0; … … 311 313 /** 312 314 * Command line options. 313 *314 * @note This class is currently in transition away from being315 * inheritted from VBoxNetBaseService, so it no longer calls its316 * getopt code and has its own parseArgs() instead.317 315 */ 318 316 RTGETOPTDEF VBoxNetLwipNAT::s_aGetOptDef[] = … … 326 324 #define RTEXITCODE_DONE RTEXITCODE_32BIT_HACK 327 325 328 void 326 RTEXITCODE 329 327 VBoxNetLwipNAT::usage() 330 328 { … … 340 338 for (size_t i = 0; i < RT_ELEMENTS(s_aGetOptDef); ++i) 341 339 RTPrintf(" -%c, %s\n", s_aGetOptDef[i].iShort, s_aGetOptDef[i].pszLong); 340 341 return RTEXITCODE_DONE; 342 342 } 343 343 … … 361 361 { 362 362 case 'n': /* --network */ 363 if ( !getNetworkName().empty())363 if (m_strNetworkName.isNotEmpty()) 364 364 return RTMsgErrorExit(RTEXITCODE_SYNTAX, "multiple --network options"); 365 setNetworkName(Val.psz);365 m_strNetworkName = Val.psz; 366 366 break; 367 367 … … 380 380 381 381 case 'h': /* --help */ 382 usage(); 383 return RTEXITCODE_DONE; 382 return usage(); 384 383 385 384 case VINF_GETOPT_NOT_OPTION: … … 391 390 } 392 391 393 if ( getNetworkName().empty())392 if (m_strNetworkName.isEmpty()) 394 393 return RTMsgErrorExit(RTEXITCODE_SYNTAX, "missing --network option"); 395 394 396 /* tell the base class while we're still joined at the hip */ 397 setVerbosityLevel((int32_t)uVerbosity); 398 395 m_uVerbosity = uVerbosity; 399 396 return RTEXITCODE_SUCCESS; 400 }401 402 403 /**404 * @note This class is currently in transition away from being405 * inheritted from VBoxNetBaseService, so it no longer calls its406 * getopt code and has its own parseArgs() instead.407 */408 int VBoxNetLwipNAT::parseOpt(int c, const RTGETOPTUNION &Value)409 {410 RT_NOREF(c, Value);411 return VERR_NOT_FOUND; /* not recognized */412 397 } 413 398 … … 438 423 * API object to get the rest of the configuration from. 439 424 */ 440 const std::string &networkName = getNetworkName(); 441 hrc = virtualbox->FindNATNetworkByName(com::Bstr(networkName.c_str()).raw(), 425 hrc = virtualbox->FindNATNetworkByName(com::Bstr(m_strNetworkName).raw(), 442 426 m_net.asOutParam()); 443 427 if (FAILED(hrc)) … … 491 475 492 476 /* connect to the intnet */ 493 rc = tryGoOnline();477 rc = m_IntNetIf.init(m_strNetworkName); 494 478 if (RT_FAILURE(rc)) 495 479 return rc; 496 497 /* start the LWIP thread */498 vboxLwipCoreInitialize(VBoxNetLwipNAT::onLwipTcpIpInit, this);499 480 500 481 LogFlowFuncLeaveRC(rc); … … 641 622 Addr4.u = Net4.u | RT_H2N_U32_C(0x00000001); 642 623 643 /* Transitional: check that old and new ways agree */644 const RTNETADDRIPV4 &CmdLineAddr4 = getIpv4Address();645 AssertReturn(CmdLineAddr4.u == 0 || CmdLineAddr4.u == Addr4.u,646 VERR_INVALID_PARAMETER);647 648 const RTNETADDRIPV4 &CmdLineMask4 = getIpv4Netmask();649 AssertReturn(CmdLineMask4.u == 0 || CmdLineMask4.u == Mask4.u,650 VERR_INVALID_PARAMETER);651 652 /*653 * Transitional: tell the base class just in case, though it's not654 * used as far as I can tell.655 */656 if (CmdLineAddr4.u == 0)657 {658 setIpv4Address(Addr4);659 setIpv4Netmask(Mask4);660 }661 662 624 memcpy(&m_ProxyOptions.ipv4_addr, &Addr4, sizeof(ip_addr)); 663 625 memcpy(&m_ProxyOptions.ipv4_mask, &Mask4, sizeof(ip_addr)); … … 768 730 769 731 /* netmask in host order, to verify the offsets */ 770 uint32_t uMask = RT_N2H_U32( getIpv4Netmask().u);732 uint32_t uMask = RT_N2H_U32(ip4_addr_get_u32(&m_ProxyOptions.ipv4_mask)); 771 733 772 734 … … 1315 1277 * the exact details. 1316 1278 */ 1317 /* static */ 1318 err_tVBoxNetLwipNAT::netifInit(netif *pNetif) RT_NOTHROW_DEF1279 /* static */ DECLCALLBACK(err_t) 1280 VBoxNetLwipNAT::netifInit(netif *pNetif) RT_NOTHROW_DEF 1319 1281 { 1320 1282 err_t rcLwip = ERR_OK; … … 1332 1294 1333 1295 pNetif->hwaddr_len = sizeof(RTMAC); 1334 RTMAC mac = self->getMacAddress(); 1335 memcpy(pNetif->hwaddr, &mac, sizeof(RTMAC)); 1296 memcpy(pNetif->hwaddr, &self->m_MacAddress, sizeof(RTMAC)); 1336 1297 1337 1298 self->m_u16Mtu = 1500; // XXX: FIXME … … 1373 1334 * feeds them to lwIP. Enter COM event loop here, on the main thread. 1374 1335 */ 1375 int VBoxNetLwipNAT::run() 1376 { 1377 VBoxNetBaseService::run(); 1378 1379 /* event pump was told to shut down, we are done ... */ 1336 int 1337 VBoxNetLwipNAT::run() 1338 { 1339 int rc; 1340 1341 AssertReturn(m_hThrRecv == NIL_RTTHREAD, VERR_INVALID_STATE); 1342 1343 /* spawn the lwIP tcpip thread */ 1344 vboxLwipCoreInitialize(VBoxNetLwipNAT::onLwipTcpIpInit, this); 1345 1346 /* spawn intnet input pump */ 1347 rc = RTThreadCreate(&m_hThrRecv, 1348 VBoxNetLwipNAT::receiveThread, this, 1349 0, /* :cbStack */ 1350 RTTHREADTYPE_IO, RTTHREADFLAGS_WAITABLE, 1351 "RECV"); 1352 AssertRCReturn(rc, rc); 1353 1354 /* main thread will run the API event queue pump */ 1355 com::NativeEventQueue *pQueue = com::NativeEventQueue::getMainEventQueue(); 1356 if (pQueue == NULL) 1357 { 1358 LogRel(("run: getMainEventQueue() == NULL\n")); 1359 return VERR_GENERAL_FAILURE; 1360 } 1361 1362 /* dispatch API events to our listeners */ 1363 for (;;) 1364 { 1365 rc = pQueue->processEventQueue(RT_INDEFINITE_WAIT); 1366 if (rc == VERR_INTERRUPTED) 1367 { 1368 LogRel(("run: shutdown\n")); 1369 break; 1370 } 1371 else if (rc != VINF_SUCCESS) 1372 { 1373 /* note any unexpected rc */ 1374 LogRel(("run: processEventQueue: %Rrc\n", rc)); 1375 } 1376 } 1377 1378 /* 1379 * We are out of the event loop, so we were told to shut down. 1380 * Tell other threads to wrap up. 1381 */ 1382 1383 /* tell the intnet input pump to terminate */ 1384 m_IntNetIf.ifAbort(); 1385 1386 /* tell the lwIP tcpip thread to terminate */ 1380 1387 vboxLwipCoreFinalize(VBoxNetLwipNAT::onLwipTcpIpFini, this); 1381 1388 1382 m_vecPortForwardRule4.clear(); 1383 m_vecPortForwardRule6.clear(); 1384 1389 rc = RTThreadWait(m_hThrRecv, 5000, NULL); 1390 m_hThrRecv = NIL_RTTHREAD; 1391 1392 return VINF_SUCCESS; 1393 } 1394 1395 1396 void 1397 VBoxNetLwipNAT::shutdown() 1398 { 1399 int rc; 1400 1401 com::NativeEventQueue *pQueue = com::NativeEventQueue::getMainEventQueue(); 1402 if (pQueue == NULL) 1403 { 1404 LogRel(("shutdown: getMainEventQueue() == NULL\n")); 1405 return; 1406 } 1407 1408 /* unregister listeners */ 1385 1409 m_ListenerNATNet.unlisten(); 1386 1410 m_ListenerVirtualBox.unlisten(); 1387 1411 m_ListenerVBoxClient.unlisten(); 1388 1412 1389 return VINF_SUCCESS; 1413 /* tell the event loop in run() to stop */ 1414 rc = pQueue->interruptEventQueueProcessing(); 1415 if (RT_FAILURE(rc)) 1416 LogRel(("shutdown: interruptEventQueueProcessing: %Rrc\n", rc)); 1390 1417 } 1391 1418 … … 1422 1449 hrc = pSettingsEvent->COMGETTER(NetworkName)(networkName.asOutParam()); 1423 1450 AssertComRCReturn(hrc, hrc); 1424 if (networkName .compare(getNetworkName().c_str()))1451 if (networkName != m_strNetworkName) 1425 1452 break; /* change not for our network */ 1426 1453 … … 1448 1475 hrc = pForwardEvent->COMGETTER(NetworkName)(networkName.asOutParam()); 1449 1476 AssertComRCReturn(hrc, hrc); 1450 if (networkName .compare(getNetworkName().c_str()))1477 if (networkName != m_strNetworkName) 1451 1478 break; /* change not for our network */ 1452 1479 … … 1606 1633 hrc = pStartStopEvent->COMGETTER(NetworkName)(networkName.asOutParam()); 1607 1634 AssertComRCReturn(hrc, hrc); 1608 if (networkName .compare(getNetworkName().c_str()))1635 if (networkName != m_strNetworkName) 1609 1636 break; /* change not for our network */ 1610 1637 … … 1809 1836 1810 1837 /** 1838 * IntNetIf receive thread. Runs intnet pump with our processFrame() 1839 * as input callback. 1840 */ 1841 /* static */ DECLCALLBACK(int) 1842 VBoxNetLwipNAT::receiveThread(RTTHREAD hThreadSelf, void *pvUser) 1843 { 1844 HRESULT hrc; 1845 int rc; 1846 1847 RT_NOREF(hThreadSelf); 1848 1849 AssertReturn(pvUser != NULL, VERR_INVALID_PARAMETER); 1850 VBoxNetLwipNAT *self = static_cast<VBoxNetLwipNAT *>(pvUser); 1851 1852 /* do we relaly need to init com on this thread? */ 1853 hrc = com::Initialize(); 1854 if (FAILED(hrc)) 1855 return VERR_GENERAL_FAILURE; 1856 1857 rc = self->m_IntNetIf.setInputCallback(VBoxNetLwipNAT::processFrame, self); 1858 AssertRCReturn(rc, rc); 1859 1860 rc = self->m_IntNetIf.ifPump(); 1861 if (rc == VERR_SEM_DESTROYED) 1862 return VINF_SUCCESS; 1863 1864 LogRel(("receiveThread: ifPump: unexpected %Rrc\n", rc)); 1865 return VERR_INVALID_STATE; 1866 } 1867 1868 1869 /** 1811 1870 * Process an incoming frame received from the intnet. 1812 1871 */ 1813 int VBoxNetLwipNAT::processFrame(void *pvFrame, size_t cbFrame) 1814 { 1815 AssertPtrReturn(pvFrame, VERR_INVALID_PARAMETER); 1816 AssertReturn(cbFrame != 0, VERR_INVALID_PARAMETER); 1872 /* static */ DECLCALLBACK(void) 1873 VBoxNetLwipNAT::processFrame(void *pvUser, void *pvFrame, uint32_t cbFrame) 1874 { 1875 AssertReturnVoid(pvFrame != NULL); 1876 AssertReturnVoid(cbFrame != 0); 1877 AssertReturnVoid(cbFrame <= 1522); /* include .1Q and FCS */ 1878 1879 AssertReturnVoid(pvUser != NULL); 1880 VBoxNetLwipNAT *self = static_cast<VBoxNetLwipNAT *>(pvUser); 1817 1881 1818 1882 struct pbuf *p = pbuf_alloc(PBUF_RAW, (u16_t)cbFrame + ETH_PAD_SIZE, PBUF_POOL); 1819 1883 if (RT_UNLIKELY(p == NULL)) 1820 return VERR_NO_MEMORY;1884 return; 1821 1885 1822 1886 /* … … 1845 1909 } while (RT_UNLIKELY(q != NULL)); 1846 1910 1847 m_LwipNetIf.input(p, &m_LwipNetIf); 1848 return VINF_SUCCESS; 1849 } 1850 1851 1852 /** 1853 * Process an incoming GSO frame received from the intnet. 1854 */ 1855 int VBoxNetLwipNAT::processGSO(PCPDMNETWORKGSO pGso, size_t cbFrame) 1856 { 1857 if (!PDMNetGsoIsValid(pGso, cbFrame, cbFrame - sizeof(PDMNETWORKGSO))) 1858 return VERR_INVALID_PARAMETER; 1859 1860 cbFrame -= sizeof(PDMNETWORKGSO); 1861 uint8_t abHdrScratch[256]; 1862 uint32_t const cSegs = PDMNetGsoCalcSegmentCount(pGso, 1863 cbFrame); 1864 for (uint32_t iSeg = 0; iSeg < cSegs; iSeg++) 1865 { 1866 uint32_t cbSegFrame; 1867 void *pvSegFrame = PDMNetGsoCarveSegmentQD(pGso, 1868 (uint8_t *)(pGso + 1), 1869 cbFrame, 1870 abHdrScratch, 1871 iSeg, 1872 cSegs, 1873 &cbSegFrame); 1874 1875 int rc = processFrame(pvSegFrame, cbSegFrame); 1876 if (RT_FAILURE(rc)) 1877 { 1878 return rc; 1879 } 1880 } 1881 1882 return VINF_SUCCESS; 1911 /* pass input to lwIP: netif input funcion tcpip_input() */ 1912 self->m_LwipNetIf.input(p, &self->m_LwipNetIf); 1883 1913 } 1884 1914 … … 1887 1917 * Send an outgoing frame from lwIP to intnet. 1888 1918 */ 1889 /* static */ 1890 err_t VBoxNetLwipNAT::netifLinkoutput(netif *pNetif, pbuf *pPBuf) RT_NOTHROW_DEF 1891 { 1919 /* static */ DECLCALLBACK(err_t) 1920 VBoxNetLwipNAT::netifLinkoutput(netif *pNetif, pbuf *pPBuf) RT_NOTHROW_DEF 1921 { 1922 int rc; 1923 1892 1924 AssertPtrReturn(pNetif, ERR_ARG); 1893 1925 AssertPtrReturn(pPBuf, ERR_ARG); … … 1903 1935 pPBuf)); 1904 1936 1905 RT_ZERO(VBoxNetLwipNAT::aXmitSeg); 1906 1907 size_t idx = 0; 1908 for (struct pbuf *q = pPBuf; q != NULL; q = q->next, ++idx) 1909 { 1910 AssertReturn(idx < RT_ELEMENTS(VBoxNetLwipNAT::aXmitSeg), ERR_MEM); 1911 1912 #if ETH_PAD_SIZE 1913 if (q == pPBuf) 1914 { 1915 VBoxNetLwipNAT::aXmitSeg[idx].pv = (uint8_t *)q->payload + ETH_PAD_SIZE; 1916 VBoxNetLwipNAT::aXmitSeg[idx].cb = q->len - ETH_PAD_SIZE; 1917 } 1918 else 1919 #endif 1920 { 1921 VBoxNetLwipNAT::aXmitSeg[idx].pv = q->payload; 1922 VBoxNetLwipNAT::aXmitSeg[idx].cb = q->len; 1923 } 1924 } 1925 1926 int rc = self->sendBufferOnWire(VBoxNetLwipNAT::aXmitSeg, idx, 1927 pPBuf->tot_len - ETH_PAD_SIZE); 1928 AssertRCReturn(rc, ERR_IF); 1929 1930 self->flushWire(); 1937 if (pPBuf->tot_len < sizeof(struct eth_hdr)) /* includes ETH_PAD_SIZE */ 1938 return ERR_ARG; 1939 1940 size_t cbFrame = (size_t)pPBuf->tot_len - ETH_PAD_SIZE; 1941 IntNetIf::Frame frame; 1942 rc = self->m_IntNetIf.getOutputFrame(frame, cbFrame); 1943 if (RT_FAILURE(rc)) 1944 return ERR_MEM; 1945 1946 pbuf_copy_partial(pPBuf, frame.pvFrame, cbFrame, ETH_PAD_SIZE); 1947 rc = self->m_IntNetIf.ifOutput(frame); 1948 if (RT_FAILURE(rc)) 1949 return ERR_IF; 1931 1950 1932 1951 LogFlowFunc(("LEAVE: %d\n", ERR_OK)); … … 1943 1962 1944 1963 AssertReturn(!virtualbox.isNull(), E_FAIL); 1945 AssertReturn( !getNetworkName().empty(), E_FAIL);1964 AssertReturn(m_strNetworkName.isNotEmpty(), E_FAIL); 1946 1965 AssertReturn(pcszKey != NULL, E_FAIL); 1947 1966 AssertReturn(*pcszKey != '\0', E_FAIL); 1948 1967 1949 com::BstrFmt bstrKey("NAT/%s/%s", getNetworkName().c_str(), pcszKey);1968 com::BstrFmt bstrKey("NAT/%s/%s", m_strNetworkName.c_str(), pcszKey); 1950 1969 com::Bstr bstrValue; 1951 1970 hrc = virtualbox->GetExtraData(bstrKey.raw(), bstrValue.asOutParam()); … … 2087 2106 int rc; 2088 2107 2089 const std::string &strNetworkName = getNetworkName(); 2090 if (strNetworkName.empty()) 2108 if (m_strNetworkName.isEmpty()) 2091 2109 return VERR_MISSING; 2092 2110 2093 2111 char szNetwork[RTPATH_MAX]; 2094 rc = RTStrCopy(szNetwork, sizeof(szNetwork), strNetworkName.c_str());2112 rc = RTStrCopy(szNetwork, sizeof(szNetwork), m_strNetworkName.c_str()); 2095 2113 if (RT_FAILURE(rc)) 2096 2114 return rc;
Note:
See TracChangeset
for help on using the changeset viewer.