pcp.cpp
1 // Copyright (c) 2024-present The Bitcoin Core developers 2 // Distributed under the MIT software license, see the accompanying 3 // file COPYING or https://www.opensource.org/licenses/mit-license.php. 4 5 #include <common/pcp.h> 6 7 #include <atomic> 8 #include <common/netif.h> 9 #include <crypto/common.h> 10 #include <logging.h> 11 #include <netaddress.h> 12 #include <netbase.h> 13 #include <random.h> 14 #include <span.h> 15 #include <util/check.h> 16 #include <util/readwritefile.h> 17 #include <util/sock.h> 18 #include <util/strencodings.h> 19 #include <util/threadinterrupt.h> 20 21 namespace { 22 23 // RFC6886 NAT-PMP and RFC6887 Port Control Protocol (PCP) implementation. 24 // NAT-PMP and PCP use network byte order (big-endian). 25 26 // NAT-PMP (v0) protocol constants. 27 //! NAT-PMP uses a fixed server port number (RFC6887 section 1.1). 28 constexpr uint16_t NATPMP_SERVER_PORT = 5351; 29 //! Version byte for NATPMP (RFC6886 1.1) 30 constexpr uint8_t NATPMP_VERSION = 0; 31 //! Request opcode base (RFC6886 3). 32 constexpr uint8_t NATPMP_REQUEST = 0x00; 33 //! Response opcode base (RFC6886 3). 34 constexpr uint8_t NATPMP_RESPONSE = 0x80; 35 //! Get external address (RFC6886 3.2) 36 constexpr uint8_t NATPMP_OP_GETEXTERNAL = 0x00; 37 //! Map TCP port (RFC6886 3.3) 38 constexpr uint8_t NATPMP_OP_MAP_TCP = 0x02; 39 //! Shared request header size in bytes. 40 constexpr size_t NATPMP_REQUEST_HDR_SIZE = 2; 41 //! Shared response header (minimum) size in bytes. 42 constexpr size_t NATPMP_RESPONSE_HDR_SIZE = 8; 43 //! GETEXTERNAL request size in bytes, including header (RFC6886 3.2). 44 constexpr size_t NATPMP_GETEXTERNAL_REQUEST_SIZE = NATPMP_REQUEST_HDR_SIZE + 0; 45 //! GETEXTERNAL response size in bytes, including header (RFC6886 3.2). 46 constexpr size_t NATPMP_GETEXTERNAL_RESPONSE_SIZE = NATPMP_RESPONSE_HDR_SIZE + 4; 47 //! MAP request size in bytes, including header (RFC6886 3.3). 48 constexpr size_t NATPMP_MAP_REQUEST_SIZE = NATPMP_REQUEST_HDR_SIZE + 10; 49 //! MAP response size in bytes, including header (RFC6886 3.3). 50 constexpr size_t NATPMP_MAP_RESPONSE_SIZE = NATPMP_RESPONSE_HDR_SIZE + 8; 51 52 // Shared header offsets (RFC6886 3.2, 3.3), relative to start of packet. 53 //! Offset of version field in packets. 54 constexpr size_t NATPMP_HDR_VERSION_OFS = 0; 55 //! Offset of opcode field in packets 56 constexpr size_t NATPMP_HDR_OP_OFS = 1; 57 //! Offset of result code in packets. Result codes are 16 bit in NAT-PMP instead of 8 bit in PCP. 58 constexpr size_t NATPMP_RESPONSE_HDR_RESULT_OFS = 2; 59 60 // GETEXTERNAL response offsets (RFC6886 3.2), relative to start of packet. 61 //! Returned external address 62 constexpr size_t NATPMP_GETEXTERNAL_RESPONSE_IP_OFS = 8; 63 64 // MAP request offsets (RFC6886 3.3), relative to start of packet. 65 //! Internal port to be mapped. 66 constexpr size_t NATPMP_MAP_REQUEST_INTERNAL_PORT_OFS = 4; 67 //! Suggested external port for mapping. 68 constexpr size_t NATPMP_MAP_REQUEST_EXTERNAL_PORT_OFS = 6; 69 //! Requested port mapping lifetime in seconds. 70 constexpr size_t NATPMP_MAP_REQUEST_LIFETIME_OFS = 8; 71 72 // MAP response offsets (RFC6886 3.3), relative to start of packet. 73 //! Internal port for mapping (will match internal port of request). 74 constexpr size_t NATPMP_MAP_RESPONSE_INTERNAL_PORT_OFS = 8; 75 //! External port for mapping. 76 constexpr size_t NATPMP_MAP_RESPONSE_EXTERNAL_PORT_OFS = 10; 77 //! Created port mapping lifetime in seconds. 78 constexpr size_t NATPMP_MAP_RESPONSE_LIFETIME_OFS = 12; 79 80 // Relevant NETPMP result codes (RFC6886 3.5). 81 //! Result code representing success status. 82 constexpr uint8_t NATPMP_RESULT_SUCCESS = 0; 83 //! Result code representing unsupported version. 84 constexpr uint8_t NATPMP_RESULT_UNSUPP_VERSION = 1; 85 //! Result code representing not authorized (router doesn't support port mapping). 86 constexpr uint8_t NATPMP_RESULT_NOT_AUTHORIZED = 2; 87 //! Result code representing lack of resources. 88 constexpr uint8_t NATPMP_RESULT_NO_RESOURCES = 4; 89 90 //! Mapping of NATPMP result code to string (RFC6886 3.5). Result codes <=2 match PCP. 91 const std::map<uint16_t, std::string> NATPMP_RESULT_STR{ 92 {0, "SUCCESS"}, 93 {1, "UNSUPP_VERSION"}, 94 {2, "NOT_AUTHORIZED"}, 95 {3, "NETWORK_FAILURE"}, 96 {4, "NO_RESOURCES"}, 97 {5, "UNSUPP_OPCODE"}, 98 }; 99 100 // PCP (v2) protocol constants. 101 //! Maximum packet size in bytes (RFC6887 section 7). 102 constexpr size_t PCP_MAX_SIZE = 1100; 103 //! PCP uses a fixed server port number (RFC6887 section 19.1). Shared with NAT-PMP. 104 constexpr uint16_t PCP_SERVER_PORT = NATPMP_SERVER_PORT; 105 //! Version byte. 0 is NAT-PMP (RFC6886), 1 is forbidden, 2 for PCP (RFC6887). 106 constexpr uint8_t PCP_VERSION = 2; 107 //! PCP Request Header. See RFC6887 section 7.1. Shared with NAT-PMP. 108 constexpr uint8_t PCP_REQUEST = NATPMP_REQUEST; // R = 0 109 //! PCP Response Header. See RFC6887 section 7.2. Shared with NAT-PMP. 110 constexpr uint8_t PCP_RESPONSE = NATPMP_RESPONSE; // R = 1 111 //! Map opcode. See RFC6887 section 19.2 112 constexpr uint8_t PCP_OP_MAP = 0x01; 113 //! TCP protocol number (IANA). 114 constexpr uint16_t PCP_PROTOCOL_TCP = 6; 115 //! Request and response header size in bytes (RFC6887 section 7.1). 116 constexpr size_t PCP_HDR_SIZE = 24; 117 //! Map request and response size in bytes (RFC6887 section 11.1). 118 constexpr size_t PCP_MAP_SIZE = 36; 119 120 // Header offsets shared between request and responses (RFC6887 7.1, 7.2), relative to start of packet. 121 //! Version field (1 byte). 122 constexpr size_t PCP_HDR_VERSION_OFS = NATPMP_HDR_VERSION_OFS; 123 //! Opcode field (1 byte). 124 constexpr size_t PCP_HDR_OP_OFS = NATPMP_HDR_OP_OFS; 125 //! Requested lifetime (request), granted lifetime (response) (4 bytes). 126 constexpr size_t PCP_HDR_LIFETIME_OFS = 4; 127 128 // Request header offsets (RFC6887 7.1), relative to start of packet. 129 //! PCP client's IP address (16 bytes). 130 constexpr size_t PCP_REQUEST_HDR_IP_OFS = 8; 131 132 // Response header offsets (RFC6887 7.2), relative to start of packet. 133 //! Result code (1 byte). 134 constexpr size_t PCP_RESPONSE_HDR_RESULT_OFS = 3; 135 136 // MAP request/response offsets (RFC6887 11.1), relative to start of opcode-specific data. 137 //! Mapping nonce (12 bytes). 138 constexpr size_t PCP_MAP_NONCE_OFS = 0; 139 //! Protocol (1 byte). 140 constexpr size_t PCP_MAP_PROTOCOL_OFS = 12; 141 //! Internal port for mapping (2 bytes). 142 constexpr size_t PCP_MAP_INTERNAL_PORT_OFS = 16; 143 //! Suggested external port (request), assigned external port (response) (2 bytes). 144 constexpr size_t PCP_MAP_EXTERNAL_PORT_OFS = 18; 145 //! Suggested external IP (request), assigned external IP (response) (16 bytes). 146 constexpr size_t PCP_MAP_EXTERNAL_IP_OFS = 20; 147 148 //! Result code representing success (RFC6887 7.4), shared with NAT-PMP. 149 constexpr uint8_t PCP_RESULT_SUCCESS = NATPMP_RESULT_SUCCESS; 150 //! Result code representing not authorized (RFC6887 7.4), shared with NAT-PMP. 151 constexpr uint8_t PCP_RESULT_NOT_AUTHORIZED = NATPMP_RESULT_NOT_AUTHORIZED; 152 //! Result code representing lack of resources (RFC6887 7.4). 153 constexpr uint8_t PCP_RESULT_NO_RESOURCES = 8; 154 155 //! Mapping of PCP result code to string (RFC6887 7.4). Result codes <=2 match NAT-PMP. 156 const std::map<uint8_t, std::string> PCP_RESULT_STR{ 157 {0, "SUCCESS"}, 158 {1, "UNSUPP_VERSION"}, 159 {2, "NOT_AUTHORIZED"}, 160 {3, "MALFORMED_REQUEST"}, 161 {4, "UNSUPP_OPCODE"}, 162 {5, "UNSUPP_OPTION"}, 163 {6, "MALFORMED_OPTION"}, 164 {7, "NETWORK_FAILURE"}, 165 {8, "NO_RESOURCES"}, 166 {9, "UNSUPP_PROTOCOL"}, 167 {10, "USER_EX_QUOTA"}, 168 {11, "CANNOT_PROVIDE_EXTERNAL"}, 169 {12, "ADDRESS_MISMATCH"}, 170 {13, "EXCESSIVE_REMOTE_PEER"}, 171 }; 172 173 //! Return human-readable string from NATPMP result code. 174 std::string NATPMPResultString(uint16_t result_code) 175 { 176 auto result_i = NATPMP_RESULT_STR.find(result_code); 177 return strprintf("%s (code %d)", result_i == NATPMP_RESULT_STR.end() ? "(unknown)" : result_i->second, result_code); 178 } 179 180 //! Return human-readable string from PCP result code. 181 std::string PCPResultString(uint8_t result_code) 182 { 183 auto result_i = PCP_RESULT_STR.find(result_code); 184 return strprintf("%s (code %d)", result_i == PCP_RESULT_STR.end() ? "(unknown)" : result_i->second, result_code); 185 } 186 187 //! Wrap address in IPv6 according to RFC6887. wrapped_addr needs to be able to store 16 bytes. 188 [[nodiscard]] bool PCPWrapAddress(std::span<uint8_t> wrapped_addr, const CNetAddr &addr) 189 { 190 Assume(wrapped_addr.size() == ADDR_IPV6_SIZE); 191 if (addr.IsIPv4()) { 192 struct in_addr addr4; 193 if (!addr.GetInAddr(&addr4)) return false; 194 // Section 5: "When the address field holds an IPv4 address, an IPv4-mapped IPv6 address [RFC4291] is used (::ffff:0:0/96)." 195 std::memcpy(wrapped_addr.data(), IPV4_IN_IPV6_PREFIX.data(), IPV4_IN_IPV6_PREFIX.size()); 196 std::memcpy(wrapped_addr.data() + IPV4_IN_IPV6_PREFIX.size(), &addr4, ADDR_IPV4_SIZE); 197 return true; 198 } else if (addr.IsIPv6()) { 199 struct in6_addr addr6; 200 if (!addr.GetIn6Addr(&addr6)) return false; 201 std::memcpy(wrapped_addr.data(), &addr6, ADDR_IPV6_SIZE); 202 return true; 203 } else { 204 return false; 205 } 206 } 207 208 //! Unwrap PCP-encoded address according to RFC6887. 209 CNetAddr PCPUnwrapAddress(std::span<const uint8_t> wrapped_addr) 210 { 211 Assume(wrapped_addr.size() == ADDR_IPV6_SIZE); 212 if (util::HasPrefix(wrapped_addr, IPV4_IN_IPV6_PREFIX)) { 213 struct in_addr addr4; 214 std::memcpy(&addr4, wrapped_addr.data() + IPV4_IN_IPV6_PREFIX.size(), ADDR_IPV4_SIZE); 215 return CNetAddr(addr4); 216 } else { 217 struct in6_addr addr6; 218 std::memcpy(&addr6, wrapped_addr.data(), ADDR_IPV6_SIZE); 219 return CNetAddr(addr6); 220 } 221 } 222 223 //! PCP or NAT-PMP send-receive loop. 224 std::optional<std::vector<uint8_t>> PCPSendRecv(Sock &sock, const std::string &protocol, std::span<const uint8_t> request, int num_tries, 225 std::chrono::milliseconds timeout_per_try, 226 std::function<bool(std::span<const uint8_t>)> check_packet, 227 CThreadInterrupt& interrupt) 228 { 229 using namespace std::chrono; 230 // UDP is a potentially lossy protocol, so we try to send again a few times. 231 uint8_t response[PCP_MAX_SIZE]; 232 bool got_response = false; 233 int recvsz = 0; 234 for (int ntry = 0; !got_response && ntry < num_tries; ++ntry) { 235 if (ntry > 0) { 236 LogDebug(BCLog::NET, "%s: Retrying (%d)\n", protocol, ntry); 237 } 238 // Dispatch packet to gateway. 239 if (sock.Send(request.data(), request.size(), 0) != static_cast<ssize_t>(request.size())) { 240 LogDebug(BCLog::NET, "%s: Could not send request: %s\n", protocol, NetworkErrorString(WSAGetLastError())); 241 return std::nullopt; // Network-level error, probably no use retrying. 242 } 243 244 // Wait for response(s) until we get a valid response, a network error, or time out. 245 auto cur_time = time_point_cast<milliseconds>(MockableSteadyClock::now()); 246 auto deadline = cur_time + timeout_per_try; 247 while ((cur_time = time_point_cast<milliseconds>(MockableSteadyClock::now())) < deadline) { 248 if (interrupt) return std::nullopt; 249 Sock::Event occurred = 0; 250 if (!sock.Wait(deadline - cur_time, Sock::RECV, &occurred)) { 251 LogWarning("%s: Could not wait on socket: %s\n", protocol, NetworkErrorString(WSAGetLastError())); 252 return std::nullopt; // Network-level error, probably no use retrying. 253 } 254 if (!occurred) { 255 LogDebug(BCLog::NET, "%s: Timeout\n", protocol); 256 break; // Retry. 257 } 258 259 // Receive response. 260 recvsz = sock.Recv(response, sizeof(response), MSG_DONTWAIT); 261 if (recvsz < 0) { 262 LogDebug(BCLog::NET, "%s: Could not receive response: %s\n", protocol, NetworkErrorString(WSAGetLastError())); 263 return std::nullopt; // Network-level error, probably no use retrying. 264 } 265 LogDebug(BCLog::NET, "%s: Received response of %d bytes: %s\n", protocol, recvsz, HexStr(std::span(response, recvsz))); 266 267 if (check_packet(std::span<uint8_t>(response, recvsz))) { 268 got_response = true; // Got expected response, break from receive loop as well as from retry loop. 269 break; 270 } 271 } 272 } 273 if (!got_response) { 274 LogDebug(BCLog::NET, "%s: Giving up after %d tries\n", protocol, num_tries); 275 return std::nullopt; 276 } 277 return std::vector<uint8_t>(response, response + recvsz); 278 } 279 280 } 281 282 std::variant<MappingResult, MappingError> NATPMPRequestPortMap(const CNetAddr &gateway, uint16_t port, uint32_t lifetime, CThreadInterrupt& interrupt, int num_tries, std::chrono::milliseconds timeout_per_try) 283 { 284 struct sockaddr_storage dest_addr; 285 socklen_t dest_addrlen = sizeof(struct sockaddr_storage); 286 287 LogDebug(BCLog::NET, "natpmp: Requesting port mapping port %d from gateway %s\n", port, gateway.ToStringAddr()); 288 289 // Validate gateway, make sure it's IPv4. NAT-PMP does not support IPv6. 290 if (!CService(gateway, PCP_SERVER_PORT).GetSockAddr((struct sockaddr*)&dest_addr, &dest_addrlen)) return MappingError::NETWORK_ERROR; 291 if (dest_addr.ss_family != AF_INET) return MappingError::NETWORK_ERROR; 292 293 // Create IPv4 UDP socket 294 auto sock{CreateSock(AF_INET, SOCK_DGRAM, IPPROTO_UDP)}; 295 if (!sock) { 296 LogWarning("natpmp: Could not create UDP socket: %s\n", NetworkErrorString(WSAGetLastError())); 297 return MappingError::NETWORK_ERROR; 298 } 299 300 // Associate UDP socket to gateway. 301 if (sock->Connect((struct sockaddr*)&dest_addr, dest_addrlen) != 0) { 302 LogWarning("natpmp: Could not connect to gateway: %s\n", NetworkErrorString(WSAGetLastError())); 303 return MappingError::NETWORK_ERROR; 304 } 305 306 // Use getsockname to get the address toward the default gateway (the internal address). 307 struct sockaddr_in internal; 308 socklen_t internal_addrlen = sizeof(struct sockaddr_in); 309 if (sock->GetSockName((struct sockaddr*)&internal, &internal_addrlen) != 0) { 310 LogWarning("natpmp: Could not get sock name: %s\n", NetworkErrorString(WSAGetLastError())); 311 return MappingError::NETWORK_ERROR; 312 } 313 314 // Request external IP address (RFC6886 section 3.2). 315 std::vector<uint8_t> request(NATPMP_GETEXTERNAL_REQUEST_SIZE); 316 request[NATPMP_HDR_VERSION_OFS] = NATPMP_VERSION; 317 request[NATPMP_HDR_OP_OFS] = NATPMP_REQUEST | NATPMP_OP_GETEXTERNAL; 318 319 auto recv_res = PCPSendRecv(*sock, "natpmp", request, num_tries, timeout_per_try, 320 [&](const std::span<const uint8_t> response) -> bool { 321 if (response.size() < NATPMP_GETEXTERNAL_RESPONSE_SIZE) { 322 LogWarning("natpmp: Response too small\n"); 323 return false; // Wasn't response to what we expected, try receiving next packet. 324 } 325 if (response[NATPMP_HDR_VERSION_OFS] != NATPMP_VERSION || response[NATPMP_HDR_OP_OFS] != (NATPMP_RESPONSE | NATPMP_OP_GETEXTERNAL)) { 326 LogWarning("natpmp: Response to wrong command\n"); 327 return false; // Wasn't response to what we expected, try receiving next packet. 328 } 329 return true; 330 }, 331 interrupt); 332 333 struct in_addr external_addr; 334 if (recv_res) { 335 const std::span<const uint8_t> response = *recv_res; 336 337 Assume(response.size() >= NATPMP_GETEXTERNAL_RESPONSE_SIZE); 338 uint16_t result_code = ReadBE16(response.data() + NATPMP_RESPONSE_HDR_RESULT_OFS); 339 if (result_code != NATPMP_RESULT_SUCCESS) { 340 LogWarning("natpmp: Getting external address failed with result %s\n", NATPMPResultString(result_code)); 341 return MappingError::PROTOCOL_ERROR; 342 } 343 344 std::memcpy(&external_addr, response.data() + NATPMP_GETEXTERNAL_RESPONSE_IP_OFS, ADDR_IPV4_SIZE); 345 } else { 346 return MappingError::NETWORK_ERROR; 347 } 348 349 // Create TCP mapping request (RFC6886 section 3.3). 350 request = std::vector<uint8_t>(NATPMP_MAP_REQUEST_SIZE); 351 request[NATPMP_HDR_VERSION_OFS] = NATPMP_VERSION; 352 request[NATPMP_HDR_OP_OFS] = NATPMP_REQUEST | NATPMP_OP_MAP_TCP; 353 WriteBE16(request.data() + NATPMP_MAP_REQUEST_INTERNAL_PORT_OFS, port); 354 WriteBE16(request.data() + NATPMP_MAP_REQUEST_EXTERNAL_PORT_OFS, port); 355 WriteBE32(request.data() + NATPMP_MAP_REQUEST_LIFETIME_OFS, lifetime); 356 357 recv_res = PCPSendRecv(*sock, "natpmp", request, num_tries, timeout_per_try, 358 [&](const std::span<const uint8_t> response) -> bool { 359 if (response.size() < NATPMP_MAP_RESPONSE_SIZE) { 360 LogWarning("natpmp: Response too small\n"); 361 return false; // Wasn't response to what we expected, try receiving next packet. 362 } 363 if (response[0] != NATPMP_VERSION || response[1] != (NATPMP_RESPONSE | NATPMP_OP_MAP_TCP)) { 364 LogWarning("natpmp: Response to wrong command\n"); 365 return false; // Wasn't response to what we expected, try receiving next packet. 366 } 367 uint16_t internal_port = ReadBE16(response.data() + NATPMP_MAP_RESPONSE_INTERNAL_PORT_OFS); 368 if (internal_port != port) { 369 LogWarning("natpmp: Response port doesn't match request\n"); 370 return false; // Wasn't response to what we expected, try receiving next packet. 371 } 372 return true; 373 }, 374 interrupt); 375 376 if (recv_res) { 377 const std::span<uint8_t> response = *recv_res; 378 379 Assume(response.size() >= NATPMP_MAP_RESPONSE_SIZE); 380 uint16_t result_code = ReadBE16(response.data() + NATPMP_RESPONSE_HDR_RESULT_OFS); 381 if (result_code != NATPMP_RESULT_SUCCESS) { 382 if (result_code == NATPMP_RESULT_NOT_AUTHORIZED) { 383 static std::atomic<bool> warned{false}; 384 if (!warned.exchange(true)) { 385 LogWarning("natpmp: Port mapping failed with result %s\n", NATPMPResultString(result_code)); 386 } else { 387 LogDebug(BCLog::NET, "natpmp: Port mapping failed with result %s\n", NATPMPResultString(result_code)); 388 } 389 } else { 390 LogWarning("natpmp: Port mapping failed with result %s\n", NATPMPResultString(result_code)); 391 } 392 if (result_code == NATPMP_RESULT_NO_RESOURCES) { 393 return MappingError::NO_RESOURCES; 394 } 395 return MappingError::PROTOCOL_ERROR; 396 } 397 398 uint32_t lifetime_ret = ReadBE32(response.data() + NATPMP_MAP_RESPONSE_LIFETIME_OFS); 399 uint16_t external_port = ReadBE16(response.data() + NATPMP_MAP_RESPONSE_EXTERNAL_PORT_OFS); 400 return MappingResult(NATPMP_VERSION, CService(internal.sin_addr, port), CService(external_addr, external_port), lifetime_ret); 401 } else { 402 return MappingError::NETWORK_ERROR; 403 } 404 } 405 406 std::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 464 // Fill in MAP request packet, See RFC6887 Figure 9. 465 // Randomize mapping nonce (this is repeated in the response, to be able to 466 // correlate requests and responses, and used to authenticate changes to the mapping). 467 std::memcpy(request.data() + ofs + PCP_MAP_NONCE_OFS, nonce.data(), PCP_MAP_NONCE_SIZE); 468 request[ofs + PCP_MAP_PROTOCOL_OFS] = PCP_PROTOCOL_TCP; 469 WriteBE16(request.data() + ofs + PCP_MAP_INTERNAL_PORT_OFS, port); 470 WriteBE16(request.data() + ofs + PCP_MAP_EXTERNAL_PORT_OFS, port); 471 if (!PCPWrapAddress(std::span(request).subspan(ofs + PCP_MAP_EXTERNAL_IP_OFS, ADDR_IPV6_SIZE), bind)) return MappingError::NETWORK_ERROR; 472 473 ofs += PCP_MAP_SIZE; 474 Assume(ofs == request.size()); 475 476 // Receive loop. 477 bool is_natpmp = false; 478 auto recv_res = PCPSendRecv(*sock, "pcp", request, num_tries, timeout_per_try, 479 [&](const std::span<const uint8_t> response) -> bool { 480 // Unsupported version according to RFC6887 appendix A and RFC6886 section 3.5, can fall back to NAT-PMP. 481 if (response.size() == NATPMP_RESPONSE_HDR_SIZE && response[PCP_HDR_VERSION_OFS] == NATPMP_VERSION && response[PCP_RESPONSE_HDR_RESULT_OFS] == NATPMP_RESULT_UNSUPP_VERSION) { 482 is_natpmp = true; 483 return true; // Let it through to caller. 484 } 485 if (response.size() < (PCP_HDR_SIZE + PCP_MAP_SIZE)) { 486 LogWarning("pcp: Response too small\n"); 487 return false; // Wasn't response to what we expected, try receiving next packet. 488 } 489 if (response[PCP_HDR_VERSION_OFS] != PCP_VERSION || response[PCP_HDR_OP_OFS] != (PCP_RESPONSE | PCP_OP_MAP)) { 490 LogWarning("pcp: Response to wrong command\n"); 491 return false; // Wasn't response to what we expected, try receiving next packet. 492 } 493 // Handle MAP opcode response. See RFC6887 Figure 10. 494 // Check that returned mapping nonce matches our request. 495 if (!std::ranges::equal(response.subspan(PCP_HDR_SIZE + PCP_MAP_NONCE_OFS, PCP_MAP_NONCE_SIZE), nonce)) { 496 LogWarning("pcp: Mapping nonce mismatch\n"); 497 return false; // Wasn't response to what we expected, try receiving next packet. 498 } 499 uint8_t protocol = response[PCP_HDR_SIZE + 12]; 500 uint16_t internal_port = ReadBE16(response.data() + PCP_HDR_SIZE + 16); 501 if (protocol != PCP_PROTOCOL_TCP || internal_port != port) { 502 LogWarning("pcp: Response protocol or port doesn't match request\n"); 503 return false; // Wasn't response to what we expected, try receiving next packet. 504 } 505 return true; 506 }, 507 interrupt); 508 509 if (!recv_res) { 510 return MappingError::NETWORK_ERROR; 511 } 512 if (is_natpmp) { 513 return MappingError::UNSUPP_VERSION; 514 } 515 516 const std::span<const uint8_t> response = *recv_res; 517 // If we get here, we got a valid MAP response to our request. 518 // Check to see if we got the result we expected. 519 Assume(response.size() >= (PCP_HDR_SIZE + PCP_MAP_SIZE)); 520 uint8_t result_code = response[PCP_RESPONSE_HDR_RESULT_OFS]; 521 uint32_t lifetime_ret = ReadBE32(response.data() + PCP_HDR_LIFETIME_OFS); 522 uint16_t external_port = ReadBE16(response.data() + PCP_HDR_SIZE + PCP_MAP_EXTERNAL_PORT_OFS); 523 CNetAddr external_addr{PCPUnwrapAddress(response.subspan(PCP_HDR_SIZE + PCP_MAP_EXTERNAL_IP_OFS, ADDR_IPV6_SIZE))}; 524 if (result_code != PCP_RESULT_SUCCESS) { 525 if (result_code == PCP_RESULT_NOT_AUTHORIZED) { 526 static std::atomic<bool> warned{false}; 527 if (!warned.exchange(true)) { 528 LogWarning("pcp: Mapping failed with result %s\n", PCPResultString(result_code)); 529 } else { 530 LogDebug(BCLog::NET, "pcp: Mapping failed with result %s\n", PCPResultString(result_code)); 531 } 532 } else { 533 LogWarning("pcp: Mapping failed with result %s\n", PCPResultString(result_code)); 534 } 535 if (result_code == PCP_RESULT_NO_RESOURCES) { 536 return MappingError::NO_RESOURCES; 537 } 538 return MappingError::PROTOCOL_ERROR; 539 } 540 541 return MappingResult(PCP_VERSION, CService(internal, port), CService(external_addr, external_port), lifetime_ret); 542 } 543 544 std::string MappingResult::ToString() const 545 { 546 Assume(version == NATPMP_VERSION || version == PCP_VERSION); 547 return strprintf("%s:%s -> %s (for %ds)", 548 version == NATPMP_VERSION ? "natpmp" : "pcp", 549 external.ToStringAddrPort(), 550 internal.ToStringAddrPort(), 551 lifetime 552 ); 553 }