From 22e08353a66add1ebb95b7ee7ce533892f65046e Mon Sep 17 00:00:00 2001 From: Masakazu Kitajo Date: Thu, 5 Feb 2026 21:53:03 -0700 Subject: [PATCH 01/10] Add support for PP2_SUBTYPE_SSL_CIPHER --- include/iocore/net/ProxyProtocol.h | 1 + src/iocore/net/ProxyProtocol.cc | 60 +++++++++++++++++++ .../net/unit_tests/test_ProxyProtocol.cc | 8 ++- 3 files changed, 67 insertions(+), 2 deletions(-) diff --git a/include/iocore/net/ProxyProtocol.h b/include/iocore/net/ProxyProtocol.h index 2cc4848dfb2..a5f589225ee 100644 --- a/include/iocore/net/ProxyProtocol.h +++ b/include/iocore/net/ProxyProtocol.h @@ -86,6 +86,7 @@ class ProxyProtocol void set_ipv6_addrs(const in6_addr &src_addr, uint16_t src_port, const in6_addr &dst_addr, uint16_t dst_port); std::optional get_tlv(const uint8_t tlvCode) const; + std::optional get_tlv_ssl_cipher() const; ProxyProtocolVersion version = ProxyProtocolVersion::UNDEFINED; uint16_t ip_family = AF_UNSPEC; diff --git a/src/iocore/net/ProxyProtocol.cc b/src/iocore/net/ProxyProtocol.cc index 0422e707717..38d4ae99087 100644 --- a/src/iocore/net/ProxyProtocol.cc +++ b/src/iocore/net/ProxyProtocol.cc @@ -547,6 +547,66 @@ ProxyProtocol::get_tlv(const uint8_t tlvCode) const return std::nullopt; } +/* + * PP2_TYPE_SSL + * struct pp2_tlv_ssl { + * uint8_t client; + * uint32_t verify; + * struct pp2_tlv sub_tlv[0]; + * }; + */ + +std::optional +ProxyProtocol::get_tlv_ssl_cipher() const +{ + if (auto v = tlv.find(PP2_TYPE_SSL); v != tlv.end() && v->second.length() != 0) { + auto ssl = v->second; + + // Is the client connected over TLS + if ((ssl.data()[0] & 0x01) == 0) { + // Not over TLS + return std::nullopt; + } + + // Find PP2_SUBTYPE_SSL_CIPHER + uint16_t len = ssl.length(); + const char *p = ssl.data() + 5; // Skip client (uint8_t) + verify (uint32_t) + const char *end = p + len; + while (p != end) { + if (end - p < 3) { + // The size of a sub TLV entry must be 3 bytes or more + Dbg(dbg_ctl_proxyprotocol_v2, "Remaining data (%ld bytes) is not enough for a sub TLV field", end - p); + return std::nullopt; + } + + // Type + uint8_t type = *p; + p += 1; + + // Length + uint16_t length = ntohs(*reinterpret_cast(p)); + p += 2; + + // Value + if (end - p < length) { + // Does not have enough data + Dbg(dbg_ctl_proxyprotocol_v2, "Remaining data (%ld bytes) is not enough for a TLV field (ID:%u LEN:%hu)", end - p, type, + length); + return std::nullopt; + } + + // Found it? + if (type == PP2_SUBTYPE_SSL_CIPHER) { + Dbg(dbg_ctl_proxyprotocol, "TLV: ID=%u LEN=%hu", type, length); + return std::string_view(p, length); + } + + p += length; + } + } + return std::nullopt; +} + int ProxyProtocol::set_additional_data(std::string_view data) { diff --git a/src/iocore/net/unit_tests/test_ProxyProtocol.cc b/src/iocore/net/unit_tests/test_ProxyProtocol.cc index 70ead688be0..3f7fb526a6c 100644 --- a/src/iocore/net/unit_tests/test_ProxyProtocol.cc +++ b/src/iocore/net/unit_tests/test_ProxyProtocol.cc @@ -303,13 +303,15 @@ TEST_CASE("PROXY Protocol v2 Parser", "[ProxyProtocol][ProxyProtocolv2]") 0x55, 0x49, 0x54, 0x0A, ///< 0x21, ///< version & command 0x11, ///< protocol & family - 0x00, 0x17, ///< len + 0x00, 0x25, ///< len 0xC0, 0x00, 0x02, 0x01, ///< src_addr 0xC6, 0x33, 0x64, 0x01, ///< dst_addr 0xC3, 0x50, ///< src_port 0x01, 0xBB, ///< dst_port 0x01, 0x00, 0x02, 0x68, 0x32, /// PP2_TYPE_ALPN (h2) - 0x02, 0x00, 0x03, 0x61, 0x62, 0x63 /// PP2_TYPE_AUTHORITY (abc) + 0x02, 0x00, 0x03, 0x61, 0x62, 0x63, /// PP2_TYPE_AUTHORITY (abc) + 0x20, 0x00, 0x0B, 0x01, 0x00, 0x00, 0x00, 0x00, /// PP2_TYPE_SSL (client=0x01, verify=0) + 0x23, 0x00, 0x03, 0x58, 0x59, 0x5A, /// PP2_SUBTYPE_SSL_CIPHER (XYZ) }; swoc::TextView tv(reinterpret_cast(raw_data), sizeof(raw_data)); @@ -327,6 +329,8 @@ TEST_CASE("PROXY Protocol v2 Parser", "[ProxyProtocol][ProxyProtocolv2]") CHECK(pp_info.tlv[PP2_TYPE_ALPN] == "h2"); CHECK(pp_info.tlv[PP2_TYPE_AUTHORITY] == "abc"); + + CHECK(pp_info.get_tlv_ssl_cipher() == "XYZ"); } SECTION("TLVs with extra data") From 2df7eef67beb82ca3cc183204cfd584ff81b9653 Mon Sep 17 00:00:00 2001 From: Masakazu Kitajo Date: Thu, 5 Feb 2026 22:12:27 -0700 Subject: [PATCH 02/10] Add pptc log field for PP2_SUBTYPE_SSL_CIPHER --- doc/admin-guide/logging/formatting.en.rst | 2 ++ include/proxy/logging/LogAccess.h | 1 + src/proxy/logging/Log.cc | 5 +++++ src/proxy/logging/LogAccess.cc | 17 +++++++++++++++++ 4 files changed, 25 insertions(+) diff --git a/doc/admin-guide/logging/formatting.en.rst b/doc/admin-guide/logging/formatting.en.rst index bac1fbeeb68..9b34fe312e0 100644 --- a/doc/admin-guide/logging/formatting.en.rst +++ b/doc/admin-guide/logging/formatting.en.rst @@ -532,6 +532,8 @@ ppd Proxy Protocol Destination IP received via Proxy Protocol context from the Dest IP to the |TS| ppa Proxy Protocol The Authority TLV from Proxy Protocol context from the LB Authority to the |TS| +pptc Proxy Protocol The TLS cipher from Proxy Protocol context from the LB + Authority to the |TS| ===== ============== ========================================================== .. note:: diff --git a/include/proxy/logging/LogAccess.h b/include/proxy/logging/LogAccess.h index 0cdd6e1098c..32c505300d5 100644 --- a/include/proxy/logging/LogAccess.h +++ b/include/proxy/logging/LogAccess.h @@ -270,6 +270,7 @@ class LogAccess int marshal_proxy_protocol_src_ip(char *); // STR int marshal_proxy_protocol_dst_ip(char *); // STR int marshal_proxy_protocol_authority(char *); // STR + int marshal_proxy_protocol_tls_cipher(char *); // STR // named fields from within a http header // diff --git a/src/proxy/logging/Log.cc b/src/proxy/logging/Log.cc index 35d2c871874..89a8397b650 100644 --- a/src/proxy/logging/Log.cc +++ b/src/proxy/logging/Log.cc @@ -1034,6 +1034,11 @@ Log::init_fields() global_field_list.add(field, false); field_symbol_hash.emplace("ppa", field); + field = new LogField("proxy_protocol_tls_cipher", "pptc", LogField::STRING, &LogAccess::marshal_proxy_protocol_tls_cipher, + &LogAccess::unmarshal_str); + global_field_list.add(field, false); + field_symbol_hash.emplace("pptc", field); + field = new LogField("version_build_number", "vbn", LogField::STRING, &LogAccess::marshal_version_build_number, &LogAccess::unmarshal_str); global_field_list.add(field, false); diff --git a/src/proxy/logging/LogAccess.cc b/src/proxy/logging/LogAccess.cc index 9c0ce48bd48..615e845012d 100644 --- a/src/proxy/logging/LogAccess.cc +++ b/src/proxy/logging/LogAccess.cc @@ -1664,6 +1664,23 @@ LogAccess::marshal_proxy_protocol_authority(char *buf) return len; } +int +LogAccess::marshal_proxy_protocol_tls_cipher(char *buf) +{ + int len = INK_MIN_ALIGN; + + if (m_http_sm) { + if (auto cipher = m_http_sm->t_state.pp_info.get_tlv_ssl_cipher(); cipher) { + len = padded_length(cipher->size() + 1); + if (buf) { + marshal_str(buf, cipher->data(), len); + buf[cipher->size()] = '\0'; + } + } + } + return len; +} + /*------------------------------------------------------------------------- -------------------------------------------------------------------------*/ int From b8b2c2b3dcb97cec05c5c561fb5166a6c7c6ed24 Mon Sep 17 00:00:00 2001 From: Masakazu Kitajo Date: Fri, 6 Feb 2026 10:43:10 -0700 Subject: [PATCH 03/10] Add support for PP2_SUBTYPE_SSL_VERSION --- include/iocore/net/ProxyProtocol.h | 3 +++ src/iocore/net/ProxyProtocol.cc | 22 +++++++++++++++---- .../net/unit_tests/test_ProxyProtocol.cc | 6 +++-- 3 files changed, 25 insertions(+), 6 deletions(-) diff --git a/include/iocore/net/ProxyProtocol.h b/include/iocore/net/ProxyProtocol.h index a5f589225ee..c8504f24b0f 100644 --- a/include/iocore/net/ProxyProtocol.h +++ b/include/iocore/net/ProxyProtocol.h @@ -86,6 +86,7 @@ class ProxyProtocol void set_ipv6_addrs(const in6_addr &src_addr, uint16_t src_port, const in6_addr &dst_addr, uint16_t dst_port); std::optional get_tlv(const uint8_t tlvCode) const; + std::optional get_tlv_ssl_version() const; std::optional get_tlv_ssl_cipher() const; ProxyProtocolVersion version = ProxyProtocolVersion::UNDEFINED; @@ -135,6 +136,8 @@ class ProxyProtocol private: std::string additional_data; + + std::optional _get_tlv_ssl_subtype(int subtype) const; }; const size_t PPv1_CONNECTION_HEADER_LEN_MAX = 108; diff --git a/src/iocore/net/ProxyProtocol.cc b/src/iocore/net/ProxyProtocol.cc index 38d4ae99087..afad67a7b1c 100644 --- a/src/iocore/net/ProxyProtocol.cc +++ b/src/iocore/net/ProxyProtocol.cc @@ -557,7 +557,7 @@ ProxyProtocol::get_tlv(const uint8_t tlvCode) const */ std::optional -ProxyProtocol::get_tlv_ssl_cipher() const +ProxyProtocol::_get_tlv_ssl_subtype(int subtype) const { if (auto v = tlv.find(PP2_TYPE_SSL); v != tlv.end() && v->second.length() != 0) { auto ssl = v->second; @@ -568,10 +568,10 @@ ProxyProtocol::get_tlv_ssl_cipher() const return std::nullopt; } - // Find PP2_SUBTYPE_SSL_CIPHER + // Find the given subtype uint16_t len = ssl.length(); const char *p = ssl.data() + 5; // Skip client (uint8_t) + verify (uint32_t) - const char *end = p + len; + const char *end = p + len + 1; while (p != end) { if (end - p < 3) { // The size of a sub TLV entry must be 3 bytes or more @@ -596,7 +596,7 @@ ProxyProtocol::get_tlv_ssl_cipher() const } // Found it? - if (type == PP2_SUBTYPE_SSL_CIPHER) { + if (type == subtype) { Dbg(dbg_ctl_proxyprotocol, "TLV: ID=%u LEN=%hu", type, length); return std::string_view(p, length); } @@ -607,6 +607,20 @@ ProxyProtocol::get_tlv_ssl_cipher() const return std::nullopt; } +std::optional +ProxyProtocol::get_tlv_ssl_version() const +{ + // The specification only says "the US-ASCII string representation of the TLS version". + // HAProxy sends a string returned by SSL_get_version. + return this->_get_tlv_ssl_subtype(PP2_SUBTYPE_SSL_VERSION); +} + +std::optional +ProxyProtocol::get_tlv_ssl_cipher() const +{ + return this->_get_tlv_ssl_subtype(PP2_SUBTYPE_SSL_CIPHER); +} + int ProxyProtocol::set_additional_data(std::string_view data) { diff --git a/src/iocore/net/unit_tests/test_ProxyProtocol.cc b/src/iocore/net/unit_tests/test_ProxyProtocol.cc index 3f7fb526a6c..f50f6839c4b 100644 --- a/src/iocore/net/unit_tests/test_ProxyProtocol.cc +++ b/src/iocore/net/unit_tests/test_ProxyProtocol.cc @@ -303,15 +303,16 @@ TEST_CASE("PROXY Protocol v2 Parser", "[ProxyProtocol][ProxyProtocolv2]") 0x55, 0x49, 0x54, 0x0A, ///< 0x21, ///< version & command 0x11, ///< protocol & family - 0x00, 0x25, ///< len + 0x00, 0x2B, ///< len 0xC0, 0x00, 0x02, 0x01, ///< src_addr 0xC6, 0x33, 0x64, 0x01, ///< dst_addr 0xC3, 0x50, ///< src_port 0x01, 0xBB, ///< dst_port 0x01, 0x00, 0x02, 0x68, 0x32, /// PP2_TYPE_ALPN (h2) 0x02, 0x00, 0x03, 0x61, 0x62, 0x63, /// PP2_TYPE_AUTHORITY (abc) - 0x20, 0x00, 0x0B, 0x01, 0x00, 0x00, 0x00, 0x00, /// PP2_TYPE_SSL (client=0x01, verify=0) + 0x20, 0x00, 0x11, 0x01, 0x00, 0x00, 0x00, 0x00, /// PP2_TYPE_SSL (client=0x01, verify=0) 0x23, 0x00, 0x03, 0x58, 0x59, 0x5A, /// PP2_SUBTYPE_SSL_CIPHER (XYZ) + 0x21, 0x00, 0x03, 0x54, 0x4C, 0x53, /// PP2_SUBTYPE_SSL_VERSION (TLS) }; swoc::TextView tv(reinterpret_cast(raw_data), sizeof(raw_data)); @@ -331,6 +332,7 @@ TEST_CASE("PROXY Protocol v2 Parser", "[ProxyProtocol][ProxyProtocolv2]") CHECK(pp_info.tlv[PP2_TYPE_AUTHORITY] == "abc"); CHECK(pp_info.get_tlv_ssl_cipher() == "XYZ"); + CHECK(pp_info.get_tlv_ssl_version() == "TLS"); } SECTION("TLVs with extra data") From 5353709da237c27dca27348991064ff962b26426 Mon Sep 17 00:00:00 2001 From: Masakazu Kitajo Date: Fri, 6 Feb 2026 10:51:39 -0700 Subject: [PATCH 04/10] Add pptv log field for PP2_SUBTYPE_SSL_VERSION --- doc/admin-guide/logging/formatting.en.rst | 2 ++ include/proxy/logging/LogAccess.h | 1 + src/proxy/logging/Log.cc | 5 +++++ src/proxy/logging/LogAccess.cc | 17 +++++++++++++++++ 4 files changed, 25 insertions(+) diff --git a/doc/admin-guide/logging/formatting.en.rst b/doc/admin-guide/logging/formatting.en.rst index 9b34fe312e0..ca9543971e7 100644 --- a/doc/admin-guide/logging/formatting.en.rst +++ b/doc/admin-guide/logging/formatting.en.rst @@ -534,6 +534,8 @@ ppa Proxy Protocol The Authority TLV from Proxy Protocol context from the LB Authority to the |TS| pptc Proxy Protocol The TLS cipher from Proxy Protocol context from the LB Authority to the |TS| +pptv Proxy Protocol The TLS version from Proxy Protocol context from the LB + Authority to the |TS| ===== ============== ========================================================== .. note:: diff --git a/include/proxy/logging/LogAccess.h b/include/proxy/logging/LogAccess.h index 32c505300d5..7cdf8ed48be 100644 --- a/include/proxy/logging/LogAccess.h +++ b/include/proxy/logging/LogAccess.h @@ -271,6 +271,7 @@ class LogAccess int marshal_proxy_protocol_dst_ip(char *); // STR int marshal_proxy_protocol_authority(char *); // STR int marshal_proxy_protocol_tls_cipher(char *); // STR + int marshal_proxy_protocol_tls_version(char *); // STR // named fields from within a http header // diff --git a/src/proxy/logging/Log.cc b/src/proxy/logging/Log.cc index 89a8397b650..50e975e2849 100644 --- a/src/proxy/logging/Log.cc +++ b/src/proxy/logging/Log.cc @@ -1039,6 +1039,11 @@ Log::init_fields() global_field_list.add(field, false); field_symbol_hash.emplace("pptc", field); + field = new LogField("proxy_protocol_tls_version", "pptv", LogField::STRING, &LogAccess::marshal_proxy_protocol_tls_version, + &LogAccess::unmarshal_str); + global_field_list.add(field, false); + field_symbol_hash.emplace("pptv", field); + field = new LogField("version_build_number", "vbn", LogField::STRING, &LogAccess::marshal_version_build_number, &LogAccess::unmarshal_str); global_field_list.add(field, false); diff --git a/src/proxy/logging/LogAccess.cc b/src/proxy/logging/LogAccess.cc index 615e845012d..49095d10d82 100644 --- a/src/proxy/logging/LogAccess.cc +++ b/src/proxy/logging/LogAccess.cc @@ -1681,6 +1681,23 @@ LogAccess::marshal_proxy_protocol_tls_cipher(char *buf) return len; } +int +LogAccess::marshal_proxy_protocol_tls_version(char *buf) +{ + int len = INK_MIN_ALIGN; + + if (m_http_sm) { + if (auto version = m_http_sm->t_state.pp_info.get_tlv_ssl_version(); version) { + len = padded_length(version->size() + 1); + if (buf) { + marshal_str(buf, version->data(), len); + buf[version->size()] = '\0'; + } + } + } + return len; +} + /*------------------------------------------------------------------------- -------------------------------------------------------------------------*/ int From 9d01982327a1e931baa2253984164f81e1273b71 Mon Sep 17 00:00:00 2001 From: Masakazu Kitajo Date: Mon, 9 Feb 2026 16:11:59 -0700 Subject: [PATCH 05/10] Fix copy pasta in documentation --- doc/admin-guide/logging/formatting.en.rst | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/doc/admin-guide/logging/formatting.en.rst b/doc/admin-guide/logging/formatting.en.rst index ca9543971e7..b85e6407ada 100644 --- a/doc/admin-guide/logging/formatting.en.rst +++ b/doc/admin-guide/logging/formatting.en.rst @@ -533,9 +533,9 @@ ppd Proxy Protocol Destination IP received via Proxy Protocol context from the ppa Proxy Protocol The Authority TLV from Proxy Protocol context from the LB Authority to the |TS| pptc Proxy Protocol The TLS cipher from Proxy Protocol context from the LB - Authority to the |TS| + TLS Cipher to the |TS| pptv Proxy Protocol The TLS version from Proxy Protocol context from the LB - Authority to the |TS| + TLS version to the |TS| ===== ============== ========================================================== .. note:: From 9b438036af868114bcb0457685fedb232cc35078 Mon Sep 17 00:00:00 2001 From: Masakazu Kitajo Date: Mon, 9 Feb 2026 16:17:25 -0700 Subject: [PATCH 06/10] Change parameter type --- include/iocore/net/ProxyProtocol.h | 2 +- src/iocore/net/ProxyProtocol.cc | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/include/iocore/net/ProxyProtocol.h b/include/iocore/net/ProxyProtocol.h index c8504f24b0f..5c73019144d 100644 --- a/include/iocore/net/ProxyProtocol.h +++ b/include/iocore/net/ProxyProtocol.h @@ -137,7 +137,7 @@ class ProxyProtocol private: std::string additional_data; - std::optional _get_tlv_ssl_subtype(int subtype) const; + std::optional _get_tlv_ssl_subtype(uint8_t subtype) const; }; const size_t PPv1_CONNECTION_HEADER_LEN_MAX = 108; diff --git a/src/iocore/net/ProxyProtocol.cc b/src/iocore/net/ProxyProtocol.cc index afad67a7b1c..eae3b1aebbd 100644 --- a/src/iocore/net/ProxyProtocol.cc +++ b/src/iocore/net/ProxyProtocol.cc @@ -557,7 +557,7 @@ ProxyProtocol::get_tlv(const uint8_t tlvCode) const */ std::optional -ProxyProtocol::_get_tlv_ssl_subtype(int subtype) const +ProxyProtocol::_get_tlv_ssl_subtype(uint8_t subtype) const { if (auto v = tlv.find(PP2_TYPE_SSL); v != tlv.end() && v->second.length() != 0) { auto ssl = v->second; From 7c37c1c47a31df9f36efd82427b8d69bc5f95d39 Mon Sep 17 00:00:00 2001 From: Masakazu Kitajo Date: Mon, 9 Feb 2026 16:46:49 -0700 Subject: [PATCH 07/10] Fix off by one error --- src/iocore/net/ProxyProtocol.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/iocore/net/ProxyProtocol.cc b/src/iocore/net/ProxyProtocol.cc index eae3b1aebbd..c81bd80cff8 100644 --- a/src/iocore/net/ProxyProtocol.cc +++ b/src/iocore/net/ProxyProtocol.cc @@ -571,7 +571,7 @@ ProxyProtocol::_get_tlv_ssl_subtype(uint8_t subtype) const // Find the given subtype uint16_t len = ssl.length(); const char *p = ssl.data() + 5; // Skip client (uint8_t) + verify (uint32_t) - const char *end = p + len + 1; + const char *end = p + len; while (p != end) { if (end - p < 3) { // The size of a sub TLV entry must be 3 bytes or more From 59a521e71f3d7f8f93623a4a9d2103e310fb3b13 Mon Sep 17 00:00:00 2001 From: Masakazu Kitajo Date: Mon, 9 Feb 2026 17:34:27 -0700 Subject: [PATCH 08/10] Add a length check --- src/iocore/net/ProxyProtocol.cc | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/src/iocore/net/ProxyProtocol.cc b/src/iocore/net/ProxyProtocol.cc index c81bd80cff8..96939412c8c 100644 --- a/src/iocore/net/ProxyProtocol.cc +++ b/src/iocore/net/ProxyProtocol.cc @@ -568,10 +568,14 @@ ProxyProtocol::_get_tlv_ssl_subtype(uint8_t subtype) const return std::nullopt; } + if (ssl.length() < 5) { + return std::nullopt; + } + // Find the given subtype uint16_t len = ssl.length(); const char *p = ssl.data() + 5; // Skip client (uint8_t) + verify (uint32_t) - const char *end = p + len; + const char *end = ssl.data() + len; while (p != end) { if (end - p < 3) { // The size of a sub TLV entry must be 3 bytes or more From dd36d63d0dd25a7170ffaf710647339bf739b85d Mon Sep 17 00:00:00 2001 From: Masakazu Kitajo Date: Tue, 10 Feb 2026 12:41:08 -0700 Subject: [PATCH 09/10] Print the default value if data sources are unavailable --- src/proxy/logging/LogAccess.cc | 16 ++++++++++++---- 1 file changed, 12 insertions(+), 4 deletions(-) diff --git a/src/proxy/logging/LogAccess.cc b/src/proxy/logging/LogAccess.cc index 49095d10d82..908ec8c22ff 100644 --- a/src/proxy/logging/LogAccess.cc +++ b/src/proxy/logging/LogAccess.cc @@ -1673,8 +1673,12 @@ LogAccess::marshal_proxy_protocol_tls_cipher(char *buf) if (auto cipher = m_http_sm->t_state.pp_info.get_tlv_ssl_cipher(); cipher) { len = padded_length(cipher->size() + 1); if (buf) { - marshal_str(buf, cipher->data(), len); - buf[cipher->size()] = '\0'; + marshal_mem(buf, cipher->data(), cipher->size(), len); + } + } else { + if (buf) { + // This prints the default value ("-") + marshal_mem(buf, nullptr, 0, len); } } } @@ -1690,8 +1694,12 @@ LogAccess::marshal_proxy_protocol_tls_version(char *buf) if (auto version = m_http_sm->t_state.pp_info.get_tlv_ssl_version(); version) { len = padded_length(version->size() + 1); if (buf) { - marshal_str(buf, version->data(), len); - buf[version->size()] = '\0'; + marshal_mem(buf, version->data(), version->size(), len); + } + } else { + if (buf) { + // This prints the default value ("-") + marshal_mem(buf, nullptr, 0, len); } } } From 2ac2e9fe68fc4e86dc87ec1ae7f483b0d65a4938 Mon Sep 17 00:00:00 2001 From: Masakazu Kitajo Date: Tue, 10 Feb 2026 15:00:48 -0700 Subject: [PATCH 10/10] Add a test case --- .../net/unit_tests/test_ProxyProtocol.cc | 32 +++++++++++++++++++ 1 file changed, 32 insertions(+) diff --git a/src/iocore/net/unit_tests/test_ProxyProtocol.cc b/src/iocore/net/unit_tests/test_ProxyProtocol.cc index f50f6839c4b..53958b30b27 100644 --- a/src/iocore/net/unit_tests/test_ProxyProtocol.cc +++ b/src/iocore/net/unit_tests/test_ProxyProtocol.cc @@ -335,6 +335,38 @@ TEST_CASE("PROXY Protocol v2 Parser", "[ProxyProtocol][ProxyProtocolv2]") CHECK(pp_info.get_tlv_ssl_version() == "TLS"); } + SECTION("TLVs with PP2_TYPE_SSL but SSL is unused") + { + uint8_t raw_data[] = { + 0x0D, 0x0A, 0x0D, 0x0A, 0x00, 0x0D, 0x0A, 0x51, ///< preface + 0x55, 0x49, 0x54, 0x0A, ///< + 0x21, ///< version & command + 0x11, ///< protocol & family + 0x00, 0x14, ///< len + 0xC0, 0x00, 0x02, 0x01, ///< src_addr + 0xC6, 0x33, 0x64, 0x01, ///< dst_addr + 0xC3, 0x50, ///< src_port + 0x01, 0xBB, ///< dst_port + 0x20, 0x00, 0x05, 0x00, 0x00, 0x00, 0x00, 0x00, /// PP2_TYPE_SSL (client=0x00, verify=0) + }; + + swoc::TextView tv(reinterpret_cast(raw_data), sizeof(raw_data)); + + ProxyProtocol pp_info; + REQUIRE(proxy_protocol_parse(&pp_info, tv) == tv.size()); + + REQUIRE(ats_ip_pton("192.0.2.1:50000", src_addr) == 0); + REQUIRE(ats_ip_pton("198.51.100.1:443", dst_addr) == 0); + + CHECK(pp_info.version == ProxyProtocolVersion::V2); + CHECK(pp_info.ip_family == AF_INET); + CHECK(pp_info.src_addr == src_addr); + CHECK(pp_info.dst_addr == dst_addr); + + CHECK(pp_info.get_tlv_ssl_cipher().has_value() == false); + CHECK(pp_info.get_tlv_ssl_version().has_value() == false); + } + SECTION("TLVs with extra data") { uint8_t raw_data[] = {