diff --git a/miss/miss.cpp b/miss/miss.cpp index 5563670..4b73e34 100644 --- a/miss/miss.cpp +++ b/miss/miss.cpp @@ -594,15 +594,29 @@ void UpdatePortMappingsForTarget(bool enable, char* targetAddressIP4, char* inte closenatpmp(&natpmp); } - // Try PCP for IPv4 if UPnP and NAT-PMP have both failed for the non-default gateway router. - // This may be the case for CGN that only supports PCP. - if (tryPcp && targetAddressIP4 != nullptr && internalAddressIP4 != nullptr) { + // Try PCP for IPv4 if UPnP and NAT-PMP have both failed. This may be the case for CGN that only supports PCP. + if (tryPcp) { SOCKADDR_IN targetAddr = {}; SOCKADDR_IN internalAddr = {}; + targetAddr.sin_family = AF_INET; - targetAddr.sin_addr.S_un.S_addr = inet_addr(targetAddressIP4); internalAddr.sin_family = AF_INET; - internalAddr.sin_addr.S_un.S_addr = inet_addr(internalAddressIP4); + + if (targetAddressIP4 != nullptr && internalAddressIP4 != nullptr) { + targetAddr.sin_addr.S_un.S_addr = inet_addr(targetAddressIP4); + internalAddr.sin_addr.S_un.S_addr = inet_addr(internalAddressIP4); + } + else { + MIB_IPFORWARDROW route; + DWORD error = GetBestRoute(0, 0, &route); + if (error == NO_ERROR) { + targetAddr.sin_addr.S_un.S_addr = route.dwForwardNextHop; + } + else { + printf("GetBestRoute() failed: %d" NL, error); + goto Exit; + } + } bool success = true; for (int i = 0; i < ARRAYSIZE(k_Ports); i++) { @@ -631,6 +645,7 @@ void UpdatePortMappingsForTarget(bool enable, char* targetAddressIP4, char* inte } } +Exit: // Write this at the end to avoid clobbering an input parameter if (upstreamAddrNatPmp[0] != 0 && inet_addr(upstreamAddrNatPmp) != 0) { printf("Using NAT-PMP upstream IPv4 address: %s" NL, upstreamAddrNatPmp); diff --git a/miss/pcp.cpp b/miss/pcp.cpp index e774e08..e4100c6 100644 --- a/miss/pcp.cpp +++ b/miss/pcp.cpp @@ -160,6 +160,17 @@ bool PCPMapPort(PSOCKADDR_STORAGE localAddr, int localAddrLen, PSOCKADDR_STORAGE return false; } + // If we didn't get a local address, use the address of the interface we bound to. + // NB: We can't do this in all cases because we may be impersonating an upstream + // device if we're behind multiple NATs. + if (localAddr->ss_family == AF_INET && ((PSOCKADDR_IN)localAddr)->sin_addr.S_un.S_addr == 0) { + if (getsockname(sock, (struct sockaddr*)localAddr, &localAddrLen) == SOCKET_ERROR) { + printf("getsockname() failed: %d\n", WSAGetLastError()); + closesocket(sock); + return false; + } + } + reqMsg = {}; reqMsg.hdr.version = PCP_VERSION; reqMsg.hdr.opcode = OPCODE_MAP_REQUEST;