Add support for PCP on the first hop

This commit is contained in:
Cameron Gutman 2018-11-20 18:09:28 -08:00
parent 5840e39e94
commit c7565256b5
2 changed files with 31 additions and 5 deletions

View File

@ -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);

View File

@ -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;