Changeset 87449 in vbox for trunk/src/VBox/NetworkServices
- Timestamp:
- Jan 27, 2021 1:05:45 AM (4 years ago)
- svn:sync-xref-src-repo-rev:
- 142467
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/VBox/NetworkServices/NAT/VBoxNetLwipNAT.cpp
r87400 r87449 167 167 168 168 169 170 VBoxNetLwipNAT( SOCKET icmpsock4, SOCKET icmpsock6);169 public: 170 VBoxNetLwipNAT(); 171 171 virtual ~VBoxNetLwipNAT(); 172 172 … … 179 179 180 180 virtual int init(); 181 virtual int run(); 182 183 private: 184 void createRawSock4(); 185 void createRawSock6(); 181 186 182 187 static DECLCALLBACK(void) onLwipTcpIpInit(void *arg); 183 188 static DECLCALLBACK(void) onLwipTcpIpFini(void *arg); 184 189 static err_t netifInit(netif *pNetif) RT_NOTHROW_PROTO; 185 186 virtual int run();187 190 188 191 HRESULT HandleEvent(VBoxEventType_T aEventType, IEvent *pEvent); … … 205 208 INTNETSEG VBoxNetLwipNAT::aXmitSeg[64]; 206 209 207 static VBoxNetLwipNAT *g_pLwipNat; 208 209 210 211 VBoxNetLwipNAT::VBoxNetLwipNAT(SOCKET icmpsock4, SOCKET icmpsock6) 210 211 212 VBoxNetLwipNAT::VBoxNetLwipNAT() 212 213 : VBoxNetBaseService("VBoxNetNAT", "nat-network") 213 214 { … … 216 217 m_ProxyOptions.ipv6_enabled = 0; 217 218 m_ProxyOptions.ipv6_defroute = 0; 218 m_ProxyOptions.icmpsock4 = icmpsock4;219 m_ProxyOptions.icmpsock6 = icmpsock6;219 m_ProxyOptions.icmpsock4 = INVALID_SOCKET; 220 m_ProxyOptions.icmpsock6 = INVALID_SOCKET; 220 221 m_ProxyOptions.tftp_root = NULL; 221 222 m_ProxyOptions.src4 = NULL; … … 376 377 377 378 /* 378 * Bind outgoing connections to the specified IP.379 * IPv4 source address, if configured. 379 380 */ 380 com::Bstr bstrSourceIpX; 381 382 /* IPv4 */ 381 com::Bstr bstrSourceIp4; 383 382 com::Bstr bstrSourceIp4Key = com::BstrFmt("NAT/%s/SourceIp4", networkName.c_str()); 384 hrc = virtualbox->GetExtraData(bstrSourceIp4Key.raw(), bstrSourceIp X.asOutParam());385 if (SUCCEEDED(hrc) && bstrSourceIp X.isNotEmpty())383 hrc = virtualbox->GetExtraData(bstrSourceIp4Key.raw(), bstrSourceIp4.asOutParam()); 384 if (SUCCEEDED(hrc) && bstrSourceIp4.isNotEmpty()) 386 385 { 387 386 RTNETADDRIPV4 addr; 388 rc = RTNetStrToIPv4Addr(com::Utf8Str(bstrSourceIp X).c_str(), &addr);387 rc = RTNetStrToIPv4Addr(com::Utf8Str(bstrSourceIp4).c_str(), &addr); 389 388 if (RT_SUCCESS(rc)) 390 389 { … … 398 397 { 399 398 LogRel(("Failed to parse \"%s\" IPv4 source address specification\n", 400 com::Utf8Str(bstrSourceIpX).c_str())); 401 } 402 403 bstrSourceIpX.setNull(); 404 } 405 406 /* IPv6 */ 407 com::Bstr bstrSourceIp6Key = com::BstrFmt("NAT/%s/SourceIp6", networkName.c_str()); 408 hrc = virtualbox->GetExtraData(bstrSourceIp6Key.raw(), bstrSourceIpX.asOutParam()); 409 if (SUCCEEDED(hrc) && bstrSourceIpX.isNotEmpty()) 410 { 411 RTNETADDRIPV6 addr; 412 char *pszZone = NULL; 413 rc = RTNetStrToIPv6Addr(com::Utf8Str(bstrSourceIpX).c_str(), &addr, &pszZone); 414 if (RT_SUCCESS(rc)) 415 { 416 memcpy(&m_src6.sin6_addr, &addr, sizeof(addr)); 417 m_ProxyOptions.src6 = &m_src6; 418 419 LogRel(("Will use %RTnaipv6 as IPv6 source address\n", 420 &m_src6.sin6_addr)); 421 } 422 else 423 { 424 LogRel(("Failed to parse \"%s\" IPv6 source address specification\n", 425 com::Utf8Str(bstrSourceIpX).c_str())); 426 } 427 428 bstrSourceIpX.setNull(); 429 } 399 com::Utf8Str(bstrSourceIp4).c_str())); 400 } 401 } 402 403 /* 404 * IPv6 source address, if configured. 405 */ 406 if (fIPv6Enabled) 407 { 408 com::Bstr bstrSourceIp6; 409 com::Bstr bstrSourceIp6Key = com::BstrFmt("NAT/%s/SourceIp6", networkName.c_str()); 410 hrc = virtualbox->GetExtraData(bstrSourceIp6Key.raw(), bstrSourceIp6.asOutParam()); 411 if (SUCCEEDED(hrc) && bstrSourceIp6.isNotEmpty()) 412 { 413 RTNETADDRIPV6 addr; 414 char *pszZone = NULL; 415 rc = RTNetStrToIPv6Addr(com::Utf8Str(bstrSourceIp6).c_str(), &addr, &pszZone); 416 if (RT_SUCCESS(rc)) 417 { 418 memcpy(&m_src6.sin6_addr, &addr, sizeof(addr)); 419 m_ProxyOptions.src6 = &m_src6; 420 421 LogRel(("Will use %RTnaipv6 as IPv6 source address\n", 422 &m_src6.sin6_addr)); 423 } 424 else 425 { 426 LogRel(("Failed to parse \"%s\" IPv6 source address specification\n", 427 com::Utf8Str(bstrSourceIp6).c_str())); 428 } 429 } 430 } 431 432 433 createRawSock4(); 434 if (fIPv6Enabled) 435 createRawSock6(); 430 436 431 437 … … 481 487 LogFlowFuncLeaveRC(rc); 482 488 return rc; 489 } 490 491 492 /** 493 * Create raw IPv4 socket for sending and snooping ICMP. 494 */ 495 void VBoxNetLwipNAT::createRawSock4() 496 { 497 SOCKET icmpsock4 = INVALID_SOCKET; 498 499 #ifndef RT_OS_DARWIN 500 const int icmpstype = SOCK_RAW; 501 #else 502 /* on OS X it's not privileged */ 503 const int icmpstype = SOCK_DGRAM; 504 #endif 505 506 icmpsock4 = socket(AF_INET, icmpstype, IPPROTO_ICMP); 507 if (icmpsock4 == INVALID_SOCKET) 508 { 509 perror("IPPROTO_ICMP"); 510 #ifdef VBOX_RAWSOCK_DEBUG_HELPER 511 icmpsock4 = getrawsock(AF_INET); 512 #endif 513 } 514 515 if (icmpsock4 != INVALID_SOCKET) 516 { 517 #ifdef ICMP_FILTER // Linux specific 518 struct icmp_filter flt = { 519 ~(uint32_t)( 520 (1U << ICMP_ECHOREPLY) 521 | (1U << ICMP_DEST_UNREACH) 522 | (1U << ICMP_TIME_EXCEEDED) 523 ) 524 }; 525 526 int status = setsockopt(icmpsock4, SOL_RAW, ICMP_FILTER, 527 &flt, sizeof(flt)); 528 if (status < 0) 529 { 530 perror("ICMP_FILTER"); 531 } 532 #endif 533 } 534 535 m_ProxyOptions.icmpsock4 = icmpsock4; 536 } 537 538 539 /** 540 * Create raw IPv6 socket for sending and snooping ICMP6. 541 */ 542 void VBoxNetLwipNAT::createRawSock6() 543 { 544 SOCKET icmpsock6 = INVALID_SOCKET; 545 546 #ifndef RT_OS_DARWIN 547 const int icmpstype = SOCK_RAW; 548 #else 549 /* on OS X it's not privileged */ 550 const int icmpstype = SOCK_DGRAM; 551 #endif 552 553 icmpsock6 = socket(AF_INET6, icmpstype, IPPROTO_ICMPV6); 554 if (icmpsock6 == INVALID_SOCKET) 555 { 556 perror("IPPROTO_ICMPV6"); 557 #ifdef VBOX_RAWSOCK_DEBUG_HELPER 558 icmpsock6 = getrawsock(AF_INET6); 559 #endif 560 } 561 562 if (icmpsock6 != INVALID_SOCKET) 563 { 564 #ifdef ICMP6_FILTER // Windows doesn't support RFC 3542 API 565 /* 566 * XXX: We do this here for now, not in pxping.c, to avoid 567 * name clashes between lwIP and system headers. 568 */ 569 struct icmp6_filter flt; 570 ICMP6_FILTER_SETBLOCKALL(&flt); 571 572 ICMP6_FILTER_SETPASS(ICMP6_ECHO_REPLY, &flt); 573 574 ICMP6_FILTER_SETPASS(ICMP6_DST_UNREACH, &flt); 575 ICMP6_FILTER_SETPASS(ICMP6_PACKET_TOO_BIG, &flt); 576 ICMP6_FILTER_SETPASS(ICMP6_TIME_EXCEEDED, &flt); 577 ICMP6_FILTER_SETPASS(ICMP6_PARAM_PROB, &flt); 578 579 int status = setsockopt(icmpsock6, IPPROTO_ICMPV6, ICMP6_FILTER, 580 &flt, sizeof(flt)); 581 if (status < 0) 582 { 583 perror("ICMP6_FILTER"); 584 } 585 #endif 586 } 587 588 m_ProxyOptions.icmpsock6 = icmpsock6; 483 589 } 484 590 … … 922 1028 923 1029 /** 924 * Fetch port-forwarding rules from the API. 1030 * Read the list of host's resolvers via the API. 1031 * 1032 * Called during initialization and in response to the 1033 * VBoxEventType_OnHostNameResolutionConfigurationChange event. 1034 */ 1035 const char **VBoxNetLwipNAT::getHostNameservers() 1036 { 1037 if (m_host.isNull()) 1038 return NULL; 1039 1040 com::SafeArray<BSTR> aNameServers; 1041 HRESULT hrc = m_host->COMGETTER(NameServers)(ComSafeArrayAsOutParam(aNameServers)); 1042 if (FAILED(hrc)) 1043 return NULL; 1044 1045 const size_t cNameServers = aNameServers.size(); 1046 if (cNameServers == 0) 1047 return NULL; 1048 1049 const char **ppcszNameServers = 1050 (const char **)RTMemAllocZ(sizeof(char *) * (cNameServers + 1)); 1051 if (ppcszNameServers == NULL) 1052 return NULL; 1053 1054 size_t idxLast = 0; 1055 for (size_t i = 0; i < cNameServers; ++i) 1056 { 1057 com::Utf8Str strNameServer(aNameServers[i]); 1058 ppcszNameServers[idxLast] = RTStrDup(strNameServer.c_str()); 1059 if (ppcszNameServers[idxLast] != NULL) 1060 ++idxLast; 1061 } 1062 1063 if (idxLast == 0) 1064 { 1065 RTMemFree(ppcszNameServers); 1066 return NULL; 1067 } 1068 1069 return ppcszNameServers; 1070 } 1071 1072 1073 /** 1074 * Fetch port-forwarding rules via the API. 925 1075 * 926 1076 * Reads the initial sets of rules from VBoxSVC. The rules will be … … 1051 1201 natPf.Pfr.szPfrName)); 1052 1202 return VERR_IGNORED; 1053 }1054 1055 1056 const char **VBoxNetLwipNAT::getHostNameservers()1057 {1058 if (m_host.isNull())1059 return NULL;1060 1061 com::SafeArray<BSTR> aNameServers;1062 HRESULT hrc = m_host->COMGETTER(NameServers)(ComSafeArrayAsOutParam(aNameServers));1063 if (FAILED(hrc))1064 return NULL;1065 1066 const size_t cNameServers = aNameServers.size();1067 if (cNameServers == 0)1068 return NULL;1069 1070 const char **ppcszNameServers =1071 (const char **)RTMemAllocZ(sizeof(char *) * (cNameServers + 1));1072 if (ppcszNameServers == NULL)1073 return NULL;1074 1075 size_t idxLast = 0;1076 for (size_t i = 0; i < cNameServers; ++i)1077 {1078 com::Utf8Str strNameServer(aNameServers[i]);1079 ppcszNameServers[idxLast] = RTStrDup(strNameServer.c_str());1080 if (ppcszNameServers[idxLast] != NULL)1081 ++idxLast;1082 }1083 1084 if (idxLast == 0)1085 {1086 RTMemFree(ppcszNameServers);1087 return NULL;1088 }1089 1090 return ppcszNameServers;1091 1203 } 1092 1204 … … 1366 1478 { 1367 1479 fprintf(stderr, "wsastartup: failed (%d)\n", err); 1368 return 1;1480 return RTEXITCODE_INIT; 1369 1481 } 1370 1482 #endif … … 1382 1494 if (RT_SUCCESS(vrc)) 1383 1495 { 1384 return RTMsgErrorExit(RTEXITCODE_ FAILURE,1496 return RTMsgErrorExit(RTEXITCODE_INIT, 1385 1497 "Failed to initialize COM: %s: %Rhrf", 1386 1498 szHome, hrc); … … 1388 1500 } 1389 1501 #endif // VBOX_WITH_XPCOM 1390 return RTMsgErrorExit(RTEXITCODE_ FAILURE,1502 return RTMsgErrorExit(RTEXITCODE_INIT, 1391 1503 "Failed to initialize COM: %Rhrf", hrc); 1392 1504 } 1393 1505 1394 1395 SOCKET icmpsock4 = INVALID_SOCKET; 1396 SOCKET icmpsock6 = INVALID_SOCKET; 1397 #ifndef RT_OS_DARWIN 1398 const int icmpstype = SOCK_RAW; 1399 #else 1400 /* on OS X it's not privileged */ 1401 const int icmpstype = SOCK_DGRAM; 1402 #endif 1403 1404 icmpsock4 = socket(AF_INET, icmpstype, IPPROTO_ICMP); 1405 if (icmpsock4 == INVALID_SOCKET) 1406 { 1407 perror("IPPROTO_ICMP"); 1408 #ifdef VBOX_RAWSOCK_DEBUG_HELPER 1409 icmpsock4 = getrawsock(AF_INET); 1410 #endif 1411 } 1412 1413 if (icmpsock4 != INVALID_SOCKET) 1414 { 1415 #ifdef ICMP_FILTER // Linux specific 1416 struct icmp_filter flt = { 1417 ~(uint32_t)( 1418 (1U << ICMP_ECHOREPLY) 1419 | (1U << ICMP_DEST_UNREACH) 1420 | (1U << ICMP_TIME_EXCEEDED) 1421 ) 1422 }; 1423 1424 int status = setsockopt(icmpsock4, SOL_RAW, ICMP_FILTER, 1425 &flt, sizeof(flt)); 1426 if (status < 0) 1427 { 1428 perror("ICMP_FILTER"); 1429 } 1430 #endif 1431 } 1432 1433 icmpsock6 = socket(AF_INET6, icmpstype, IPPROTO_ICMPV6); 1434 if (icmpsock6 == INVALID_SOCKET) 1435 { 1436 perror("IPPROTO_ICMPV6"); 1437 #ifdef VBOX_RAWSOCK_DEBUG_HELPER 1438 icmpsock6 = getrawsock(AF_INET6); 1439 #endif 1440 } 1441 1442 if (icmpsock6 != INVALID_SOCKET) 1443 { 1444 #ifdef ICMP6_FILTER // Windows doesn't support RFC 3542 API 1445 /* 1446 * XXX: We do this here for now, not in pxping.c, to avoid 1447 * name clashes between lwIP and system headers. 1448 */ 1449 struct icmp6_filter flt; 1450 ICMP6_FILTER_SETBLOCKALL(&flt); 1451 1452 ICMP6_FILTER_SETPASS(ICMP6_ECHO_REPLY, &flt); 1453 1454 ICMP6_FILTER_SETPASS(ICMP6_DST_UNREACH, &flt); 1455 ICMP6_FILTER_SETPASS(ICMP6_PACKET_TOO_BIG, &flt); 1456 ICMP6_FILTER_SETPASS(ICMP6_TIME_EXCEEDED, &flt); 1457 ICMP6_FILTER_SETPASS(ICMP6_PARAM_PROB, &flt); 1458 1459 int status = setsockopt(icmpsock6, IPPROTO_ICMPV6, ICMP6_FILTER, 1460 &flt, sizeof(flt)); 1461 if (status < 0) 1462 { 1463 perror("ICMP6_FILTER"); 1464 } 1465 #endif 1466 } 1467 1468 1469 g_pLwipNat = new VBoxNetLwipNAT(icmpsock4, icmpsock6); 1506 VBoxNetLwipNAT NAT; 1470 1507 1471 1508 Log2(("NAT: initialization\n")); 1472 rc = g_pLwipNat->parseArgs(argc - 1, argv + 1);1509 rc = NAT.parseArgs(argc - 1, argv + 1); 1473 1510 rc = (rc == 0) ? VINF_SUCCESS : VERR_GENERAL_FAILURE; /* XXX: FIXME */ 1474 1511 1475 1512 if (RT_SUCCESS(rc)) 1476 rc = g_pLwipNat->init();1513 rc = NAT.init(); 1477 1514 1478 1515 if (RT_SUCCESS(rc)) 1479 g_pLwipNat->run(); 1480 1481 delete g_pLwipNat; 1482 return 0; 1516 NAT.run(); 1517 1518 return RTEXITCODE_SUCCESS; 1483 1519 } 1484 1520
Note:
See TracChangeset
for help on using the changeset viewer.