MCPcopy Create free account
hub / github.com/bitcoin/bitcoin / PCPRequestPortMap

Function PCPRequestPortMap

src/common/pcp.cpp:406–542  ·  view source on GitHub ↗

Source from the content-addressed store, hash-verified

404}
405
406std::variant<MappingResult, MappingError> PCPRequestPortMap(const PCPMappingNonce &nonce, const CNetAddr &gateway, const CNetAddr &bind, uint16_t port, uint32_t lifetime, CThreadInterrupt& interrupt, int num_tries, std::chrono::milliseconds timeout_per_try)
407{
408 struct sockaddr_storage dest_addr, bind_addr;
409 socklen_t dest_addrlen = sizeof(struct sockaddr_storage), bind_addrlen = sizeof(struct sockaddr_storage);
410
411 LogDebug(BCLog::NET, "pcp: Requesting port mapping for addr %s port %d from gateway %s\n", bind.ToStringAddr(), port, gateway.ToStringAddr());
412
413 // Validate addresses, make sure they're the same network family.
414 if (!CService(gateway, PCP_SERVER_PORT).GetSockAddr((struct sockaddr*)&dest_addr, &dest_addrlen)) return MappingError::NETWORK_ERROR;
415 if (!CService(bind, 0).GetSockAddr((struct sockaddr*)&bind_addr, &bind_addrlen)) return MappingError::NETWORK_ERROR;
416 if (dest_addr.ss_family != bind_addr.ss_family) return MappingError::NETWORK_ERROR;
417
418 // Create UDP socket (IPv4 or IPv6 based on provided gateway).
419 auto sock{CreateSock(dest_addr.ss_family, SOCK_DGRAM, IPPROTO_UDP)};
420 if (!sock) {
421 LogWarning("pcp: Could not create UDP socket: %s\n", NetworkErrorString(WSAGetLastError()));
422 return MappingError::NETWORK_ERROR;
423 }
424
425 // Make sure that we send from requested destination address, anything else will be
426 // rejected by a security-conscious router.
427 if (sock->Bind((struct sockaddr*)&bind_addr, bind_addrlen) != 0) {
428 LogWarning("pcp: Could not bind to address: %s\n", NetworkErrorString(WSAGetLastError()));
429 return MappingError::NETWORK_ERROR;
430 }
431
432 // Associate UDP socket to gateway.
433 if (sock->Connect((struct sockaddr*)&dest_addr, dest_addrlen) != 0) {
434 LogWarning("pcp: Could not connect to gateway: %s\n", NetworkErrorString(WSAGetLastError()));
435 return MappingError::NETWORK_ERROR;
436 }
437
438 // Use getsockname to get the address toward the default gateway (the internal address),
439 // in case we don't know what address to map
440 // (this is only needed if bind is INADDR_ANY, but it doesn't hurt as an extra check).
441 struct sockaddr_storage internal_addr;
442 socklen_t internal_addrlen = sizeof(struct sockaddr_storage);
443 if (sock->GetSockName((struct sockaddr*)&internal_addr, &internal_addrlen) != 0) {
444 LogWarning("pcp: Could not get sock name: %s\n", NetworkErrorString(WSAGetLastError()));
445 return MappingError::NETWORK_ERROR;
446 }
447 CService internal;
448 if (!internal.SetSockAddr((struct sockaddr*)&internal_addr, internal_addrlen)) return MappingError::NETWORK_ERROR;
449 LogDebug(BCLog::NET, "pcp: Internal address after connect: %s\n", internal.ToStringAddr());
450
451 // Build request packet. Make sure the packet is zeroed so that reserved fields are zero
452 // as required by the spec (and not potentially leak data).
453 // Make sure there's space for the request header and MAP specific request data.
454 std::vector<uint8_t> request(PCP_HDR_SIZE + PCP_MAP_SIZE);
455 // Fill in request header, See RFC6887 Figure 2.
456 size_t ofs = 0;
457 request[ofs + PCP_HDR_VERSION_OFS] = PCP_VERSION;
458 request[ofs + PCP_HDR_OP_OFS] = PCP_REQUEST | PCP_OP_MAP;
459 WriteBE32(request.data() + ofs + PCP_HDR_LIFETIME_OFS, lifetime);
460 if (!PCPWrapAddress(std::span(request).subspan(ofs + PCP_REQUEST_HDR_IP_OFS, ADDR_IPV6_SIZE), internal)) return MappingError::NETWORK_ERROR;
461
462 ofs += PCP_HDR_SIZE;
463

Callers 3

ProcessPCPFunction · 0.85
BOOST_AUTO_TEST_CASEFunction · 0.85
pcp.cppFile · 0.85

Calls 15

CServiceClass · 0.85
NetworkErrorStringFunction · 0.85
WriteBE32Function · 0.85
PCPWrapAddressFunction · 0.85
WriteBE16Function · 0.85
PCPSendRecvFunction · 0.85
ReadBE16Function · 0.85
ReadBE32Function · 0.85
PCPUnwrapAddressFunction · 0.85
PCPResultStringFunction · 0.85
MappingResultClass · 0.85
ToStringAddrMethod · 0.80

Tested by 1

BOOST_AUTO_TEST_CASEFunction · 0.68