net: reduce log level for PCP/NAT-PMP NOT_AUTHORIZED failures
What changed, and why it matters
This change is purely cosmetic: it stops Bitcoin Core from repeatedly printing the same router-related warning in the log. Home routers that don't support automatic port mapping now produce one warning instead of many, with later messages hidden behind a debug log level. There is no security vulnerability being fixed and no behavior of the network code is changed.
No security action needed. Treat as a normal log-quality improvement.
Security signals we found
No strong security signals were identified.
Evidence from the diff
The commit adds named constants for the NAT-PMP/PCP NOT_AUTHORIZED result code (value 2) and downgrades repeated NOT_AUTHORIZED log messages from LogWarning to LogDebug after the first occurrence. The actual port-mapping logic, error handling, and return values are unchanged. It is a log-noise reduction patch, not a security fix.
Changed components
src/common/pcp.cppInspect captured patch +25 / −2
diff --git a/src/common/pcp.cpp b/src/common/pcp.cpp
index 4864136b..a640b823 100644
--- a/src/common/pcp.cpp
+++ b/src/common/pcp.cpp
@@ -4,6 +4,7 @@
#include <common/pcp.h>
+#include <atomic>
#include <common/netif.h>
#include <crypto/common.h>
#include <logging.h>
@@ -81,6 +82,8 @@ constexpr size_t NATPMP_MAP_RESPONSE_LIFETIME_OFS = 12;
constexpr uint8_t NATPMP_RESULT_SUCCESS = 0;
//! Result code representing unsupported version.
constexpr uint8_t NATPMP_RESULT_UNSUPP_VERSION = 1;
+//! Result code representing not authorized (router doesn't support port mapping).
+constexpr uint8_t NATPMP_RESULT_NOT_AUTHORIZED = 2;
//! Result code representing lack of resources.
constexpr uint8_t NATPMP_RESULT_NO_RESOURCES = 4;
@@ -144,6 +147,8 @@ constexpr size_t PCP_MAP_EXTERNAL_IP_OFS = 20;
//! Result code representing success (RFC6887 7.4), shared with NAT-PMP.
constexpr uint8_t PCP_RESULT_SUCCESS = NATPMP_RESULT_SUCCESS;
+//! Result code representing not authorized (RFC6887 7.4), shared with NAT-PMP.
+constexpr uint8_t PCP_RESULT_NOT_AUTHORIZED = NATPMP_RESULT_NOT_AUTHORIZED;
//! Result code representing lack of resources (RFC6887 7.4).
constexpr uint8_t PCP_RESULT_NO_RESOURCES = 8;
@@ -374,7 +379,16 @@ std::variant<MappingResult, MappingError> NATPMPRequestPortMap(const CNetAddr &g
Assume(response.size() >= NATPMP_MAP_RESPONSE_SIZE);
uint16_t result_code = ReadBE16(response.data() + NATPMP_RESPONSE_HDR_RESULT_OFS);
if (result_code != NATPMP_RESULT_SUCCESS) {
- LogWarning("natpmp: Port mapping failed with result %s\n", NATPMPResultString(result_code));
+ if (result_code == NATPMP_RESULT_NOT_AUTHORIZED) {
+ static std::atomic<bool> warned{false};
+ if (!warned.exchange(true)) {
+ LogWarning("natpmp: Port mapping failed with result %s\n", NATPMPResultString(result_code));
+ } else {
+ LogDebug(BCLog::NET, "natpmp: Port mapping failed with result %s\n", NATPMPResultString(result_code));
+ }
+ } else {
+ LogWarning("natpmp: Port mapping failed with result %s\n", NATPMPResultString(result_code));
+ }
if (result_code == NATPMP_RESULT_NO_RESOURCES) {
return MappingError::NO_RESOURCES;
}
@@ -508,7 +522,16 @@ std::variant<MappingResult, MappingError> PCPRequestPortMap(const PCPMappingNonc
uint16_t external_port = ReadBE16(response.data() + PCP_HDR_SIZE + PCP_MAP_EXTERNAL_PORT_OFS);
CNetAddr external_addr{PCPUnwrapAddress(response.subspan(PCP_HDR_SIZE + PCP_MAP_EXTERNAL_IP_OFS, ADDR_IPV6_SIZE))};
if (result_code != PCP_RESULT_SUCCESS) {
- LogWarning("pcp: Mapping failed with result %s\n", PCPResultString(result_code));
+ if (result_code == PCP_RESULT_NOT_AUTHORIZED) {
+ static std::atomic<bool> warned{false};
+ if (!warned.exchange(true)) {
+ LogWarning("pcp: Mapping failed with result %s\n", PCPResultString(result_code));
+ } else {
+ LogDebug(BCLog::NET, "pcp: Mapping failed with result %s\n", PCPResultString(result_code));
+ }
+ } else {
+ LogWarning("pcp: Mapping failed with result %s\n", PCPResultString(result_code));
+ }
if (result_code == PCP_RESULT_NO_RESOURCES) {
return MappingError::NO_RESOURCES;
}
Why this scored 15/100
Community notes
Notes can correct, qualify, or add evidence to the AI analysis. Every note shown here has been validated by a human moderator.
The AI analysis stands alone for now. Submit a note if you can add evidence or important context.