Changeset 105726 in vbox for trunk/src/VBox/Devices
- Timestamp:
- Aug 19, 2024 2:05:15 PM (8 months ago)
- svn:sync-xref-src-repo-rev:
- 164430
- Location:
- trunk/src/VBox/Devices/Network
- Files:
-
- 1 deleted
- 2 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/VBox/Devices/Network/DrvNAT.cpp
r105353 r105726 1097 1097 * information ourselves. 1098 1098 */ 1099 static DECLCALLBACK(void) drvNATNotifyDnsChanged(PPDMINETWORKNATCONFIG pInterface) 1100 { 1099 static DECLCALLBACK(void) drvNATNotifyDnsChanged(PPDMINETWORKNATCONFIG pInterface, PCPDMINETWORKNATDNSCONFIG pDnsConf) 1100 { 1101 RT_NOREF(pDnsConf); 1101 1102 PDRVNAT pThis = RT_FROM_MEMBER(pInterface, DRVNAT, INetworkNATCfg); 1102 1103 drvNATUpdateDNS(pThis, /* fFlapLink */ true); -
trunk/src/VBox/Devices/Network/DrvNATlibslirp.cpp
r105429 r105726 31 31 *********************************************************************************************************************************/ 32 32 #define LOG_GROUP LOG_GROUP_DRV_NAT 33 34 #include "DrvNATlibslirp.h" 35 36 37 /** 33 #define RTNET_INCL_IN_ADDR 34 #include "VBoxDD.h" 35 36 #ifdef RT_OS_WINDOWS 37 # include <iprt/win/winsock2.h> 38 # include <iprt/win/ws2tcpip.h> 39 #endif 40 41 #include <libslirp.h> 42 43 #include <VBox/vmm/dbgf.h> 44 #include <VBox/vmm/pdmdrv.h> 45 #include <VBox/vmm/pdmnetifs.h> 46 #include <VBox/vmm/pdmnetinline.h> 47 48 #ifndef RT_OS_WINDOWS 49 # include <unistd.h> 50 # include <fcntl.h> 51 # include <poll.h> 52 # include <errno.h> 53 #endif 54 #ifdef RT_OS_FREEBSD 55 # include <netinet/in.h> 56 #endif 57 58 #ifdef RT_OS_WINDOWS 59 # include <iprt/win/winsock2.h> 60 # define inet_aton(x, y) inet_pton(2, x, y) 61 # define AF_INET6 23 62 #endif 63 64 #include <iprt/assert.h> 65 #include <iprt/critsect.h> 66 #include <iprt/cidr.h> 67 #include <iprt/file.h> 68 #include <iprt/mem.h> 69 #include <iprt/net.h> 70 #include <iprt/pipe.h> 71 #include <iprt/string.h> 72 #include <iprt/stream.h> 73 #include <iprt/time.h> 74 #include <iprt/uuid.h> 75 76 #include <iprt/asm.h> 77 78 #include <iprt/semaphore.h> 79 #include <iprt/req.h> 80 #ifdef RT_OS_DARWIN 81 # include <SystemConfiguration/SystemConfiguration.h> 82 # include <CoreFoundation/CoreFoundation.h> 83 #endif 84 85 #define COUNTERS_INIT 86 #include "slirp/counters.h" 87 #include "slirp/resolv_conf_parser.h" 88 89 90 /********************************************************************************************************************************* 91 * Defined Constants And Macros * 92 *********************************************************************************************************************************/ 93 #define DRVNAT_MAXFRAMESIZE (16 * 1024) 94 #define DRVNAT_DEFAULT_TIMEOUT (3600*1000) 95 96 /** 97 * @todo: This is a bad hack to prevent freezing the guest during high network 98 * activity. Windows host only. This needs to be fixed properly. 99 */ 100 #define VBOX_NAT_DELAY_HACK 101 102 #define GET_EXTRADATA(pdrvins, node, name, rc, type, type_name, var) \ 103 do { \ 104 (rc) = (pdrvins)->pHlpR3->pfnCFGMQuery ## type((node), name, &(var)); \ 105 if (RT_FAILURE((rc)) && (rc) != VERR_CFGM_VALUE_NOT_FOUND) \ 106 return PDMDrvHlpVMSetError((pdrvins), (rc), RT_SRC_POS, \ 107 N_("NAT#%d: configuration query for \"" name "\" " #type_name " failed"), \ 108 (pdrvins)->iInstance); \ 109 } while (0) 110 111 #define GET_ED_STRICT(pdrvins, node, name, rc, type, type_name, var) \ 112 do { \ 113 (rc) = (pdrvins)->pHlpR3->pfnCFGMQuery ## type((node), name, &(var)); \ 114 if (RT_FAILURE((rc))) \ 115 return PDMDrvHlpVMSetError((pdrvins), (rc), RT_SRC_POS, \ 116 N_("NAT#%d: configuration query for \"" name "\" " #type_name " failed"), \ 117 (pdrvins)->iInstance); \ 118 } while (0) 119 120 #define GET_EXTRADATA_N(pdrvins, node, name, rc, type, type_name, var, var_size) \ 121 do { \ 122 (rc) = (pdrvins)->pHlpR3->pfnCFGMQuery ## type((node), name, &(var), var_size); \ 123 if (RT_FAILURE((rc)) && (rc) != VERR_CFGM_VALUE_NOT_FOUND) \ 124 return PDMDrvHlpVMSetError((pdrvins), (rc), RT_SRC_POS, \ 125 N_("NAT#%d: configuration query for \"" name "\" " #type_name " failed"), \ 126 (pdrvins)->iInstance); \ 127 } while (0) 128 129 #define GET_BOOL(rc, pdrvins, node, name, var) \ 130 GET_EXTRADATA(pdrvins, node, name, (rc), Bool, bolean, (var)) 131 #define GET_STRING(rc, pdrvins, node, name, var, var_size) \ 132 GET_EXTRADATA_N(pdrvins, node, name, (rc), String, string, (var), (var_size)) 133 #define GET_STRING_ALLOC(rc, pdrvins, node, name, var) \ 134 GET_EXTRADATA(pdrvins, node, name, (rc), StringAlloc, string, (var)) 135 #define GET_S32(rc, pdrvins, node, name, var) \ 136 GET_EXTRADATA(pdrvins, node, name, (rc), S32, int, (var)) 137 #define GET_S32_STRICT(rc, pdrvins, node, name, var) \ 138 GET_ED_STRICT(pdrvins, node, name, (rc), S32, int, (var)) 139 140 #define DO_GET_IP(rc, node, instance, status, x) \ 141 do { \ 142 char sz##x[32]; \ 143 GET_STRING((rc), (node), (instance), #x, sz ## x[0], sizeof(sz ## x)); \ 144 if (rc != VERR_CFGM_VALUE_NOT_FOUND) \ 145 (status) = inet_aton(sz ## x, &x); \ 146 } while (0) 147 148 #define GETIP_DEF(rc, node, instance, x, def) \ 149 do \ 150 { \ 151 int status = 0; \ 152 DO_GET_IP((rc), (node), (instance), status, x); \ 153 if (status == 0 || rc == VERR_CFGM_VALUE_NOT_FOUND) \ 154 x.s_addr = def; \ 155 } while (0) 156 157 158 /********************************************************************************************************************************* 159 * Structures and Typedefs * 160 *********************************************************************************************************************************/ 161 /** Slirp Timer */ 162 typedef struct slirpTimer 163 { 164 struct slirpTimer *next; 165 uint32_t uTimeExpire; 166 SlirpTimerCb pHandler; 167 void *opaque; 168 } SlirpTimer; 169 170 /** 171 * Main state of Libslirp NAT 172 */ 173 typedef struct SlirpState 174 { 175 unsigned int nsock; 176 177 Slirp *pSlirp; 178 struct pollfd *polls; 179 180 /** Num Polls (not bytes) */ 181 unsigned int uPollCap = 0; 182 183 SlirpTimer *pTimerHead; 184 } SlirpState; 185 typedef SlirpState *pSlirpState; 186 187 /** 188 * NAT network transport driver instance data. 189 * 190 * @implements PDMINETWORKUP 191 */ 192 typedef struct DRVNAT 193 { 194 /** The network interface. */ 195 PDMINETWORKUP INetworkUp; 196 /** The network NAT Engine configuration. */ 197 PDMINETWORKNATCONFIG INetworkNATCfg; 198 /** The port we're attached to. */ 199 PPDMINETWORKDOWN pIAboveNet; 200 /** The network config of the port we're attached to. */ 201 PPDMINETWORKCONFIG pIAboveConfig; 202 /** Pointer to the driver instance. */ 203 PPDMDRVINS pDrvIns; 204 /** Link state */ 205 PDMNETWORKLINKSTATE enmLinkState; 206 /** NAT state */ 207 pSlirpState pNATState; 208 /** TFTP directory prefix. */ 209 char *pszTFTPPrefix; 210 /** Boot file name to provide in the DHCP server response. */ 211 char *pszBootFile; 212 /** tftp server name to provide in the DHCP server response. */ 213 char *pszNextServer; 214 /** Polling thread. */ 215 PPDMTHREAD pSlirpThread; 216 /** Queue for NAT-thread-external events. */ 217 RTREQQUEUE hSlirpReqQueue; 218 /** The guest IP for port-forwarding. */ 219 uint32_t GuestIP; 220 /** Link state set when the VM is suspended. */ 221 PDMNETWORKLINKSTATE enmLinkStateWant; 222 223 #ifndef RT_OS_WINDOWS 224 /** The write end of the control pipe. */ 225 RTPIPE hPipeWrite; 226 /** The read end of the control pipe. */ 227 RTPIPE hPipeRead; 228 # if HC_ARCH_BITS == 32 229 uint32_t u32Padding; 230 # endif 231 #else 232 /** for external notification */ 233 HANDLE hWakeupEvent; 234 #endif 235 236 #define DRV_PROFILE_COUNTER(name, dsc) STAMPROFILE Stat ## name 237 #define DRV_COUNTING_COUNTER(name, dsc) STAMCOUNTER Stat ## name 238 #include "slirp/counters.h" 239 /** thread delivering packets for receiving by the guest */ 240 PPDMTHREAD pRecvThread; 241 /** event to wakeup the guest receive thread */ 242 RTSEMEVENT EventRecv; 243 /** Receive Req queue (deliver packets to the guest) */ 244 RTREQQUEUE hRecvReqQueue; 245 246 /** makes access to device func RecvAvail and Recv atomical. */ 247 RTCRITSECT DevAccessLock; 248 /** Number of in-flight packets. */ 249 volatile uint32_t cPkts; 250 251 /** Transmit lock taken by BeginXmit and released by EndXmit. */ 252 RTCRITSECT XmitLock; 253 254 #ifdef RT_OS_DARWIN 255 /* Handle of the DNS watcher runloop source. */ 256 CFRunLoopSourceRef hRunLoopSrcDnsWatcher; 257 #endif 258 } DRVNAT; 259 AssertCompileMemberAlignment(DRVNAT, StatNATRecvWakeups, 8); 260 /** Pointer to the NAT driver instance data. */ 261 typedef DRVNAT *PDRVNAT; 262 263 264 /********************************************************************************************************************************* 265 * Internal Functions * 266 *********************************************************************************************************************************/ 267 static void drvNATNotifyNATThread(PDRVNAT pThis, const char *pszWho); 268 static void drvNAT_UpdateTimeout(uint32_t *uTimeout, void *opaque); 269 static void drvNAT_CheckTimeout(void *opaque); 270 static DECLCALLBACK(int) drvNAT_AddPollCb(int iFd, int iEvents, void *opaque); 271 static DECLCALLBACK(int64_t) drvNAT_ClockGetNsCb(void *opaque); 272 static DECLCALLBACK(int) drvNAT_GetREventsCb(int idx, void *opaque); 273 274 275 276 /* 38 277 * PDM Function Implementations 39 278 */ … … 499 738 */ 500 739 #ifndef RT_OS_WINDOWS 501 uint32_t uTimeout = 0;740 uint32_t uTimeout = DRVNAT_DEFAULT_TIMEOUT; 502 741 pThis->pNATState->nsock = 1; 503 742 … … 548 787 549 788 #else /* RT_OS_WINDOWS */ 550 uint32_t uTimeout = 0;789 uint32_t uTimeout = DRVNAT_DEFAULT_TIMEOUT; 551 790 pThis->pNATState->nsock = 0; 552 791 slirp_pollfds_fill(pThis->pNATState->pSlirp, &uTimeout, drvNAT_AddPollCb /* SlirpAddPollCb */, pThis /* opaque */); … … 775 1014 } 776 1015 1016 /** 1017 * @interface_method_impl{PDMINETWORKNATCONFIG,pfnRedirectRuleCommand} 1018 */ 777 1019 static DECLCALLBACK(int) drvNATNetworkNatConfigRedirect(PPDMINETWORKNATCONFIG pInterface, bool fRemove, 778 1020 bool fUdp, const char *pHostIp, uint16_t u16HostPort, … … 811 1053 812 1054 /** 1055 * @interface_method_impl{PDMINETWORKNATCONFIG,pfnNotifyDnsChanged} 1056 */ 1057 static DECLCALLBACK(void) drvNATNotifyDnsChanged(PPDMINETWORKNATCONFIG pInterface, PCPDMINETWORKNATDNSCONFIG pDnsConf) 1058 { 1059 PDRVNAT const pThis = RT_FROM_MEMBER(pInterface, DRVNAT, INetworkNATCfg); 1060 SlirpState * const pNATState = pThis->pNATState; 1061 AssertReturnVoid(pNATState); 1062 AssertReturnVoid(pNATState->pSlirp); 1063 1064 slirp_set_vdomainname(pNATState->pSlirp, pDnsConf->szDomainName); 1065 slirp_set_vdnssearch(pNATState->pSlirp, pDnsConf->papszSearchDomains); 1066 /** @todo Convert the papszNameServers entries to IP address and tell about 1067 * the first IPv4 and IPv6 ones. */ 1068 } 1069 1070 1071 /* 813 1072 * Libslirp Utility Functions 814 1073 */ … … 822 1081 */ 823 1082 static void drvNAT_UpdateTimeout(uint32_t *uTimeout, void *opaque) 1083 { 1084 PDRVNAT pThis = (PDRVNAT)opaque; 1085 Assert(pThis); 1086 1087 uint32_t currTime = drvNAT_ClockGetNsCb(pThis) / (1000 * 1000); 1088 SlirpTimer *pCurrent = pThis->pNATState->pTimerHead; 1089 while (pCurrent != NULL) 1090 { 1091 if (pCurrent->uTimeExpire != 0) 1092 { 1093 int64_t diff = pCurrent->uTimeExpire - currTime; 1094 1095 if (diff < 0) 1096 diff = 0; 1097 1098 if (diff < *uTimeout) 1099 *uTimeout = diff; 1100 } 1101 1102 pCurrent = pCurrent->next; 1103 } 1104 } 1105 1106 /** 1107 * Check if timeout has passed in given list of Slirp timers. 1108 * 1109 * @param opaque Pointer to NAT State context. 1110 * 1111 * @thread ? 1112 */ 1113 static void drvNAT_CheckTimeout(void *opaque) 824 1114 { 825 1115 PDRVNAT pThis = (PDRVNAT)opaque; … … 830 1120 while (pCurrent != NULL) 831 1121 { 832 if (pCurrent->uTimeExpire != -1) 833 { 834 int64_t diff = pCurrent->uTimeExpire - currTime; 835 836 if (diff < 0) 837 diff = 0; 838 839 if (diff < *uTimeout) 840 *uTimeout = diff; 841 } 842 843 pCurrent = pCurrent->next; 844 } 845 } 846 847 /** 848 * Check if timeout has passed in given list of Slirp timers. 849 * 850 * @param opaque Pointer to NAT State context. 851 * 852 * @thread ? 853 */ 854 static void drvNAT_CheckTimeout(void *opaque) 855 { 856 PDRVNAT pThis = (PDRVNAT)opaque; 857 Assert(pThis); 858 859 int64_t currTime = drvNAT_ClockGetNsCb(pThis) / (1000 * 1000); 860 SlirpTimer *pCurrent = pThis->pNATState->pTimerHead; 861 while (pCurrent != NULL) 862 { 863 if (pCurrent->uTimeExpire != -1) 1122 if (pCurrent->uTimeExpire != 0) 864 1123 { 865 1124 int64_t diff = pCurrent->uTimeExpire - currTime; 866 1125 if (diff <= 0) 867 1126 { 868 pCurrent->uTimeExpire = -1;1127 pCurrent->uTimeExpire = 0; 869 1128 pCurrent->pHandler(pCurrent->opaque); 870 1129 } … … 929 1188 } 930 1189 931 /** 1190 1191 /* 932 1192 * Libslirp Callbacks 933 1193 */ … … 1029 1289 1030 1290 pNewTimer->next = pThis->pNATState->pTimerHead; 1031 pNewTimer->uTimeExpire = -1; 1291 pNewTimer->uTimeExpire = -1; /** @todo r=bird: uTimeExpire is unsigned, not signed. Visual C++ barfs at this mixup. */ 1032 1292 pNewTimer->pHandler = slirpTimeCb; 1033 1293 pNewTimer->opaque = cb_opaque; … … 1094 1354 * Registers poll. Unused function (other than logging). 1095 1355 */ 1096 static DECLCALLBACK(void) drvNAT_RegisterPoll(int fd, void *opaque) { 1356 static DECLCALLBACK(void) drvNAT_RegisterPoll(int fd, void *opaque) 1357 { 1097 1358 RT_NOREF(fd, opaque); 1098 1359 Log4(("Poll registered\n")); … … 1102 1363 * Unregisters poll. Unused function (other than logging). 1103 1364 */ 1104 static DECLCALLBACK(void) drvNAT_UnregisterPoll(int fd, void *opaque) { 1365 static DECLCALLBACK(void) drvNAT_UnregisterPoll(int fd, void *opaque) 1366 { 1105 1367 RT_NOREF(fd, opaque); 1106 1368 Log4(("Poll unregistered\n")); … … 1127 1389 int cbNew = pThis->pNATState->uPollCap * 2 * sizeof(struct pollfd); 1128 1390 struct pollfd *pvNew = (struct pollfd *)RTMemRealloc(pThis->pNATState->polls, cbNew); 1129 if (pvNew)1391 if (pvNew) 1130 1392 { 1131 1393 pThis->pNATState->polls = pvNew; … … 1182 1444 PDMDRV_CHECK_VERSIONS_RETURN_VOID(pDrvIns); 1183 1445 1184 if (pThis->pNATState) 1185 { 1186 slirp_cleanup(pThis->pNATState->pSlirp); 1446 SlirpState * const pNATState = pThis->pNATState; 1447 if (pNATState) 1448 { 1449 slirp_cleanup(pNATState->pSlirp); 1450 1187 1451 #ifdef VBOX_WITH_STATISTICS 1188 1452 # define DRV_PROFILE_COUNTER(name, dsc) DEREGISTER_COUNTER(name, pThis) … … 1190 1454 # include "slirp/counters.h" 1191 1455 #endif 1456 RTMemFree(pNATState->polls); 1457 pNATState->polls = NULL; 1458 1459 RTMemFree(pNATState); 1192 1460 pThis->pNATState = NULL; 1193 1461 } … … 1221 1489 static DECLCALLBACK(int) drvNATConstruct(PPDMDRVINS pDrvIns, PCFGMNODE pCfg, uint32_t fFlags) 1222 1490 { 1223 int rc = 0;1224 1225 /* Construct PDRVNAT */1226 1227 1491 RT_NOREF(fFlags); 1228 1492 PDMDRV_CHECK_VERSIONS_RETURN(pDrvIns); 1229 PDRVNAT 1493 PDRVNAT pThis = PDMINS_2_DATA(pDrvIns, PDRVNAT); 1230 1494 1231 1495 /* … … 1233 1497 */ 1234 1498 pThis->pDrvIns = pDrvIns; 1235 pThis->pNATState = (SlirpState *)RTMemAlloc(sizeof(SlirpState)); 1236 if(pThis->pNATState == NULL) 1499 1500 SlirpState * const pNATState = (SlirpState *)RTMemAllocZ(sizeof(*pNATState)); 1501 if (pNATState == NULL) 1237 1502 return VERR_NO_MEMORY; 1238 else1239 {1240 pThis->pNATState->nsock = 0;1241 pThis->pNATState->pTimerHead = NULL;1242 pThis->pNATState->polls = (struct pollfd *)RTMemAlloc(64 * sizeof(struct pollfd));1243 pThis->pNATState->uPollCap= 64;1244 } 1503 pThis->pNATState = pNATState; 1504 pNATState->nsock = 0; 1505 pNATState->pTimerHead = NULL; 1506 pNATState->polls = (struct pollfd *)RTMemAllocZ(64 * sizeof(struct pollfd)); 1507 AssertReturn(pNATState->polls, VERR_NO_MEMORY); 1508 pNATState->uPollCap = 64; 1509 1245 1510 pThis->hSlirpReqQueue = NIL_RTREQQUEUE; 1246 1511 pThis->EventRecv = NIL_RTSEMEVENT; … … 1260 1525 /* NAT engine configuration */ 1261 1526 pThis->INetworkNATCfg.pfnRedirectRuleCommand = drvNATNetworkNatConfigRedirect; 1262 pThis->INetworkNATCfg.pfnNotifyDnsChanged = NULL;1527 pThis->INetworkNATCfg.pfnNotifyDnsChanged = drvNATNotifyDnsChanged; 1263 1528 1264 1529 /* … … 1289 1554 * Get the configuration settings. 1290 1555 */ 1556 int rc; 1291 1557 bool fPassDomain = true; 1292 1558 GET_BOOL(rc, pDrvIns, pCfg, "PassDomain", fPassDomain); … … 1335 1601 1336 1602 RTNETADDRIPV4 Network, Netmask; 1337 1338 1603 rc = RTCidrStrToIPv4(szNetwork, &Network, &Netmask); 1339 1604 if (RT_FAILURE(rc)) … … 1344 1609 /* Construct Libslirp Config and Initialzie Slirp */ 1345 1610 1346 LogFlow(("Here is what is coming out of the vbox config:\n \1347 Network: %lu\n \1348 Netmask: %lu\n", Network, Netmask));1349 1350 #ifndef RT_OS_WINDOWS 1611 LogFlow(("Here is what is coming out of the vbox config:\n" 1612 " Network: %lu\n" 1613 " Netmask: %lu\n", Network, Netmask)); 1614 1615 #ifndef RT_OS_WINDOWS /** @todo r=bird: Why do we need special windows code here?!? */ 1351 1616 struct in_addr vnetwork = RTNetIPv4AddrHEToInAddr(&Network); 1352 1617 struct in_addr vnetmask = RTNetIPv4AddrHEToInAddr(&Netmask); … … 1371 1636 #endif 1372 1637 1638 /** @todo r=bird: This is leaked. It can be a stack structure since libslirp 1639 * only copies values from it and doesn't retain the pointer. */ 1373 1640 SlirpConfig *pSlirpCfg = new SlirpConfig { 0 }; 1374 1641 … … 1398 1665 pSlirpCfg->vdomainname = NULL; 1399 1666 1667 /** @todo r=bird: This is leaked. It can be a static structure. */ 1400 1668 SlirpCb *slirpCallbacks = (struct SlirpCb *)RTMemAlloc(sizeof(SlirpCb)); 1401 1669 … … 1432 1700 1433 1701 rc = PDMDrvHlpThreadCreate(pDrvIns, &pThis->pRecvThread, pThis, drvNATRecv, 1434 1702 drvNATRecvWakeup, 256 * _1K, RTTHREADTYPE_IO, "NATRX"); 1435 1703 AssertRCReturn(rc, rc); 1436 1704 … … 1463 1731 1464 1732 rc = PDMDrvHlpThreadCreate(pDrvIns, &pThis->pSlirpThread, pThis, drvNATAsyncIoThread, 1465 1733 drvNATAsyncIoWakeup, 256 * _1K, RTTHREADTYPE_IO, "NAT"); 1466 1734 AssertRCReturn(rc, rc); 1467 1735
Note:
See TracChangeset
for help on using the changeset viewer.