From afea2af1391314be0e5caaa0125c884da2405316 Mon Sep 17 00:00:00 2001 From: ANAVHEOBA Date: Fri, 19 Dec 2025 11:35:00 -0500 Subject: [PATCH] net: reduce log level for PCP/NAT-PMP NOT_AUTHORIZED failures Users running on home networks with routers that don't support PCP (Port Control Protocol) or NAT-PMP port mapping receive frequent warning-level log messages every few minutes: "pcp: Mapping failed with result NOT_AUTHORIZED (code 2)" This is expected behavior for many consumer routers that have PCP disabled by default, not an actionable error. Add explicit constants for the NOT_AUTHORIZED result code (value 2) for both NAT-PMP and PCP protocols. Log the first NOT_AUTHORIZED failure at warning level for visibility, then downgrade subsequent occurrences to LogDebug to avoid log noise. Other failure types continue to warn unconditionally. Fixes #34114 Co-authored-by: willcl-ark --- src/common/pcp.cpp | 27 +++++++++++++++++++++++++-- 1 file changed, 25 insertions(+), 2 deletions(-) diff --git a/src/common/pcp.cpp b/src/common/pcp.cpp index 4864136b840..a640b823f9c 100644 --- a/src/common/pcp.cpp +++ b/src/common/pcp.cpp @@ -4,6 +4,7 @@ #include +#include #include #include #include @@ -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 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 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 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 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; }